Skip to content

main.js only wires: eight startup blocks move into their own modules (part of #683) - #1004

Merged
ccoventry merged 2 commits into
devfrom
chore/slim-main-js-683
Oct 24, 2026
Merged

ccoventry merged 2 commits into
devfrom
chore/slim-main-js-683

Conversation

@ccoventry

Copy link
Copy Markdown
Owner

Release note: none

Part of #683 (closed; this is the second pass it asked for).

studio/src/main.js goes from 900 → 559 lines. main_js_budget.test.js's BUDGET drops from 900 to 580 (559 + ~20 headroom). Each block below was a feature's init, listeners and the state only it needs; each now lives in its own module and main.js wires it with one call, the way open_from_explorer.js did. Boot order is unchanged: every call sits where its block used to be.

What moved where

Block New module Call in main.js
Capture Locations + Export Drives: both list editors, the two pickers, Add/Browse buttons, the free-space line, their settings load and state folder_pools.js createFolderPools({ getDemos, persist, refreshSetup })
Pinned folders (scanPaths), Explorer Recent tier, demo-count toggle, sidebar width: state, settings load, pin/unpin/recent handlers, initAnalyzerPane demo_folders.js createDemoFolders({ persist }), later .startAnalyzerPane()
Scan workers field and its memory hint scan_workers.js startScanWorkers({ persist }) (+ readScanWorkers import)
Configuration tabs, top nav, Capture subtabs, Commands-tab warning refresh on focus nav_tabs.js startNavTabs()
Window close (running batch, unsaved project, settings flush) and the beforeunload guard close_guard.js startCloseGuard({ needsSavePrompt, requestUnsavedChangesConfirmation, persistAppSettings })
Map warnings, demo links, hl.exe path change listeners (cfg warnings, packet-entity marks) hl_path_watch.js startHlPathWatch({ renderQueue }) (+ readHlPath, used for three getters main had inline)
Queue footer text and Clear buttons' enabled state queue_footer.js renderQueueFooter(demos) inside updateDemoFooter
Ctrl+N/O/S, swallowed reload keys, suppressed context menu app_shortcuts.js startAppShortcuts()

main.js keeps the queue state and the functions that reassign it (replaceScannedDemos, onDeleteDemo, selectDemoAndRenderDetail), the factories' wiring, and the boot order. Two stale comments in capture_pane.js that named main.js's updateExportPoolIndicator/targetDrives now point at the new modules.

CLAUDE.md: one sentence added to the "studio/src/main.js only wires" bullet (asked for by the user): the budget is a backstop, not the target; build a feature outside main.js from its first line and wire it in with one call.

New test

tests/e2e/app-boot.spec.js is the first e2e spec that boots the real index.html + main.js (every other spec loads its own pane harness, so none of them ran main.js). With mocked settings it checks: the capture/render folder lists and free-space line fill in, the scan-workers hint shows the memory, Add puts a typed folder in the list and the save carries it along with the pinned folder, the reload/session shortcuts and context menu are swallowed, and boot throws no ReferenceError/"is not a function" (the shape a wiring slip takes). Panes whose boot IPC the mock doesn't answer still throw on undefined at boot; those 5 errors are the same on dev, so the spec ignores them. README in tests/e2e/ notes the exception.

Test done

  • npm run test:unit: 851 passed (budget test included, at 559/580).
  • CI=1 npx playwright test (full suite): 390 passed (388 existing + 2 new).
  • npm run build: exit 0.
  • Parity check: ran app-boot.spec.js against dev's original main.js swapped in. Same functional results and the same 5 unmocked-IPC boot errors as the new main.js.
  • Not tested: the real Tauri app (no launch overnight). Close-guard behaviour is the same code moved; the mocked window never fires onCloseRequested.

Decisions

🤖 Generated with Claude Code

#683)

main.js goes from 900 to 559 lines; the budget drops to 580. Folder pools,
demo folder lists, scan workers, nav tabs, the close guard, the hl.exe path
watchers, the queue footer and the app shortcuts each get a module wired in
with one call. No behaviour change. Adds app-boot.spec.js, the first e2e spec
that boots the real index.html + main.js, and a CLAUDE.md line: the budget is
a backstop, not the target.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ccoventry

Copy link
Copy Markdown
Owner Author

Review of dfff4f4 (diff against origin/dev main.js, plus a live run of the real Tauri app).

Diff review: every moved block compared line by line with dev's main.js. All state reads still go through getters (folderPools.targetDrives(), demoFolders.pinned() / .all()), so no closure ends up holding a stale copy. That covers initCaptureUI, initRenderUI, finish clips, clip names, Setup, the pinned review, project_demos and settings_sync. The list editors still change the live arrays in place. No listener is lost or registered twice, and nothing that ran once now runs per call. The differences I found are all harmless:

  • app_shortcuts.js: (e.key || '') means a keydown with no key (Chromium autofill) no longer throws a TypeError. This is an improvement, covered by app-boot.spec's noKey.
  • folder_pools.js: #add-drive-btn is now looked up with ?., so a missing button no longer throws at boot.
  • The Add/Browse listeners on both folder pools are now registered before await getSettings() instead of after queue actions. In theory, a click in those few milliseconds could save before load. In practice that can't happen: Add needs a typed path, and Browse returns after load. The scan-workers field was already wired before load on dev.
  • pinnedListCleaned = demoFolders.load(settings) now always assigns instead of only setting true. load runs once, so this is equivalent.
  • markDemosOverLimit is now .then(renderQueue). The limit value is passed to it and ignored, so this is equivalent.
  • refreshCommandWarningsIfShown and readScanWorkers moved to module scope, and the #hl-path-input reads now go through readHlPath. Same expressions.
  • Startup order is the same as dev: folder pools → scan workers → settings_sync → settings load → nav tabs → close guard → hl-path watch → analyzer pane → setup → shortcuts.

Live check (npm run tauri dev from a separate worktree on this head, CDP, isolated appdata seeded with a copy of the real settings; the real settings.json hash was unchanged afterwards). No page errors or console.error during the run:

  • All 6 top nav tabs, the 3 Capture Studio subtabs and the 9 Configuration tabs show the right pane.
  • Settings loaded into both folder pools, the free-space line and the scan-workers hint (31 GB). Add Directory, Browse (native picker) and remove on Capture Output and on Render Output each saved straight away. Scan workers 12 was clamped to 8 and saved.
    • Add Folder with ci_fixture.dem: the queue footer shows 1 demo / 3 highlights, Clear All and Clear Untracked are enabled, the folder went to the front of demo_folder_history, and the project shows as unsaved.
  • In the Explorer, pin/unpin of a Recent folder saved pinned_folders both ways. The demo-count toggle and the sidebar drag-resize saved too.
  • F5, Ctrl+R and Ctrl+W are swallowed, plain keys are not, and the context menu is suppressed. Ctrl+S opened the Save dialog (cancelled).
  • Changing the hl.exe path from POST to PRE to empty and back to POST: the Initial and Scheduled command warnings followed each path, the queue redrew each time, and the path saved.
  • Closing the window (WM_CLOSE) with the dirty project showed the unsaved-changes prompt, and Cancel left the window open.

npm run test:unit: 851 passed. CI=1 npx playwright test: 390 passed, including app-boot.spec.

An older issue, not from this PR: the Explorer's Recent list doesn't redraw when + Add Folder records a visit. The new folder is saved, but the list stays out of date until something else redraws it. Dev's recordDemoFolderVisit had the same code path, and nothing calls refreshAnalyzerQuickLinks there.

No changes pushed. As far as I can tell this changes no behaviour and is ready to merge.

@ccoventry
ccoventry merged commit e305bbe into dev Oct 24, 2026
5 checks passed
@ccoventry
ccoventry deleted the chore/slim-main-js-683 branch October 24, 2026 10:20
ccoventry added a commit that referenced this pull request Oct 24, 2026
…ast demo by full path

- initDemoCache returned nothing when the Cache all button exists (the real
  app), so analyzer_pane's destructure threw and the rest of
  initAnalyzerPane never ran. app-boot.spec.js (from #1004) caught it.
- demo_cache_progress's `last` was a bare file name, so the player read's
  `paths.includes(last)` never matched and players only filled in when
  Cache all ended. It is now the full path given (nothing else reads it).
- CloudCheck looks a folder's volume up once, not once per demo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant