Skip to content

Conversation

@engylemure
Copy link

Added usage of the LocalStorage to save the current history into it, allowing the user to visualize the recently executed queries between page reloads.

@rlaiola
Copy link
Contributor

rlaiola commented Nov 14, 2025

Reference issue

#233

What does this implement/fix?

This PR implements persistent editor state and improves editor history handling by using LocalStorage, fixes cross-tab contamination of saved editor content/history, adds TTL and reload-detection for autosaved editor content, and ensures the language-change confirmation text is loaded from the JSON locale resources.

  • Editor content persistence: The CodeMirror editor content is now saved to localStorage so the editor state is restored after a page reload. Saved content is stored as a JSON payload (e.g. { "content": "...", "savedAt": 169... }) which allows TTL-aware restores and safer upgrades.

    Before:
    Screen Recording 2025-11-14 at 17 49 48

    After:
    Screen Recording 2025-11-14 at 17 48 55

  • TTL & reload/navigation behavior:

    • A contentTtlMs prop allows automatic expiration of autosaved content (so stale drafts are ignored). Default: no expiration.
    • Best-effort detection of a "hard reload" vs in-app navigation (isReloadNavigation()), plus props clearOnReload and clearOnNavigation, allow choosing whether to restore or start fresh when the user reloads or navigates away/back. Default: clearOnReload=false and clearOnNavigation=true.

    Before:

    clear on reload clear on navigation
    Screen Recording 2025-11-14 at 18 48 44 Screen Recording 2025-11-14 at 18 48 19

    After:

    restore on reload clear on navigation
    Screen Recording 2025-11-14 at 18 55 24 Screen Recording 2025-11-14 at 18 55 44
  • Per-tab storage isolation (fix for cross-pollination):

    • Storage and history keys now use props.tab || props.mode (the logical editor tab id) instead of props.mode alone. This prevents saved content or history from one editor (e.g. Group Editor) being loaded into another (e.g. RelAlg, BagAlg).
    • History operations (load/append/clear) were updated to use the same tab-based key.
  • LocalStorage-backed history:

    • Editor history (previous queries / snippets) is persisted to localStorage under a per-editor key. Helper functions (e.g. appendHistoryToStorage, loadHistoryFromStorage, clearHistoryFromStorage) are used to maintain a stable history with maximum size and to synchronize across tabs/windows via storage events.

      Before:
      Screen Recording 2025-11-14 at 17 28 36

      After:
      Screen Recording 2025-11-14 at 17 29 12

    • Clearing history is scoped by the same per-tab key so clearing one editor's history does not cause unexpected UI side effects.

      Before:
      Screen Recording 2025-11-14 at 17 36 47

      After:
      Screen Recording 2025-11-14 at 17 37 21

  • i18n fix (missing localization key):

    • The confirmation text used by navigation.tsx (i18n.t('local.change')) was missing from the JSON locale files that i18n loads. This PR adds the local.change entry to the JSON locale bundles (e.g. src/locales/en.json, de.json, es.json, etc.) so localized confirmation messages display correctly.

      Before:
      Screen Recording 2025-11-14 at 17 20 28

      After:
      Screen Recording 2025-11-14 at 17 18 20

  • Files (high-level)

    • Modified: src/calc2/components/editorBase.tsx
      • Added helpers for storage keys, TTL-aware load/save, reload detection, save-on-change hook, and updated history key usage.
      • Added props: contentTtlMs?: number, clearOnReload?: boolean, clearOnNavigation?: boolean.
      • Switched all editor storage/history operations to use props.tab || props.mode.
    • Reviewed / Updated: src/calc2/components/*Editor*.tsx (editor instantiations)
      • Ensure EditorBase is invoked with the appropriate tab prop if needed to isolate storage.
    • Modified: src/calc2/i18n.tsx (investigation) and updated locale payloads in src/locales/*.json
      • Added local.change to JSON locale files consumed by i18n (so i18n.t('local.change') returns a message).
    • Other: history helper functions used across editor components (load/append/clear) were wired to tab-based keys.
  • Why this change?

    • Prevents surprising content loss or cross-pollination between different editor tabs.
    • Improves user experience by restoring in-progress edits after reloads (configurable).
    • Makes history persistent and scoped per logical editor, enabling consistent undo/history behavior across reloads and windows.
    • Fixes a visible bug where language-change confirmation text did not appear because it wasn't present in the JSON resources used by i18n.
  • Reviewer notes / things to verify

    • Verify per-tab persistence:
      • Open two different editor tabs (e.g., RelAlg and Group), type different content into each, reload — ensure each editor restores its own content and doesn't show the other's content.
    • Verify clear-on-reload/navigation:
      • For all editor tabs clearOnReload=false and clearOnNavigation=true so content is preserved on reload and cleared on navigation.
    • Verify history persistence:
      • Add entries to history, reload, and confirm history is preserved per editor.
      • Use the "clear" action in history and confirm it only clears the history for the current editor tab.
    • Verify i18n fix:
      • Change language in UI and ensure window.confirm(i18n.t('local.change')) shows the localized string.

@rlaiola
Copy link
Contributor

rlaiola commented Nov 14, 2025

@engylemure I made some changes, give it a try!

Cheers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants