Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client side js mods. Modding! #255

Open
wants to merge 9 commits into
base: next
Choose a base branch
from
Open

Client side js mods. Modding! #255

wants to merge 9 commits into from

Conversation

zardoy
Copy link
Owner

@zardoy zardoy commented Jan 28, 2025

PR Type

Enhancement, Tests

fixes #314


Description

  • Introduced a client-side modding system with mod management.

    • Added database support for mods and repositories.
    • Implemented mod activation, installation, and updates.
  • Enhanced UI with mod-related features.

    • Added a "Client Mods" button in the options menu.
    • Created a dedicated mods page for managing mods.
  • Added configuration options for mod support and updates.

  • Included a new HTML configuration page for client settings.


Changes walkthrough 📝

Relevant files
Configuration changes
1 files
rsbuild.config.ts
Added support for copying `config.html` to the build output.
+1/-0     
Enhancement
8 files
clientMods.ts
Implemented client-side modding system with database and activation
logic.
+295/-0 
index.ts
Integrated mod startup logic into the application initialization.
+2/-0     
optionsGuiScheme.tsx
Added "Client Mods" button to the options menu.                   
+7/-0     
optionsStorage.ts
Added mod-related configuration options.                                 
+3/-0     
ModsPage.tsx
Created a new mods management page.                                           
+13/-0   
storageProvider.ts
Added storage support for mod update checks.                         
+1/-0     
reactUi.tsx
Integrated the mods page into the React UI structure.       
+2/-0     
config.html
Added a new HTML configuration page for client settings. 
+25/-0   

Need help?
  • Type /help how to ... in the comments thread for any questions about Qodo Merge usage.
  • Check out the documentation for more information.
  • Summary by CodeRabbit

    • New Features

      • Introduced a new configuration interface with interactive elements for managing settings.
      • Expanded client mod functionality, including capabilities for installation, updates, and removal.
      • Enhanced the user interface with a dynamic button displaying mod counts that opens a detailed modal view.
      • Improved application startup by integrating the mod management system.
      • Added a new component for managing and displaying mods with user interaction options.
      • Implemented a new button in the world creation process for selecting server plugins.
      • Introduced new properties for mod management configuration, including auto-update options.
    • Chores

      • Updated the build process to include the new configuration interface in the deployment bundle.
      • Updated dependency version for flying-squid.

    Copy link

    codesandbox bot commented Jan 28, 2025

    Review or Edit in CodeSandbox

    Open the branch in Web EditorVS CodeInsiders

    Open Preview

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
    🧪 No relevant tests
    🔒 Security concerns

    Remote Code Execution:
    The mod system allows downloading and executing arbitrary JavaScript code from remote sources without proper validation or sandboxing (src/clientMods.ts lines 139-144). This could allow malicious code to be executed in the context of the application. Consider implementing code signing, content security policies, and proper sandboxing mechanisms.

    ⚡ Recommended focus areas for review

    Security Risk

    The mod installation process loads and executes arbitrary JavaScript code from mod repositories without proper validation or sandboxing, which could allow malicious code execution.

    const blob = new Blob([mod.scriptMainUnstable], { type: 'application/javascript' })
    const url = URL.createObjectURL(blob)
    try {
      const module = await import(url)
      module.default?.(structuredClone(mod))
      window.loadedMods[mod.name] = module
    Incomplete Implementation

    The configuration page has non-functional buttons and lacks proper event handlers for critical data management operations.

    <button>Reset all settings</button>
    <button>Remove all user data (worlds, resourcepacks)</button>
    <button>Remove all mods</button>
    <button>Remove all mod repositories</button>
    Error Handling

    The mod activation and installation functions lack comprehensive error handling and recovery mechanisms, which could lead to unstable application state.

    const activateMod = async (mod: ClientMod, reason: string) => {
      console.debug(`Activating mod ${mod.name} (${reason})...`)
      if (window.loadedMods[mod.name]) {
        console.warn(`Mod is ${mod.name} already loaded, skipping activation...`)
        return false
      }
      if (mod.stylesGlobal) {
        const style = document.createElement('style')
        style.textContent = mod.stylesGlobal
        style.id = `mod-${mod.name}`
        document.head.appendChild(style)
      }
      if (mod.scriptMainUnstable) {
        const blob = new Blob([mod.scriptMainUnstable], { type: 'application/javascript' })
        const url = URL.createObjectURL(blob)
        try {
          const module = await import(url)
          module.default?.(structuredClone(mod))
          window.loadedMods[mod.name] = module
        } catch (e) {
          console.error(`Error loading mod ${mod.name}:`, e)
        }
      }
      return true
    }

    Copy link

    qodo-merge-pro-for-open-source bot commented Jan 28, 2025

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Score
    Possible issue
    Prevent memory leaks in blob URLs

    Add error handling for the case when the blob URL creation fails. The current code
    could leak memory if URL.createObjectURL fails, as the blob URL is never revoked.

    src/clientMods.ts [139-148]

     const blob = new Blob([mod.scriptMainUnstable], { type: 'application/javascript' })
    -const url = URL.createObjectURL(blob)
    +let url
     try {
    +  url = URL.createObjectURL(blob)
       const module = await import(url)
       module.default?.(structuredClone(mod))
       window.loadedMods[mod.name] = module
     } catch (e) {
       console.error(`Error loading mod ${mod.name}:`, e)
    +} finally {
    +  if (url) URL.revokeObjectURL(url)
     }
    • Apply this suggestion
    Suggestion importance[1-10]: 8

    Why: The suggestion addresses a potential memory leak by properly cleaning up blob URLs. This is an important fix for resource management and preventing memory issues in long-running applications.

    8
    Add missing button functionality
    Suggestion Impact:The commit implemented onclick handlers for buttons as suggested, though with some differences. Only two buttons were kept (with one renamed), and the other buttons were commented out. The first button uses the suggested handler name, but the second uses a different function name (removeAllData instead of removeUserData).

    code diff:

    -        <button>Reset all settings</button>
    -        <button>Remove all user data (worlds, resourcepacks)</button>
    -        <button>Remove all mods</button>
    -        <button>Remove all mod repositories</button>
    +        <button onclick="removeSettings()">Reset all settings</button>
    +        <button onclick="removeAllData()">Remove all user data (but not mods or worlds)</button>
    +        <!-- <button>Remove all user data (worlds, resourcepacks)</button> -->
    +        <!-- <button>Remove all mods</button> -->
    +        <!-- <button>Remove all mod repositories</button> -->

    The buttons are defined but lack onclick handlers, making them non-functional. Add
    event handlers to implement the intended functionality for each button.

    assets/config.html [18-21]

     <div style="display: flex;gap: 10px;">
    -    <button>Reset all settings</button>
    -    <button>Remove all user data (worlds, resourcepacks)</button>
    -    <button>Remove all mods</button>
    -    <button>Remove all mod repositories</button>
    +    <button onclick="removeSettings()">Reset all settings</button>
    +    <button onclick="removeUserData()">Remove all user data (worlds, resourcepacks)</button>
    +    <button onclick="removeMods()">Remove all mods</button>
    +    <button onclick="removeModRepositories()">Remove all mod repositories</button>
     </div>

    [Suggestion has been applied]

    Suggestion importance[1-10]: 7

    Why: The suggestion fixes non-functional UI elements by adding necessary onclick handlers. This is important for user interaction and making the configuration interface work as intended.

    7
    Validate version strings before comparison

    Add validation for the mod version format before using semver.gt() comparison to
    prevent potential crashes with invalid version strings.

    src/clientMods.ts [200-201]

    -if (modExisting?.version && gt(mod.version, modExisting.version)) {
    +const isValidVersion = (v: string) => /^\d+\.\d+\.\d+/.test(v);
    +if (modExisting?.version && isValidVersion(mod.version) && isValidVersion(modExisting.version) && gt(mod.version, modExisting.version)) {
       modsUpdateStatus[mod.name] = [modExisting.version, mod.version]
    • Apply this suggestion
    Suggestion importance[1-10]: 7

    Why: The suggestion adds important input validation to prevent potential crashes when comparing version strings. This improves the robustness of the mod update system.

    7

    Copy link

    coderabbitai bot commented Mar 18, 2025

    Walkthrough

    This pull request introduces a new HTML configuration interface and integrates its inclusion into the build process. A new client mods module is added to manage modifications using IndexedDB, providing various CRUD operations and update checks. The startup routine now calls the mod initialization function. Additionally, the UI is enhanced with a custom button displaying mod status, a new modal component for mod details, and the corresponding import in the React UI setup.

    Changes

    Files Change Summary
    assets/config.html, rsbuild.config.ts Added a new config HTML file featuring management buttons and a JavaScript function to reset settings; updated the build routine to copy this file into the distribution folder.
    src/clientMods.ts, src/index.ts Introduced a new module for client mods with interfaces and functions for IndexedDB CRUD operations and mod update checks; updated index file to import and invoke the appStartup function.
    src/optionsGuiScheme.tsx, src/react/ModsPage.tsx, src/reactUi.tsx Enhanced the UI with a custom button in the options scheme that displays mod counts, a new React modal component for displaying mod details, and a new import for the ModsPage component in the React UI.
    src/optionsStorage.ts, src/react/appStorageProvider.ts Expanded configuration options for mod management by adding properties to defaultOptions and StorageData types to track mod support and update behaviors.
    src/react/Input.tsx, src/react/Screen.tsx, src/react/SelectOption.tsx Improved input flexibility by modifying class handling and adding placeholder text capabilities to enhance user experience.
    src/react/mods.module.css, src/react/mods.module.css.d.ts Introduced a new CSS module and its TypeScript declaration for styling the mod interface, ensuring a cohesive design and type safety for CSS class names.
    src/core/progressReporter.ts Updated notification logic to include icons for better visual feedback.
    src/screens.css Added a new z-index property to the backdrop class to manage stacking context.
    src/defaultLocalServerOptions.js Introduced a new property pluginsFolder to the exported object, indicating a configuration option related to server's plugin management.
    src/react/CreateWorld.tsx, src/react/CreateWorldProvider.tsx Added functionality for managing server plugins during world creation, including a new button to fetch and select plugins, and modifications to handle plugin content retrieval and storage.
    package.json Updated the version of the flying-squid dependency to a newer version.

    Sequence Diagram(s)

    sequenceDiagram
        participant User
        participant ConfigPage
        participant BrowserStorage
        participant Browser
    
        User->>ConfigPage: Click "Reset Settings" button
        ConfigPage->>User: Prompt confirmation
        User-->>ConfigPage: Confirm reset
        ConfigPage->>BrowserStorage: Set 'options' key to {}
        BrowserStorage-->>ConfigPage: Acknowledge update
        ConfigPage->>Browser: Reload page
    
    Loading
    sequenceDiagram
        participant User
        participant OptionsUI
        participant ModsModal
        participant ClientMods
        participant DB[IndexedDB]
    
        User->>OptionsUI: Click mod count button
        OptionsUI->>ModsModal: Open mod details modal
        ModsModal->>ClientMods: Request mod data
        ClientMods->>DB: Retrieve mods and repo data
        DB-->>ClientMods: Return data
        ClientMods-->>ModsModal: Send mod information
        ModsModal-->>User: Display mod details
    
    Loading

    Assessment against linked issues

    Objective Addressed Explanation
    Implement mod management functionality (#314)

    Suggested labels

    Review effort 4/5

    Suggested reviewers

    • Phoenix616

    Poem

    I’m a rabbit in this codey glade,
    Hopping through mods that have been laid.
    Buttons bounce like carrots anew,
    Config pages bloom with each debut.
    In digital meadows I cheer and play,
    CodeRabbit hops on in a joyful way!
    🐰✨


    🪧 Tips

    Chat

    There are 3 ways to chat with CodeRabbit:

    • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
      • I pushed a fix in commit <commit_id>, please review it.
      • Generate unit testing code for this file.
      • Open a follow-up GitHub issue for this discussion.
    • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
      • @coderabbitai generate unit testing code for this file.
      • @coderabbitai modularize this function.
    • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
      • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
      • @coderabbitai read src/utils.ts and generate unit testing code.
      • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
      • @coderabbitai help me debug CodeRabbit configuration file.

    Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

    CodeRabbit Commands (Invoked using PR comments)

    • @coderabbitai pause to pause the reviews on a PR.
    • @coderabbitai resume to resume the paused reviews.
    • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
    • @coderabbitai full review to do a full review from scratch and review all the files again.
    • @coderabbitai summary to regenerate the summary of the PR.
    • @coderabbitai generate docstrings to generate docstrings for this PR.
    • @coderabbitai resolve resolve all the CodeRabbit review comments.
    • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
    • @coderabbitai help to get help.

    Other keywords and placeholders

    • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
    • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
    • Add @coderabbitai anywhere in the PR title to generate the title automatically.

    CodeRabbit Configuration File (.coderabbit.yaml)

    • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
    • Please see the configuration documentation for more information.
    • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

    Documentation and Community

    • Visit our Documentation for detailed information on how to use CodeRabbit.
    • Join our Discord Community to get help, request features, and share feedback.
    • Follow us on X/Twitter for updates and announcements.

    Copy link

    @coderabbitai coderabbitai bot left a comment

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Actionable comments posted: 6

    🧹 Nitpick comments (4)
    src/index.ts (1)

    1057-1057: Add error handling for mod initialization.

    The appStartup() function is called to initialize the client mods system, but errors aren't handled. Since this runs during application startup, uncaught exceptions could prevent the application from loading properly.

    -void appStartup()
    +void appStartup().catch(error => {
    +  console.error("Failed to initialize client mods:", error)
    +  showNotification("Mod System Error", "Failed to initialize the mod system. Some mods may not work properly.", true)
    +})
    assets/config.html (1)

    23-23: Consider adding a label/placeholder for the input field.
    A placeholder or label would improve clarity for what the user should input.

    src/optionsGuiScheme.tsx (1)

    214-219: Consider using reactive state to track loaded mods.
    Referencing window.loadedMods works, but if you want the button label to update automatically when mods change, moving loadedMods into a reactive store (similar to modsUpdateStatus) could help.

    src/clientMods.ts (1)

    53-56: Avoid using the delete operator for performance reasons.
    Per lint suggestions, assigning undefined may reduce the risk of de-optimizations. If removing these properties is essential, continue using delete, but be aware of potential performance implications.

    🧰 Tools
    🪛 Biome (1.9.4)

    [error] 53-53: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 54-54: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 55-55: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 56-56: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)

    📜 Review details

    Configuration used: CodeRabbit UI
    Review profile: CHILL
    Plan: Pro

    📥 Commits

    Reviewing files that changed from the base of the PR and between 2277020 and 69bfc1a.

    📒 Files selected for processing (7)
    • assets/config.html (1 hunks)
    • rsbuild.config.ts (1 hunks)
    • src/clientMods.ts (1 hunks)
    • src/index.ts (2 hunks)
    • src/optionsGuiScheme.tsx (2 hunks)
    • src/react/ModsPage.tsx (1 hunks)
    • src/reactUi.tsx (1 hunks)
    🧰 Additional context used
    🧬 Code Definitions (4)
    rsbuild.config.ts (1)
    scripts/build.js (1) (1)
    • fs (5-5)
    src/optionsGuiScheme.tsx (2)
    src/react/SelectOption.tsx (1) (1)
    • useSnapshot (89-176)
    src/clientMods.ts (1) (1)
    • modsUpdateStatus (162-162)
    src/index.ts (1)
    src/clientMods.ts (1) (1)
    • appStartup (152-160)
    src/clientMods.ts (1)
    src/optionsStorage.ts (1) (1)
    • options (186-191)
    🪛 Biome (1.9.4)
    src/clientMods.ts

    [error] 53-53: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 54-54: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 55-55: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 56-56: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)

    🪛 GitHub Check: build-and-deploy
    src/clientMods.ts

    [failure] 247-247:
    Property 'modsUpdatePeriodCheck' does not exist on type '{ renderDistance: number; keepChunksDistance: number; multiplayerRenderDistance: number; closeConfirmation: boolean; autoFullScreen: boolean; mouseRawInput: boolean; autoExitFullscreen: boolean; ... 78 more ...; highlightBlockColor: "auto" | "blue" | "classic"; }'.


    [failure] 245-245:
    Property 'modsAutoUpdate' does not exist on type '{ renderDistance: number; keepChunksDistance: number; multiplayerRenderDistance: number; closeConfirmation: boolean; autoFullScreen: boolean; mouseRawInput: boolean; autoExitFullscreen: boolean; ... 78 more ...; highlightBlockColor: "auto" | "blue" | "classic"; }'.


    [failure] 202-202:
    Property 'modsAutoUpdate' does not exist on type '{ renderDistance: number; keepChunksDistance: number; multiplayerRenderDistance: number; closeConfirmation: boolean; autoFullScreen: boolean; mouseRawInput: boolean; autoExitFullscreen: boolean; ... 78 more ...; highlightBlockColor: "auto" | "blue" | "classic"; }'.


    [failure] 6-6:
    Cannot find module './react/storageProvider' or its corresponding type declarations.

    🪛 GitHub Actions: CI
    src/clientMods.ts

    [error] 6-6: Cannot find module './react/storageProvider' or its corresponding type declarations.

    🔇 Additional comments (3)
    rsbuild.config.ts (1)

    176-176: Enhance build process to include config.html file.

    The addition correctly copies the config.html file from assets to the distribution directory, making it available for the client-side modding system. This follows the same pattern as other asset files.

    src/index.ts (1)

    100-100: New import for client mod functionality.

    The import adds the client mod module to the application, which implements the modding system mentioned in the PR description.

    src/optionsGuiScheme.tsx (1)

    17-17: Import statement looks fine.
    No concerns found with this new import of modsUpdateStatus.

    Copy link

    @coderabbitai coderabbitai bot left a comment

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Actionable comments posted: 0

    🧹 Nitpick comments (13)
    src/screens.css (2)

    16-21: Establishing Stacking Context for the Backdrop Element
    The addition of z-index: 12; to the .backdrop class correctly establishes a new stacking context, ensuring that modal or overlay elements relying on this style will appear above base content. However, note that the .fullscreen class also uses z-index: 12; if the intent is to layer these elements distinctly (for example, to have the fullscreen modal appear above the backdrop), you might consider assigning a higher z-index value to one of them to avoid potential overlay conflicts.


    16-19: Viewport Height Unit Consideration
    The use of height: 100dvh; ensures the backdrop covers the dynamic viewport height, which is beneficial for handling mobile browser UI changes. However, consider potential compatibility issues with browsers that do not fully support the dvh unit. Including a fallback such as 100vh might improve robustness across all target browsers.

    src/react/ModsPage.tsx (3)

    122-129: Consider using a more stable identifier than array index.

    The useMemo for allModsArray is well-implemented, but selecting mods by index could lead to issues if the array order changes (e.g., when filtering or sorting).

    - const [selectedModIndex, setSelectedModIndex] = useState<number | null>(null)
    + const [selectedModName, setSelectedModName] = useState<string | null>(null)
    
    - const selectedMod = selectedModIndex === null ? null : allModsArray[selectedModIndex]
    + const selectedMod = selectedModName === null ? null : allModsArray.find(mod => mod.name === selectedModName)
    
    // And then update the onClick handlers:
    - onClick={() => setSelectedModIndex(allModsArray.findIndex(m => m.name === mod.name))}
    + onClick={() => setSelectedModName(mod.name)}

    130-140: Good reactive data fetching, but consider adding loading state.

    The useEffect for fetching mods data when the modal is active is well implemented, but there's no explicit loading state handling.

    Consider adding a loading state and displaying a loading indicator:

    const [modsData, setModsData] = useState<ModsData | null>(null)
    + const [isLoading, setIsLoading] = useState(false)
    
    useEffect(() => {
      if (isModalActive) {
    +    setIsLoading(true)
        void getAllModsDisplayList().then(mods => {
          setModsData(mods)
          // Update selected mod index if needed
          if (selectedModIndex !== null && selectedModIndex < allModsArray.length) {
            setSelectedModIndex(selectedModIndex)
          }
    +      setIsLoading(false)
    +    }).catch(error => {
    +      console.error('Failed to load mods:', error)
    +      setIsLoading(false)
        })
      }
    }, [isModalActive, counter])

    179-304: Well-structured UI with responsive layout, but consider adding pagination.

    The Screen component is well utilized with appropriate styling. The UI is organized into clear sections with responsive layout handling. However, for repositories with many mods, consider adding pagination.

    You could implement pagination for large mod lists to improve performance and UI clarity:

    // Add pagination state
    + const [pageSize, setPageSize] = useState(10)
    + const [currentPage, setCurrentPage] = useState(1)
    
    // Modify filteredMods to include pagination
    const filteredMods = modsData ? {
      repos: modsData.repos.map(repo => ({
        ...repo,
    -   packages: repo.packages.filter(modFilter)
    +   packages: repo.packages.filter(modFilter)
      })),
      modsWithoutRepos: modsData.modsWithoutRepos.filter(modFilter)
    } : null
    
    // Add pagination controls at the bottom of the modList div
    <div className={styles.modList}>
      {/* Existing code */}
    + {filteredModsCount > pageSize && (
    +   <div className={styles.pagination}>
    +     <Button 
    +       onClick={() => setCurrentPage(p => Math.max(1, p - 1))}
    +       disabled={currentPage === 1}
    +       title="Previous Page"
    +     />
    +     <span>Page {currentPage} of {Math.ceil(filteredModsCount / pageSize)}</span>
    +     <Button
    +       onClick={() => setCurrentPage(p => Math.min(Math.ceil(filteredModsCount / pageSize), p + 1))}
    +       disabled={currentPage === Math.ceil(filteredModsCount / pageSize)}
    +       title="Next Page"
    +     />
    +   </div>
    + )}
    </div>
    src/clientMods.ts (8)

    15-15: Fix spelling of “sensetiveKeys”.
    You have a minor typographical error in the variable name: consider renaming “sensetiveKeys” to “sensitiveKeys” for clarity.

    -  const sensetiveKeys = new Set(['authenticatedAccounts', 'serversList', 'username'])
    +  const sensitiveKeys = new Set(['authenticatedAccounts', 'serversList', 'username'])

    121-127: Avoid performance overhead from using delete.
    Using the delete operator repeatedly can degrade object shape optimizations in some JS engines. Setting properties to undefined can be more performant.

    const cleanupFetchedModData = (mod: ClientModDefinition | Record<string, any>) => {
    -  delete mod['enabled']
    -  delete mod['repo']
    -  delete mod['autoUpdateOverride']
    -  delete mod['lastUpdated']
    +  mod.enabled = undefined
    +  mod.repo = undefined
    +  mod.autoUpdateOverride = undefined
    +  mod.lastUpdated = undefined
      return mod
    }
    🧰 Tools
    🪛 Biome (1.9.4)

    [error] 122-122: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 123-123: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 124-124: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 125-125: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    218-229: Remove the useless catch block.
    The catch block rethrows the original error without additional logic, making it redundant. Simplify by removing the try/catch here.

          // eslint-disable-next-line no-useless-catch
          try {
            const module = await import(/* webpackIgnore: true */ url)
            module.default?.(structuredClone(mod))
            window.loadedMods[mod.name] = module
    -      } catch (e) {
    -        // ...
    -        throw e
    +      } catch (error) {
    +        console.error(`Error loading mod ${mod.name}:`, error)
    +        throw error
           }
    🧰 Tools
    🪛 Biome (1.9.4)

    [error] 227-227: The catch clause that only rethrows the original error is useless.

    An unnecessary catch clause can be confusing.
    Unsafe fix: Remove the try/catch clause.

    (lint/complexity/noUselessCatch)


    273-276: Remove redundant catch block rethrow.
    This try/catch is simply rethrowing the error. Consider removing it or adding meaningful handling if needed.

    try {
      const response = await fetch(url)
      if (!response.ok) throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`)
      return await response.text()
    -} catch (e) {
    -  throw e
    }
    🧰 Tools
    🪛 Biome (1.9.4)

    [error] 275-275: The catch clause that only rethrows the original error is useless.

    An unnecessary catch clause can be confusing.
    Unsafe fix: Remove the try/catch clause.

    (lint/complexity/noUselessCatch)


    306-307: Drop the useless catch clause.
    Again, this catch only rethrows the same error. Remove it unless you plan to provide additional error handling.

    try {
      // ...
    } catch (e) {
    -  // console.error(`Error installing mod ${mod.name}:`, e)
    -  throw e
    }
    🧰 Tools
    🪛 Biome (1.9.4)

    [error] 307-307: The catch clause that only rethrows the original error is useless.

    An unnecessary catch clause can be confusing.
    Unsafe fix: Remove the try/catch clause.

    (lint/complexity/noUselessCatch)


    436-436: Correct the UI message.
    There is a typo in the 'won\' be automatically removed' text. Fix it to “won’t” or “will not” for clarity.

    -  const choice = await showOptionsModal('Remove repository? Installed mods won\' be automatically removed.', ['Yes'])
    +  const choice = await showOptionsModal('Remove repository? Installed mods won\'t be automatically removed.', ['Yes'])

    406-407: Offer help with the missing deactivation logic.
    You have a todo comment about deactivating the mod. Let me know if you want assistance implementing a proper teardown for disabled mods.


    1-462: Consider adding tests for this new module.
    This file manages crucial functionality (storage, activation, updates, deletion). Automated tests would help ensure stability and maintainability.

    🧰 Tools
    🪛 Biome (1.9.4)

    [error] 122-122: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 123-123: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 124-124: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 125-125: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 227-227: The catch clause that only rethrows the original error is useless.

    An unnecessary catch clause can be confusing.
    Unsafe fix: Remove the try/catch clause.

    (lint/complexity/noUselessCatch)


    [error] 275-275: The catch clause that only rethrows the original error is useless.

    An unnecessary catch clause can be confusing.
    Unsafe fix: Remove the try/catch clause.

    (lint/complexity/noUselessCatch)


    [error] 307-307: The catch clause that only rethrows the original error is useless.

    An unnecessary catch clause can be confusing.
    Unsafe fix: Remove the try/catch clause.

    (lint/complexity/noUselessCatch)

    📜 Review details

    Configuration used: CodeRabbit UI
    Review profile: CHILL
    Plan: Pro

    📥 Commits

    Reviewing files that changed from the base of the PR and between 69bfc1a and f4632c5.

    📒 Files selected for processing (14)
    • src/clientMods.ts (1 hunks)
    • src/core/progressReporter.ts (2 hunks)
    • src/index.ts (4 hunks)
    • src/optionsGuiScheme.tsx (2 hunks)
    • src/optionsStorage.ts (1 hunks)
    • src/react/Input.tsx (1 hunks)
    • src/react/ModsPage.tsx (1 hunks)
    • src/react/Screen.tsx (1 hunks)
    • src/react/SelectOption.tsx (2 hunks)
    • src/react/appStorageProvider.ts (3 hunks)
    • src/react/mods.module.css (1 hunks)
    • src/react/mods.module.css.d.ts (1 hunks)
    • src/reactUi.tsx (2 hunks)
    • src/screens.css (1 hunks)
    ✅ Files skipped from review due to trivial changes (2)
    • src/react/mods.module.css.d.ts
    • src/react/mods.module.css
    🚧 Files skipped from review as they are similar to previous changes (2)
    • src/optionsGuiScheme.tsx
    • src/reactUi.tsx
    🧰 Additional context used
    🧬 Code Definitions (2)
    src/core/progressReporter.ts (1)
    src/react/NotificationProvider.tsx (1) (1)
    • showNotification (22-37)
    src/clientMods.ts (4)
    src/core/progressReporter.ts (1) (1)
    • ProgressReporter (6-19)
    src/optionsStorage.ts (1) (1)
    • options (189-194)
    src/react/appStorageProvider.ts (1) (1)
    • appStorage (88-88)
    src/react/SelectOption.tsx (2) (2)
    • showOptionsModal (24-49)
    • showInputsModal (57-88)
    🪛 Biome (1.9.4)
    src/clientMods.ts

    [error] 122-122: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 123-123: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 124-124: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 125-125: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 227-227: The catch clause that only rethrows the original error is useless.

    An unnecessary catch clause can be confusing.
    Unsafe fix: Remove the try/catch clause.

    (lint/complexity/noUselessCatch)


    [error] 275-275: The catch clause that only rethrows the original error is useless.

    An unnecessary catch clause can be confusing.
    Unsafe fix: Remove the try/catch clause.

    (lint/complexity/noUselessCatch)


    [error] 307-307: The catch clause that only rethrows the original error is useless.

    An unnecessary catch clause can be confusing.
    Unsafe fix: Remove the try/catch clause.

    (lint/complexity/noUselessCatch)

    🔇 Additional comments (16)
    src/core/progressReporter.ts (2)

    4-4: Added new icon import for notification enhancements.

    The import of pixelartIcons from the PixelartIcon module is now used to display visual feedback in notifications, improving the user interface.


    173-173: Enhanced notification with visual feedback.

    Adding the checkmark icon (pixelartIcons.check) to the end notification improves the user experience by providing a clear visual indicator of successful completion.

    src/react/Input.tsx (1)

    45-45: Input component now supports custom class names.

    The updated implementation correctly concatenates the base input styles with any additional class names passed as props, enhancing component flexibility and allowing for custom styling in the mod management UI.

    src/react/SelectOption.tsx (2)

    55-55: Added placeholder support to input options.

    The addition of an optional placeholder property to the InputOption type extends the component's functionality for input fields, improving user guidance.


    134-134: Implemented placeholder support in text inputs.

    The placeholder property is now correctly passed to the InputWithLabel component, providing visual hints to users when interacting with form fields in the modding interface.

    src/index.ts (3)

    100-100: Added client mods system import.

    The import of appStartup from the clientMods module integrates the new modding system into the application.


    750-750: Improved loading message clarity.

    Using progress.setMessage instead of setLoadingScreenStatus provides more consistent user feedback during world loading and block placement.

    Also applies to: 782-782


    1057-1057: Integrated client mods initialization.

    The addition of appStartup() to the application startup sequence initializes the client-side modding system, ensuring mods are loaded when the application starts.

    This aligns with the PR objective of implementing a client-side modding system, enabling the mod management capabilities described in the PR summary.

    src/optionsStorage.ts (1)

    65-67: Well-structured configuration for mod system.

    The additions to defaultOptions correctly implement the necessary configuration settings for the client-side modding system. The default values are appropriate - modding is disabled by default, update checks are enabled, and the check period is set to 24 hours.

    src/react/appStorageProvider.ts (3)

    10-10: Good refactoring for localStorage access.

    Extracting localStorage from window makes the code more consistent and readable.


    41-41: Type definition properly added for mod update tracking.

    The addition of modsAutoUpdateLastCheck to the StorageData type interface is appropriate for tracking when mod updates were last checked.


    81-81: Default value correctly set for new storage property.

    Setting the default value to undefined for the new storage property is appropriate as it indicates that no updates have been checked yet.

    src/react/Screen.tsx (1)

    9-9: Flexible enhancement to Screen component.

    The addition of the contentStyle prop improves the flexibility of the Screen component, allowing for more customized styling. The implementation correctly merges the new style with existing conditional styling.

    Also applies to: 12-12, 17-17

    src/react/ModsPage.tsx (2)

    1-16: Good component structure and type definitions.

    The imports are well-organized and the ModsData type is properly defined using the return type of getAllModsDisplayList for type safety.


    17-108: Well-implemented ModSidebar component with appropriate error handling.

    The ModSidebar component is well structured with appropriate conditional rendering and error handling. The handleAction function properly manages async operations and displays error messages.

    src/clientMods.ts (1)

    317-317: Ensure modsAutoUpdate & modsUpdatePeriodCheck exist in AppOptions.
    References to options.modsAutoUpdate and options.modsUpdatePeriodCheck may cause type errors if these properties aren’t defined in the AppOptions interface.

    Also applies to: 367-367

    @zardoy
    Copy link
    Owner Author

    zardoy commented Mar 20, 2025

    /deploy

    Copy link

    Deployed to Vercel Preview: https://prismarine-qp65go3oj-zaro.vercel.app
    Playground
    Storybook

    Copy link

    @coderabbitai coderabbitai bot left a comment

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Actionable comments posted: 0

    🧹 Nitpick comments (11)
    src/react/CreateWorldProvider.tsx (1)

    30-43: Implementation of plugin installation for new worlds

    This code now extracts plugins from the creation state and processes each plugin by:

    1. Fetching the plugin content and version
    2. Creating a plugins directory in the world save path
    3. Writing the plugin content to a file with a versioned filename

    The implementation correctly handles potential null returns from getServerPlugin and uses proper async/await patterns.

    Consider adding error handling for the file operations to inform the user if a plugin installation fails:

     for (const plugin of plugins) {
       // eslint-disable-next-line no-await-in-loop
       const { content, version } = await getServerPlugin(plugin) ?? {}
       if (content) {
         // eslint-disable-next-line no-await-in-loop
    -    await mkdirRecursive(path.join(savePath, 'plugins'))
    -    // eslint-disable-next-line no-await-in-loop
    -    await fs.promises.writeFile(path.join(savePath, 'plugins', `${plugin}-${version}.js`), content)
    +    try {
    +      // eslint-disable-next-line no-await-in-loop
    +      await mkdirRecursive(path.join(savePath, 'plugins'))
    +      // eslint-disable-next-line no-await-in-loop
    +      await fs.promises.writeFile(path.join(savePath, 'plugins', `${plugin}-${version}.js`), content)
    +    } catch (error) {
    +      console.error(`Failed to install plugin ${plugin}:`, error)
    +      // Could show a toast notification here if you have that functionality
    +    }
       }
     }
    src/react/CreateWorld.tsx (1)

    79-109: Added "Use Mods" functionality to world creation

    Implemented a new button and functionality that allows users to:

    1. View and select from available server plugins (mods)
    2. See the count of selected plugins
    3. Access the full mods page via an "Install More" button
    4. Apply selected plugins to the world being created

    The implementation includes a disabled "Save Type: Java" button for future functionality.

    Consider adding a loading state to the "Use Mods" button for better UX:

     <Button onClick={async () => {
    +  const [isLoading, setIsLoading] = useState(false)
    +  setIsLoading(true)
       const availableServerPlugins = await getAvailableServerPlugins()
    +  setIsLoading(false)
       const availableModNames = availableServerPlugins.map(mod => mod.name)
       // ...rest of the implementation
     }}
    ->Use Mods ({plugins.length})
    +>{isLoading ? 'Loading...' : `Use Mods (${plugins.length})`}
     </Button>

    Also, it would be helpful to show a message when no mods are available:

     const availableServerPlugins = await getAvailableServerPlugins()
    +if (availableServerPlugins.length === 0) {
    +  showOptionsModal('No mods available', [
    +    { label: 'Install Mods', value: 'install', onClick: () => showModal({ reactType: 'mods' }) },
    +    { label: 'Cancel', value: 'cancel' }
    +  ])
    +  return
    +}
     const availableModNames = availableServerPlugins.map(mod => mod.name)
    src/react/ModsPage.tsx (2)

    30-31: Clarify the data-enabled logic.

    Currently, data-enabled is assigned an empty string if a mod is installed and the value of mod.activated otherwise. Ensure this reflects the intended enabled state (e.g., installed vs. activated) and confirm that your stylesheet selectors handle the resulting attributes properly.


    235-239: Centralize stats calculation logic.

    The code in getStatsText() branches on showOnlyEnabled and showOnlyInstalled, each building a separate count. Consider extracting these conditions into a helper function or a single calculation pass, which could help improve readability and maintainability.

    src/react/mods.module.css (2)

    17-27: Remove duplicated .statsRow definitions.

    .statsRow is declared twice (lines 17–21 and 23–27) with identical properties. Consider merging them into a single declaration to eliminate duplication.


    1-178: Consider extracting recurring color values into variables or a theme file.

    Multiple color codes (#999, #bcbcbc, #ff6b6b, etc.) are scattered throughout. Centralizing them can simplify future theming or changes to the color palette.

    src/clientMods.ts (5)

    127-130: Avoid using delete for performance-sensitive code.

    The repeated use of delete can impact performance according to JS engine implementations. Consider setting properties to undefined or refactoring these keys to be omitted from the object at creation time.

    -  delete mod['enabled']
    -  delete mod['repo']
    -  delete mod['autoUpdateOverride']
    -  delete mod['lastUpdated']
    +  mod['enabled'] = undefined
    +  mod['repo'] = undefined
    +  mod['autoUpdateOverride'] = undefined
    +  mod['lastUpdated'] = undefined
    🧰 Tools
    🪛 Biome (1.9.4)

    [error] 127-127: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 128-128: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 129-129: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 130-130: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    229-235: Remove or integrate this try/catch that rethrows the same error.

    This catch block simply rethrows the error, rendering it effectively redundant and possibly confusing to readers. Eliminate it to simplify the flow, or include additional error handling logic if needed.

    🧰 Tools
    🪛 Biome (1.9.4)

    [error] 233-233: The catch clause that only rethrows the original error is useless.

    An unnecessary catch clause can be confusing.
    Unsafe fix: Remove the try/catch clause.

    (lint/complexity/noUselessCatch)


    279-282: Simplify the catch clause.

    Similar to the previous comment, this catch block rethrows the same error. Consider removing the catch entirely or adding more meaningful error handling.

    🧰 Tools
    🪛 Biome (1.9.4)

    [error] 281-281: The catch clause that only rethrows the original error is useless.

    An unnecessary catch clause can be confusing.
    Unsafe fix: Remove the try/catch clause.

    (lint/complexity/noUselessCatch)


    323-324: Eliminate the no-op catch block.

    This catch clause only rethrows the error; remove or expand it if you need actual fallback or logging here.

    🧰 Tools
    🪛 Biome (1.9.4)

    [error] 324-324: The catch clause that only rethrows the original error is useless.

    An unnecessary catch clause can be confusing.
    Unsafe fix: Remove the try/catch clause.

    (lint/complexity/noUselessCatch)


    404-407: Improve mod deactivation logic.

    Current uninstallation logic deletes the loaded mod from window.loadedMods, but additional cleanup code (e.g., reversing injected styles or calling a proper deactivation method) remains partially commented. Consider finalizing mod teardown to avoid stale references or partial state in memory.

    📜 Review details

    Configuration used: CodeRabbit UI
    Review profile: CHILL
    Plan: Pro

    📥 Commits

    Reviewing files that changed from the base of the PR and between f4632c5 and 31a6579.

    ⛔ Files ignored due to path filters (1)
    • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
    📒 Files selected for processing (9)
    • package.json (1 hunks)
    • src/clientMods.ts (1 hunks)
    • src/defaultLocalServerOptions.js (1 hunks)
    • src/react/CreateWorld.tsx (4 hunks)
    • src/react/CreateWorldProvider.tsx (3 hunks)
    • src/react/ModsPage.tsx (1 hunks)
    • src/react/SelectOption.tsx (3 hunks)
    • src/react/appStorageProvider.ts (3 hunks)
    • src/react/mods.module.css (1 hunks)
    🚧 Files skipped from review as they are similar to previous changes (2)
    • src/react/SelectOption.tsx
    • src/react/appStorageProvider.ts
    🧰 Additional context used
    🧬 Code Definitions (2)
    src/react/CreateWorldProvider.tsx (2)
    src/react/CreateWorld.tsx (1) (1)
    • creatingWorldState (17-23)
    src/clientMods.ts (1) (1)
    • getServerPlugin (483-493)
    src/clientMods.ts (4)
    src/core/progressReporter.ts (1) (1)
    • ProgressReporter (6-19)
    src/optionsStorage.ts (1) (1)
    • options (189-194)
    src/react/appStorageProvider.ts (1) (1)
    • appStorage (90-90)
    src/react/SelectOption.tsx (2) (2)
    • showOptionsModal (24-49)
    • showInputsModal (58-89)
    🪛 Biome (1.9.4)
    src/clientMods.ts

    [error] 127-127: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 128-128: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 129-129: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 130-130: Avoid the delete operator which can impact performance.

    Unsafe fix: Use an undefined assignment instead.

    (lint/performance/noDelete)


    [error] 233-233: The catch clause that only rethrows the original error is useless.

    An unnecessary catch clause can be confusing.
    Unsafe fix: Remove the try/catch clause.

    (lint/complexity/noUselessCatch)


    [error] 281-281: The catch clause that only rethrows the original error is useless.

    An unnecessary catch clause can be confusing.
    Unsafe fix: Remove the try/catch clause.

    (lint/complexity/noUselessCatch)


    [error] 324-324: The catch clause that only rethrows the original error is useless.

    An unnecessary catch clause can be confusing.
    Unsafe fix: Remove the try/catch clause.

    (lint/complexity/noUselessCatch)

    🔇 Additional comments (10)
    src/defaultLocalServerOptions.js (1)

    11-11: New plugin folder configuration added

    A new configuration option pluginsFolder has been added with a default value of true. This aligns well with the modding system implementation and will enable plugin functionality by default.

    package.json (1)

    78-78:

    ❓ Verification inconclusive

    Updated flying-squid dependency

    The flying-squid dependency has been updated from version ^0.0.51 to ^0.0.57. This update likely includes fixes or features required for the new modding system.


    🏁 Script executed:

    #!/bin/bash
    # Check for changes between the two versions of flying-squid that might be relevant to plugin support
    
    # Clone the repo to inspect changes
    git clone https://github.com/zardoy/flying-squid.git temp-flying-squid
    cd temp-flying-squid
    
    # Check commits between v0.0.51 and v0.0.57
    echo "Changes between v0.0.51 and v0.0.57:"
    git log --oneline v0.0.51..v0.0.57 | grep -i "plugin\|mod"

    Length of output: 276


    Updated flying-squid dependency

    The dependency in package.json has been updated from version ^0.0.51 to ^0.0.57. A search in the upstream commit history (using keywords "plugin" and "mod") returned no explicit references to modding support changes between these versions. This could mean the improvements are internal or not documented via commit messages. It is recommended to review the release notes or upstream documentation to confirm that the new version indeed provides the necessary fixes or features for the modding system.

    src/react/CreateWorldProvider.tsx (2)

    1-7: Import updates to support plugin functionality

    The addition of fs, path, and getServerPlugin imports support the new plugin system implementation. This allows the component to handle file operations and retrieve plugin information from the modding system.


    20-20: Improved version label for clarity

    Changed version label format to simply show "(default)" instead of an offline availability message, making it clearer to users which version is the default.

    src/react/CreateWorld.tsx (5)

    4-5: New imports to support mod functionality

    Added imports for mod-related functionality:

    • getAvailableServerPlugins to fetch available server plugins
    • showModal to display the mods modal
    • UI components for selection options

    These imports properly support the new modding features being added.

    Also applies to: 11-11


    17-23: Added plugins array to world creation state

    The creatingWorldState proxy has been extended with a plugins property initialized as an empty array. This properly enables tracking selected plugins during world creation.


    28-28: Updated state snapshot to include plugins

    Modified the state destructuring to include the new plugins property, ensuring it's properly tracked in the component.


    76-77: Improved Game Mode label formatting

    Changed "Gamemode" to "Game Mode" for better readability and consistency with standard terminology.


    118-122: Enhanced create button visibility

    The "Create" button text is now bold, making it more prominent as the primary action. This is a good UI improvement.

    src/react/ModsPage.tsx (1)

    211-217: Confirm the need for multiple filter conditions.

    The filter leverages showOnlyInstalled and showOnlyEnabled in combination with the search text. Double-check that this logic matches your intended user experience (e.g., to ensure that installed and enabled filters don't conflict). This is a subtle area where logic mistakes can easily creep in.

    Copy link

    @coderabbitai coderabbitai bot left a comment

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Actionable comments posted: 0

    🧹 Nitpick comments (3)
    assets/config.html (3)

    15-26: Function removeAllData: Consider a DRY Approach
    The function correctly removes several specific items from localStorage. For better maintainability and clarity, consider iterating over an array of keys instead of making multiple removeItem calls. For example:

    -            localStorage.removeItem('serversList')
    -            localStorage.removeItem('serversHistory')
    -            localStorage.removeItem('authenticatedAccounts')
    -            localStorage.removeItem('modsAutoUpdateLastCheck')
    -            localStorage.removeItem('firstModsPageVisit')
    -            localStorage.removeItem('proxiesData')
    -            localStorage.removeItem('keybindings')
    -            localStorage.removeItem('username')
    -            localStorage.removeItem('customCommands')
    -            localStorage.removeItem('options')
    +            ['serversList', 'serversHistory', 'authenticatedAccounts', 'modsAutoUpdateLastCheck', 'firstModsPageVisit', 'proxiesData', 'keybindings', 'username', 'customCommands', 'options']
    +              .forEach(key => localStorage.removeItem(key));

    This refactor minimizes repetition and makes future changes easier.


    29-36: User Interface Layout: Maintainability and Cleanup
    The buttons are correctly grouped within a flex container to ensure spacing and alignment. As a future enhancement, consider moving the inline CSS (display: flex; gap: 10px;) to a dedicated CSS file or <style> block for better maintainability. Additionally, if the commented-out buttons (lines 33-35) are not planned for immediate use, they could be removed to reduce clutter.


    37-37: Input Field: Clarification Needed
    The file contains an empty <input /> element without any label or placeholder. If this input is meant for future functionality, consider adding a placeholder text or appropriate labeling; otherwise, remove it to avoid confusing users.

    📜 Review details

    Configuration used: CodeRabbit UI
    Review profile: CHILL
    Plan: Pro

    📥 Commits

    Reviewing files that changed from the base of the PR and between 31a6579 and 7fb49c1.

    📒 Files selected for processing (1)
    • assets/config.html (1 hunks)
    ⏰ Context from checks skipped due to timeout of 90000ms (1)
    • GitHub Check: build-and-deploy
    🔇 Additional comments (3)
    assets/config.html (3)

    1-6: HTML Structure is Solid and Compliant
    The document includes a proper <!DOCTYPE html> declaration, sets the language attribute, and defines essential meta tags along with the title. No issues found.


    7-13: Function removeSettings: Clear and Integrated
    The function is implemented correctly by prompting the user with a confirmation dialog, resetting the options key in localStorage, and reloading the page. This ensures that users apply the changes immediately upon reset.


    38-39: Proper Closure of HTML Document
    The closing tags for <body> and <html> are correctly in place, ensuring proper document structure.

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    None yet
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    MODS
    1 participant