-
Notifications
You must be signed in to change notification settings - Fork 74
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
base: next
Are you sure you want to change the base?
Conversation
Review or Edit in CodeSandboxOpen the branch in Web Editor • VS Code • Insiders |
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Explore these optional code suggestions:
|
WalkthroughThis 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
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
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
Assessment against linked issues
Suggested labels
Suggested reviewers
Poem
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this 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.
Referencingwindow.loadedMods
works, but if you want the button label to update automatically when mods change, movingloadedMods
into a reactive store (similar tomodsUpdateStatus
) could help.src/clientMods.ts (1)
53-56
: Avoid using thedelete
operator for performance reasons.
Per lint suggestions, assigningundefined
may reduce the risk of de-optimizations. If removing these properties is essential, continue usingdelete
, 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
📒 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 ofmodsUpdateStatus
.
There was a problem hiding this 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 ofz-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 usesz-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 ofheight: 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 thedvh
unit. Including a fallback such as100vh
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 usingdelete
.
Using thedelete
operator repeatedly can degrade object shape optimizations in some JS engines. Setting properties toundefined
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 atodo
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
📒 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 theInputOption
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 ofsetLoadingScreenStatus
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
: EnsuremodsAutoUpdate
&modsUpdatePeriodCheck
exist inAppOptions
.
References tooptions.modsAutoUpdate
andoptions.modsUpdatePeriodCheck
may cause type errors if these properties aren’t defined in theAppOptions
interface.Also applies to: 367-367
/deploy |
Deployed to Vercel Preview: https://prismarine-qp65go3oj-zaro.vercel.app |
There was a problem hiding this 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 worldsThis code now extracts plugins from the creation state and processes each plugin by:
- Fetching the plugin content and version
- Creating a plugins directory in the world save path
- 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 creationImplemented a new button and functionality that allows users to:
- View and select from available server plugins (mods)
- See the count of selected plugins
- Access the full mods page via an "Install More" button
- 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 thedata-enabled
logic.Currently,
data-enabled
is assigned an empty string if a mod is installed and the value ofmod.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 onshowOnlyEnabled
andshowOnlyInstalled
, 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 usingdelete
for performance-sensitive code.The repeated use of
delete
can impact performance according to JS engine implementations. Consider setting properties toundefined
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
⛔ 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 addedA new configuration option
pluginsFolder
has been added with a default value oftrue
. 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 functionalityThe addition of
fs
,path
, andgetServerPlugin
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 clarityChanged 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 functionalityAdded imports for mod-related functionality:
getAvailableServerPlugins
to fetch available server pluginsshowModal
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 stateThe
creatingWorldState
proxy has been extended with aplugins
property initialized as an empty array. This properly enables tracking selected plugins during world creation.
28-28
: Updated state snapshot to include pluginsModified the state destructuring to include the new
plugins
property, ensuring it's properly tracked in the component.
76-77
: Improved Game Mode label formattingChanged "Gamemode" to "Game Mode" for better readability and consistency with standard terminology.
118-122
: Enhanced create button visibilityThe "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
andshowOnlyEnabled
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.
There was a problem hiding this 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
: FunctionremoveAllData
: 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 multipleremoveItem
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
📒 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
: FunctionremoveSettings
: Clear and Integrated
The function is implemented correctly by prompting the user with a confirmation dialog, resetting theoptions
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.
PR Type
Enhancement, Tests
fixes #314
Description
Introduced a client-side modding system with mod management.
Enhanced UI with mod-related features.
Added configuration options for mod support and updates.
Included a new HTML configuration page for client settings.
Changes walkthrough 📝
1 files
Added support for copying `config.html` to the build output.
8 files
Implemented client-side modding system with database and activation
logic.
Integrated mod startup logic into the application initialization.
Added "Client Mods" button to the options menu.
Added mod-related configuration options.
Created a new mods management page.
Added storage support for mod update checks.
Integrated the mods page into the React UI structure.
Added a new HTML configuration page for client settings.
Summary by CodeRabbit
New Features
Chores
flying-squid
.