Skip to content

Mundus v0.7.96

Choose a tag to compare

@NotBedd NotBedd released this 20 Oct 16:28
· 65 commits to main since this release

Mundus v0.7.96 — Bugfixing Release

Fixes (5)

1. Modern dialogs (no more native boxes)

  • NEW src/components/ConfirmDialog.tsx: promise-based in-app confirm host
    (showConfirmDialog({title, message, detail, confirmLabel, tone/danger}) → Promise).
    Styled like the rest of the app (rounded-2xl, border, backdrop blur, dark-mode aware,
    danger=red / warning=amber / info=accent), Enter confirms, Esc + backdrop click cancel,
    auto-focused confirm button, one-dialog-at-a-time. ConfirmDialogHost is mounted in BOTH
    app branches (Atlas + writing).
  • Replaced window.confirm for snapshot restore (App.tsx handleRestoreBackupSnapshot,
    now async) and for "Clear custom Firebase settings" (FirebaseConfigModal).
  • Replaced alert() for Firebase validation (inline red banner inside the modal instead of
    a blocking box) and for "+ Dictionary" in TextEditor (transient green "Added …" chip that
    outlives the button, which unmounts once the word joins the dictionary).
  • Bonus fix (latent React crash): FirebaseConfigModal returned null for closed state
    before its useState calls — hook count changed between renders. Hooks now run
    unconditionally; the form re-seeds via useEffect on open.
  • Swept the whole bundle: zero window.confirm/app-level alert( remain (the only alert(
    strings in the bundle are inside the third-party libwebp decoder).

2. Duplicate shortcut warning

  • src/lib/shortcutManager.ts: new bindingsEqual() + findBindingConflicts(bindings, excludeId, binding).
  • Settings → Keyboard Shortcuts:
    • Recording a combo that another action already uses shows an amber "Duplicate shortcut"
      banner (naming the conflicting action(s), auto-dismiss 8s, manual dismiss).
    • Persistent badges: any action whose combo is shared shows an amber chip + warning icon
      • "dup" tag until resolved; Reset Defaults clears everything.
    • Esc now cancels recording instead of binding Escape as a shortcut.
    • Shortcut groups lifted to module scope (KEYBINDING_GROUPS/KEYBINDING_LABELS) so the
      warning can name actions.

3. Settings submenus from the Atlas

  • Root cause: FirebaseConfigModal was rendered only in the writing-mode return. The Atlas
    is an early return, so "Configure Firebase" set the open state with no modal in the Atlas tree;
    it appeared only after opening a world.
  • Fix: extracted firebaseConfigModalElement and rendered it in both branches (same pattern
    the settings modal already used since v0.7.91). Verified E2E: Settings → Configure Firebase
    opens instantly on the Atlas.

4. Story Flow Graph layout survives backups

  • Root cause: the graph's layout (placed scene ids + x/y) lived only in localStorage
    (mundus_story_flow_nodes_ / mundus_story_flow_positions_). Backups carried story
    links but never the layout, so restoring on a fresh install/other device dropped every scene
    into default stacked positions; imports that renamed colliding ids also detached stored layouts.
  • NEW src/lib/storyFlowLayout.ts: readStoryFlowLayout, writeStoryFlowLayout,
    normalizeStoryFlowLayout (untrusted payloads), remapStoryFlowLayout (collision renames),
    mergeStoryFlowLayouts (backup wins for shared ids; local-only placed scenes kept — matches
    merge-import semantics), clearStoryFlowLayout, key helpers.
  • Backup payloads now carry layouts (storyFlowLayouts per-world map in app-wide backups +
    snapshots; storyFlowLayout in per-Mundus backups):
    • backupEngine.ts: ProjectBackupData, MundusBackupFile, export/build/parse for all three
      payload types extended (old backups without layouts restore harmlessly).
    • App.tsx: manual app-wide export, per-Mundus export, scheduled auto-download, and all three
      snapshot call sites (initial/timer/instant) capture layouts; app-wide import, snapshot
      restore, and Atlas import write them back (Atlas import remaps ids through the same rename
      table as items, then merges over the existing layout).
  • Deleting a world now also clears its two layout keys (v0.7.95 had cleaned map data; layouts
    were missed).

5. App-blanking crash (fixed)

  • TextEditor's status bar rendered document.wordCount.toLocaleString() /
    document.characterCount.toLocaleString() unguarded. A backup JSON missing characterCount
    (hand-edited/third-party imports) crashed React with no error boundary → blank screen on
    opening the world.
  • Fixed both ends: all five stat render sites guarded with || 0, StartMenu doc-row guarded,
    and applyMundusImport now derives missing wordCount/characterCount from plainText on
    the way in. E2E: the previously app-killing backup now imports and opens cleanly
    ("12 words · 13 chars" shown).

Files changed / added

New: src/components/ConfirmDialog.tsx, src/lib/storyFlowLayout.ts, scripts/test_v096_helpers.ts
Modified: src/App.tsx, src/components/SettingsModal.tsx, src/components/FirebaseConfigModal.tsx,
src/components/TextEditor.tsx, src/components/StartMenu.tsx, src/lib/backupEngine.ts,
src/lib/shortcutManager.ts, + the 6 version files.