UI/UX Optimizations, Code Quality Enhancements, Deploy UI, and Mod Importing Improvements - #958
UI/UX Optimizations, Code Quality Enhancements, Deploy UI, and Mod Importing Improvements#958vthiep2412 wants to merge 21 commits into
Conversation
Optimize mod cache performance using double buffering and asynchronous file reads. Add bulk mod staging and verification to the mod list manager. Use localStorage to cache update checks and display loading indicators during page navigation. Cache optimization - Implement double-buffered cache preloading for mod manifests, folders, and framework checks in utils - Replace synchronous memoized file reads with asynchronous cache checks Mod importing and management - Add a staging container for bulk mod archives with validation checks in mod list page - Support folder naming for custom RPKG mods during staging UI performance - Render inline loading states and tips during page navigation in layout view - Cache GitHub release checks and mod update checks using localStorage to avoid rate limits - Remove obsolete page-reloads to leverage Svelte routing smoothly Platform and build integration - Avoid hard crash on launch when Deploy exe is absent in development mode - Enable multi-selection in file open dialog within electron backend - Append build artifacts to gitignore and disable server-side rendering for SvelteKit
… Deploy UI
## UI/UX optimization
- Increase the loading speed of ModList, Settings page.
- Refactor page caching, allowing for faster page load after cache.
- Group missing mods validation into a single startup alert dialog and filter them from the load order.
- Preload and cache mod folders and manifests in memory to avoid slow disk reads during UI rendering.
- Wrap preloadModsCache calls in Svelte page mount with try/catch/finally to prevent infinite loading spinners.
- Patch manifestsMap in-memory directly during setModManifest to prevent synchronous disk rescans.
- Add safe options checks in sortMods to prevent page crashes when option arrays are undefined.
## Code quality
- Limit chunk extraction regex matching to file basenames or relative subpaths to prevent directory name conflicts.
- Sanitize folder names in sanitizeModName by stripping Windows-invalid filename characters and dot segments.
- Generate a validation cache key based on the stats of all validation-critical files and cache the "No manifest" state.
- Track the active 7-Zip process handle in Svelte and kill the process when the user cancels staging.
- Kill rpkg-cli.exe using taskkill when a deployment fails to clean up orphaned worker processes.
## Improve Deploy UI
- Adjust the font size and output console size for a better visual.
- Add Elapsed High Performance time, persistent even if the GUI crashes.
- If the deploy is successful, it will show “Done in…”; If it fails, it will show “Failed in…”.
- Note: Elapse is a custom timer by the frontend and has a higher precision than the backend timer. So “Done in…” by the frontend will differ from the backend because Node.Js overhead is incurred on the backend.
- Add Smart scroll to console: pause auto-scroll on manual scroll up and resume after random idle delay (15s to 25s) or on scroll back to bottom.
- Add percentage and a progress bar based on the percentage.
- 0% to 10% is for Discovering mods.
- 10% to 30% is for Analysing framework mod.
- 30% to 90% is for Deploying and Applying patch.
- 90% to 100% is for:
- Localising text
- Patching thumbs
- Patching packagedefinition
- Generating RPKGs
- Add a filter for duplicate output to the console.
- The warning block has been moved to the side to display multiple warnings more easily, and it uses `set` to prevent duplicate warnings.
… issues - Remove duplicate flags from child_process spawn for Deploy.exe - Implement robust error handling on deployProcess to prevent stuck state - Make mod validation reactive and eliminate mounting flicker - Evict older validation cache entries in localStorage to prevent key accumulation - Default config.loadOrder to empty array if missing - centralize trustedHosts allowlist and require HTTPS protocol for updates - Wrap preload cache calls and manifest lookups in try-catch on authoring pages
- Add single cleanup path and single-fire guard for deploy process setup - Kill partially started child process to prevent process leaks - Defer expensive filesystem validation checks using setTimeout to improve initial paint performance
…timize deploy process - Move cache state variables to the top of utils.ts to resolve used-before-defined warnings - Convert mutable let exports to getter functions to prevent ES module mutable binding issues - Silence unused variable warning on the dummy Svelte reactivity helper parameter using a void statement - Specify type-safe unknown instead of any for directory removal error reference - Add skipcq directives to bypass cyclomatic complexity check on performValidation - Safely type options mapping functions in validation helpers to prevent runtime errors - Fix typo in platform check inside main.ts by remove `as any`, idk why it like that but I follow linter. - Adjust Warnings container width to a stable 260px inline style on the modList page - Expand deploy modal container width to 56% on screens wider than 82rem - Hide the deployment failure duration label if the duration is 5s or less - Replace empty catch blocks with clean parameterless catch declarations - Check Deploy.exe exit codes on close to report crashed or terminated deployments to the UI - Secure download validation by enforcing HTTPS protocol and restricting subdomains to trusted hosts - Introduce markChanged helper to update changed and deployFinished states together on mod list modifications - Move mod file open dialog result IPC listener to page level to prevent duplicate listener registration - Install mods into temporary sibling directories first and rename them into place after copy operations succeed - Guard execFileAsync and staging progress flags with run identity checks to prevent staging race conditions - Track deploy process identifier and send IPC signal to terminate process tree instead of global taskkill - Stream auto-install downloads chunk-by-chunk to disk and wrap file operations in a unified try-catch-finally block - Resolve foldersMap compile error by querying getModFolder helper with knownMods presence validation
…/O), and layout improvements, add warning count, improve deploy error specificity and flush final console logs - Restrict console resizing to the vertical axis only (resize: vertical) - Set console dimensions to range between a 25vh minimum and a 535px maximum height cap - Implement incremental console log parser with a throttled 200ms update frequency to prevent UI lag and improve I/O - Reset the deployment warnings state array when opening the modal to clear previous run leaks - Render the progress bar percentage text in white during active deployment - Count warnings in the sidebar with bold gray indices in style `[xx]` - Added total warnings count to the sidebar header - Preserve and append process launch failure errors to the deployment logs inside electron.cjs - Refactor deploy exit error checking in electron.cjs to report neutral failure messages for non-spawn errors - Flush the throttled console log rendering immediately on deployment finished to avoid missing trailing logs
…gress UI refactor: optimize validation cache and resolve linter warnings Improve Mod Manager responsiveness, reliability, and stability by implementing async file operations, safe rollback swaps, and optimizing validation caching. ## UI/UX and process stability (`modList/+page.svelte`, `electron.cjs`) + Add deleteInProgress and importInProgress loading states with modal progress indicators ~ Make mod import and delete operations run asynchronously ~ Bind dialogs to main window to ensure proper modal focus ~ Ignore staging and temp directories in electron-reloader to prevent page reloads ~ Fix HTML markup inside the delete modal by moving progress bar container out of paragraph tags ## Safe swap and rollback (`+page.svelte`, `modList/+page.svelte`) + Implement safeReplaceFolder helper to rename dest to backup and restore it if rename fails ~ Replace destinations using safeReplaceFolder in bulk import framework and RPKG paths ~ Apply safe swap rollback pattern to synchronous mod updates ## Caching and validation (`utils.ts`, `+page.svelte`) + Add clearValidationCacheForFolder to clear cache for both raw and resolved paths ~ Selectively invalidate validation cache per folder during imports and updates ~ Return safe default manifest values on read or parse failure to avoid crashes - Remove debug cache hit console info message
…elte`) style: add skipcq directive to suppress warning (`utils.ts`) Add inline documentation comments and skipcq directives to improve code clarity and resolve static analysis warnings. ## Caching and validation (`utils.ts`) + Add JSDoc comments to `markModAsDeleting` and `unmarkModAsDeleting` status helpers + Add JSDoc comments to fallback manifest reader `getManifestFromModID` + Add JSDoc comments to validation cache invalidator `clearValidationCacheForFolder` ~ Add skipcq directive for window.alert warning to resolve DeepSource JS-0052 alert check ## Safe swap and rollback (`modList/+page.svelte`) + Add JSDoc comments to folder replacement swap helper `safeReplaceFolder`
- The main thread performs console warning and error parsing, blocking everything else because it parses in O(n^2), including the elapsed timer stuck/freeze and being incorrect. - Fixed by introducing a web worker for time counting. - Fixed by parsing only newly appended log lines incrementally to keep CPU usage low. And offload with Web Worker - Smart auto scrolling has a race condition and is insensitive threshold - Fixed by increasing the threshold up to 100px - Use Svelte's native `tick()` lifecycle handler to ensure it only scrolls after new DOM elements are fully rendered. Extras: - Increase console max height to 65vh.
- Make every scroll have dark mode for those who have eye strain. - Analyze the framework now in 11% to 30% instead of 40%. - 65vh is too high, so 60vh! Check previous change: - The console does work faster and with less lag - The smart auto scroll does work as expected - The elapse does work and is very persistent Rated my work: 8/10 - Coderabbit passed
style: fix mainpage overflow and improve loading UI on modList, setting page fix: resolve cache prefix mismatch and infinite directory loops Optimize mod loading speed and UI responsiveness by shifting file walks to IPC and validation checks to a worker thread. ## Asynchronous validation pipeline + Add `validation.worker.js` background thread to compile schemas and run Ajv JSON validation. + Add `ipc.invoke` wrapper to `preload.cjs` to support asynchronous renderer-to-main IPC communication. + Add `onerror` crash handler to validation worker in `utils.ts` to prevent Svelte promise hangs. ~ Offload directory walks and file stats in `electron.cjs` using async promises to avoid blocking the main thread. ~ Rewrite `validateModFolder` in `utils.ts` to execute asynchronously via the sequential `validationQueue`. ~ Resolve validation Promise reactively inside `Mod.svelte` and `authoring/[mod]/+page.svelte`. ( `Mod.svelte`, `validation.worker.js`, `electron.cjs`, `preload.cjs`, `utils.ts`, `authoring/[mod]/+page.svelte` ) ## UI layout and loading improvements + Add 1.5-second timer on `modList/+page.svelte`, `authoring/+page.svelte`, and `settings/+page.svelte` to show building cache status. ~ Replace inline loaders on settings, modList, authoring, and option pages with centered large spinner elements. ~ Adjust homepage flex layout in `+page.svelte` to prevent scrollbar cutoff at the top of the viewport. - Remove unused `InlineLoading` and `klaw-sync` imports across page views and Electron code. ( `+page.svelte`, `modList/+page.svelte`, `settings/+page.svelte`, `authoring/+page.svelte`, `authoring/[mod]/options/[option]/+page.svelte`, `electron.cjs` ) ## Cache and path safety fixes + Add path verification using `realpath` and a visited Set in `electron.cjs` to block circular symlink loops. ~ Remove trailing colons from `val-cache` lookup prefixes in `utils.ts` to ensure mod updates evict old cache files. ( `electron.cjs`, `utils.ts` ) ## Info page & easter eggs + Add click counter triggers to skip intro, developer mode, and error reporting components to render easter egg texts. with 3s fade timeouts to hide easter egg elements after display. ~ Replace click spans with semantic button elements to satisfy Svelte accessibility rules. ( `info/+page.svelte` )
- Mods could theoretically specify folder paths in their settings that point to files outside the mod's own directory (using absolute paths or `..` folders). - Fixed by introducing verification checks. If the path tries to escape, just skip it. - Blame Atampy25 - Found by `CodeRabbit` - If the Mod Manager window is closed or destroyed while the backend is trying to send a message to it, the application could crash silently in the background. - Added a helper check `!mainWindow.webContents.isDestroyed()` - Blame me - Found by `CodeRabbit` - Fast mod-switching could cause slow validation results from previous mods to overwrite the currently selected mod view or crash the app on missing folders. - Fixed by wrapping the validation logic in error catches and added a check to discard validation results if the mod ID changed before completion. - Blame me because of asynchronous promise implementation. - Found by `CodeRabbit`, `Gemini-Code-Assist` - A crashed validation worker would hang the app permanently, crash results were cached to disk, and malformed files or mismatched versions broke validations. - Fixed by resetting the worker on error to spawn fresh, blocked caching of worker crashes, and added version guards and null checks to the worker. - Blame me for creating the Worker - Found by `CodeRabbit`, `Gemini-Code-Assist` - When loading the mod list, the cache preloader validates each mod folder one-by-one and adds an artificial 0ms delay between each folder. - Fixed by launching all validation tasks concurrently (relying on our queue system under the hood) and removing the artificial setTimeout delay loop entirely. - Blame me bruh, I added it to fix UI freeze but it does nothing. - Found by `Sourcery`. - The code for rendering the loading screen, handling its 1.5-second timer transition, and preloading cache is copy-pasted across the Settings, Authoring, and Option pages. This makes maintenance difficult. - Fixed by creating a new shared component `CacheLoading.svelte` that wraps the loading logic and layout. Replaced the duplicate code on the three Svelte pages with this component. - Blame me for copy/pasting - Found by `CodeRabbit` - Cache validation checks were queued sequentially, causing slow page reloads even when mods were already cached. - Fixed by checking local cache in parallel (via IPC) before entering the queue, bypassing the queue completely for cached mods. - Blame both me (for the queue design) and Gemini (for moving IPC stats inside the queue without considering the bottleneck). - Found by me #### Below are found by `CodeRabbit`, `Sourcery`, `Gemini-Code-Assist` - The log parsing worker was terminated instantly when deployment finished, cutting off the last few console logs. - Fixed by flushing and parsing the final batch of log lines synchronously in Svelte right before shutting down the worker. - Blame me and Atampy - The manager stopped tracking the deployment immediately on errors, which allowed closing the modal or uploading logs before the underlying process had fully exited. - Fixed by keeping track of active deployment until the backend process officially triggers frameworkDeployFinished, disabling modal exit actions until shutdown completes. - This is mandatory for the `Deploy.exe` to clean up. - Blame both me and Atampy - Creating new worker Blob URLs on every deployment without revoking them leaked memory in the browser over time. - Fixed by immediately calling `URL.revokeObjectURL()` right after creating the worker instances. - Blame me. - Navigating away from the mod list page while deployment is active or completed left background timers and workers running (Resource Leak). - Fixed by importing Svelte's `onDestroy` lifecycle method and calling `stopDeployTimer()` to ensure everything is terminated on unmount. - Additionally, fixed by registering a SvelteKit `beforeNavigate` lifecycle hook to intercept and cancel any navigation events while the deployment process is actively running. - Blame no one, I just implemented it and maybe some blame on Atampy.
fix: guard deployment Web Workers with construction and runtime fallbacks fix: resolve mod deletion race condition by cleaning loadOrder config style: resolve DeepSource type warnings and skipcq rules in utils.ts Introduce structured preloading error recovery, built-in worker fallbacks, and deletion state synchronization to ensure UI stability. ## Cache loading architecture + Add loading error and retry callback props to CacheLoading ~ Move 1500ms delay timer and cleanup into CacheLoading ~ Simplify initialization loading logic in modList, authoring, and settings pages ~ Catch cache preloading errors on mount and show a retry state - Remove duplicated timer state and timeout handle cleanups from Svelte pages (`CacheLoading.svelte`, `authoring/+page.svelte`, `settings/+page.svelte`, `modList/+page.svelte`) ## Worker error handling + Wrap deployment workers in try/catch construction blocks + Add runtime onerror handlers to terminate crashed workers and fallback ~ Recover gracefully with local setInterval and synchronous log parsing on worker crashes (`modList/+page.svelte`) ## Mod deletion ~ Clean up loadOrder during deletion to prevent race condition lookup alerts (`modList/+page.svelte`) ## Code quality ~ Change validationPromises type from any to unknown in utils.ts to satisfy DeepSource ~ Correct DeepSource skipcq rule code annotations in utils.ts (`utils.ts`)
fix: lock deploy modal to prevent dismissals during active deployment style: suppress DeepSource global scope warning in electron.cjs Ensure UI stability during deployment and improve maintainability by eliminating log parsing code duplication. ## UI/UX enhancements + Add `on:close` handler to the deploy modal to block Escape key and window-close dismissals while deployment is active (`modList/+page.svelte`) ## Code optimization + Add shared `parseLogs` helper function ~ Refactor `parserWorkerCode` thread and local `parseLinesSynchronously` fallback to call `parseLogs` (`modList/+page.svelte`) ## Code quality ~ Suppress `JS-0067` global function warning in `electron.cjs` alongside `JS-R1005` (`electron.cjs`)
Fix/deploy UI improvements
|
I have redesigned the deployment GUI logic to ensure a full cleanup occurs and that the main process closes before the UI declares success. |
|
Sorry to be the bearer of bad news but SMF version 3 (in another, hidden for now repo) is already in the final stages of a closed beta getting ready for release. It's a ground up rewrite. |
Aw, man 😢. So should I close the PR? |
UI/UX Optimization
manifestsMapin-memory directly duringsetModManifestto prevent synchronous disk rescans.sortModsto prevent page crashes when option arrays are undefined.+page.svelteto prevent scrollbar cutoff at the top of the viewport.Cache Optimization
utils.ts.validation.worker.jsbackground thread to compile schemas and run Ajv JSON validation.ipc.invokewrapper topreload.cjsto support asynchronous renderer-to-main IPC communication.electron.cjsusing async promises.Code Quality / Security Improvements
sanitizeModNameby stripping Windows-invalid filename characters and dot segments.rpkg-cli.exeusing taskkill when a deployment fails to clean up orphaned worker processes.github.iosubdomains.Mod Importing and Management
Deploy UI
setto prevent duplicate warnings.[xx].Notes for codebase management
.gitignoreduring testing and debugging.Deploy.exeis absent in the developer environment.Notes