diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index e0a953d31..09791941d 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -211,11 +211,11 @@ one. The rules: Anything over 500 lines must be split. (The cap does **not** apply to `src/index.css` — it is the single, intentional styling foundation and the only app stylesheet; see the CSS rule above.) -- **Pages are thin orchestrators.** A file in `frontend/src/pages/` is just +- **Pages are thin orchestrators.** A file in `electron/src/shared/pages/` is just layout + routing + state wiring that composes feature components — no inline sub-component over ~50 lines. - **One component per file.** Co-locate `Foo.jsx` + `Foo.test.jsx` together in a - per-page feature folder under `frontend/src/components/` (e.g. + per-page feature folder under `electron/src/shared/components/` (e.g. `components/settings/`, `components/dub/`). Styling is **not** co-located — it's utilities + shadcn, with any irreducible rules in `src/index.css`. - **Shared bits go in a `primitives/` folder** inside the feature folder @@ -309,7 +309,7 @@ hard rules from the first prompt. var, or CLI flag). - **i18n — all 21 locales (hard rule):** every user-facing string goes through `t('...')` and the key must exist in **all 21** files under - `frontend/src/i18n/locales/`. Translate; don't copy English into non-English + `electron/src/shared/i18n/locales/`. Translate; don't copy English into non-English locales. CI fails on hardcoded CJK outside the allowlist in `tests/test_no_hardcoded_cjk.py` (extend `_ALLOWED_FILES` with a justification for legitimate functional CJK). diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3edec3bd1..b14ea14fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,7 +61,7 @@ jobs: cache-dependency-glob: "uv.lock" # Node 22 is needed for --experimental-strip-types so node:test can - # import .ts files directly from frontend/src/api/*. + # import .ts files directly from electron/src/shared/api/*. - name: Setup Node 22 uses: actions/setup-node@v4 with: diff --git a/AGENTS.md b/AGENTS.md index a236b3dd6..8926036d3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3,7 +3,7 @@ Electron (`electron/`) is the only desktop and web UI. The Tauri shell and legacy UI entrypoints are removed; do not restore build, runtime, release, or CI paths for them. Triage reports from final Tauri installations toward the migration guide and -preserve their immutable updater feeds. Some modules under `frontend/src/` remain +preserve their immutable updater feeds. Some modules under `electron/src/shared/` remain temporarily shared by Electron; they are not a runnable app. New UI, IPC, setup instructions, tests, and browser assets belong in Electron; validate Electron on macOS, Windows and Linux. @@ -37,7 +37,7 @@ Binding for every AI agent (Claude, Codex, Cursor, review bots, …). CLAUDE.md - Root-cause the class, not the instance; fail-before/pass-after regression test; smallest correct change. - Default behavior identical on macOS/Windows/Linux; platform-only features go behind explicit opt-in. Divergent default = P0. - Local-first: no new required network calls; any HF download gated on installed-ness or explicit user action; all synthetic audio through the `mark_synthetic` chokepoint. -- Every user-facing string via i18n, present in ALL 21 `frontend/src/i18n/locales/*.json` with real translations. +- Every user-facing string via i18n, present in ALL 21 `electron/src/shared/i18n/locales/*.json` with real translations. - Docs-sync in the same PR. CHANGELOG Unreleased: quiet one-liners ending `(#N)` + `— thanks @user!` for community work, under a short `**Highlights**` list. - Tagged release announcements lead with the biggest user-visible change; redesigns need real UI screenshots and migrations need installer links and steps. Verify all contributor credits from the tag comparison and included PRs; list authors and bug reporters separately (see `docs/RELEASING.md`). - Versioning: root `package.json` is the single source of truth; never bump without the owner asking. @@ -46,7 +46,7 @@ Binding for every AI agent (Claude, Codex, Cursor, review bots, …). CLAUDE.md ## Shared select controls -- Use `frontend/src/components/SearchableSelect.jsx` for all new or redesigned select boxes. Reuse `VoiceSelector` for voice choices. Do not introduce native `` controls. - Provide a localized `ariaLabel`; use `menuPortal` inside scrolling or clipping containers. Preserve keyboard selection and disabled states. ## Agent skills diff --git a/CLAUDE.md b/CLAUDE.md index a0dac2cf1..56045a681 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -3,7 +3,7 @@ Electron (`electron/`) is the only desktop and web UI. The Tauri shell and legacy UI entrypoints are removed; do not restore build, runtime, release, or CI paths for them. Triage reports from final Tauri installations toward the migration guide and -preserve their immutable updater feeds. Some modules under `frontend/src/` remain +preserve their immutable updater feeds. Some modules under `electron/src/shared/` remain temporarily shared by Electron; they are not a runnable app. New UI, IPC, setup instructions, tests, and browser assets belong in Electron; validate Electron on macOS, Windows and Linux. @@ -34,7 +34,7 @@ Everything else (new engines, fancy features) is downstream of "the thing instal The May-2026 stack research that used to live here served five capabilities that have all since shipped (HF-token Settings panel, prefilled-URL bug reporting, uv mirror fallback for restricted networks, the Supertonic-3 engine, in-repo Markdown docs). Follow the patterns in the code itself; the durable *don'ts* that research established: -- **No third-party endpoints for bug reporting or crash dumps** (`sentry-tauri` was evaluated and rejected) — bug reporting stays opt-in via prefilled GitHub-issue URLs, submitted from the user's own browser. The one sanctioned third-party endpoint is the opt-in PostHog US product analytics and error tracking (owner-set 2026-07-16; migrated 2026-09-26; sanitized renderer errors approved 2026-09-26), which is consent-gated behind the first-run prompt and ships allowlisted content-free metadata only. Raw exception, DOM, and session autocapture stay disabled; manually captured renderer exceptions must replace messages and scrub stack paths before transmission. Its publishable write-only project token is committed in-repo (owner reversal 2026-07-20, #1193 — source builds get the same consent-gated analytics as installers; env/baked token overrides), allowed by `tests/test_no_committed_analytics_token.py` in exactly `backend/core/analytics.py` + `frontend/src/utils/analytics.ts`. +- **No third-party endpoints for bug reporting or crash dumps** (`sentry-tauri` was evaluated and rejected) — bug reporting stays opt-in via prefilled GitHub-issue URLs, submitted from the user's own browser. The one sanctioned third-party endpoint is the opt-in PostHog US product analytics and error tracking (owner-set 2026-07-16; migrated 2026-09-26; sanitized renderer errors approved 2026-09-26), which is consent-gated behind the first-run prompt and ships allowlisted content-free metadata only. Raw exception, DOM, and session autocapture stay disabled; manually captured renderer exceptions must replace messages and scrub stack paths before transmission. Its publishable write-only project token is committed in-repo (owner reversal 2026-07-20, #1193 — source builds get the same consent-gated analytics as installers; env/baked token overrides), allowed by `tests/test_no_committed_analytics_token.py` in exactly `backend/core/analytics.py` + `electron/src/shared/utils/analytics.ts`. - **No PAT/token-based GitHub posting from the app** — the user submits from their own browser. - **Don't recommend `setx` for env vars on Windows** (silent truncation, no current-shell propagation) — use the in-app Settings panel or PowerShell `[Environment]::SetEnvironmentVariable`. - **Don't adopt Material for MkDocs** for any future docs site (maintenance mode since Nov 2025) — Astro Starlight is the precedent if docs ever outgrow the repo. @@ -58,7 +58,7 @@ For anything new: prefer what's already pinned in `pyproject.toml` / `electron/p **Release presentation and credits (owner-set 2026-09-17):** Tagged release announcements lead with the biggest user-visible change; redesigns need real UI screenshots and migrations need installer links and steps. Verify all contributor credits from the tag comparison and included PRs; list authors and bug reporters separately (see `docs/RELEASING.md`). Keep Highlights to 3–5 bullets; the release introduction can include prose, images, and a download table before the concise change entries. -**Localization (hard rule):** No hardcoded non-English (CJK) **user-facing text** anywhere in the codebase except the translation layer (`frontend/src/i18n/`). All UI strings go through i18n (`t('...')` keys in `locales/*.json`); native language names live in `i18n/index.ts` (`LANGUAGES`). Functional CJK is allowed and tracked via the allowlist in `tests/test_no_hardcoded_cjk.py` — text-processing regexes, model/engine vocabulary & identifiers (e.g. CosyVoice speaker IDs), localized error matching, demo/eval data, and test fixtures. CI fails on any hardcoded CJK outside the allowlist; to add legitimate functional CJK, extend `_ALLOWED_FILES` there with a justification. +**Localization (hard rule):** No hardcoded non-English (CJK) **user-facing text** anywhere in the codebase except the translation layer (`electron/src/shared/i18n/`). All UI strings go through i18n (`t('...')` keys in `locales/*.json`); native language names live in `i18n/index.ts` (`LANGUAGES`). Functional CJK is allowed and tracked via the allowlist in `tests/test_no_hardcoded_cjk.py` — text-processing regexes, model/engine vocabulary & identifiers (e.g. CosyVoice speaker IDs), localized error matching, demo/eval data, and test fixtures. CI fails on any hardcoded CJK outside the allowlist; to add legitimate functional CJK, extend `_ALLOWED_FILES` there with a justification. **Release deployment channels (hard rule, owner-set 2026-07-16):** a version bump is not "released" until **every** maintained channel ships it — the full checklist lives in `docs/RELEASING.md`. The channels are the four-platform Electron GitHub Release, GHCR and Docker Hub in CUDA and ROCm flavors, and the Docker Hub overview page synced from `deploy/dockerhub-overview.md`. The final Tauri feeds are immutable compatibility assets copied into releases for old clients; they are never rebuilt. Verify all channels after tagging. Preview/RC builds always source from `main`; never cut a side-branch build. diff --git a/backend/core/analytics.py b/backend/core/analytics.py index 36323ca28..15ccf0d38 100644 --- a/backend/core/analytics.py +++ b/backend/core/analytics.py @@ -53,7 +53,7 @@ _OFF_VALUES = {"1", "true", "yes", "on"} #: A `POSTHOG_PROJECT_TOKEN` env var (release builds bake one in via the #: desktop shell; developers can point at their own project) always wins. #: Committed-token guard: tests/test_no_committed_analytics_token.py allows a -#: `phc_` literal in exactly this file and frontend/src/utils/analytics.ts. +#: `phc_` literal in exactly this file and electron/src/shared/utils/analytics.ts. _PUBLIC_PROJECT_TOKEN = "phc_kJK9nFqtwFmB4CYWS4bMDTY7z9P4KCRyiRT7CzJTXm9f" # gitleaks:allow — publishable write-only key (#1193) _DEFAULT_HOST = "https://us.i.posthog.com" diff --git a/backend/core/archetypes.py b/backend/core/archetypes.py index 15091528f..6fdcadecf 100644 --- a/backend/core/archetypes.py +++ b/backend/core/archetypes.py @@ -83,7 +83,7 @@ _DIALECTS_SORTED = sorted(_CAT[5]) # 12 Chinese dialects # ── Use-case categories (replaces the named-real-person buckets) ────────────── # `icon` values are lucide-react component names; the frontend maps them to SVG -# components (see frontend/src/utils/archetypeIcons.jsx). No emoji — they render +# components (see electron/src/shared/utils/archetypeIcons.jsx). No emoji — they render # inconsistently across OSes. USE_CASES = [ {"id": "narration", "name": "Narration & Story", "icon": "BookOpen"}, @@ -323,7 +323,7 @@ def _make_featured(): # gender/age/pitch axes keeps every instruct inside the validator's vocabulary — # ``test_archetypes.py`` enforces this independently. # -# Each ``language`` label must match an entry in ``frontend/src/languages.json`` +# Each ``language`` label must match an entry in ``electron/src/shared/languages.json`` # verbatim, because the string flows straight into ``model.generate(language=…)`` # with no normalization. ("Arabic" is intentionally omitted — it is not in that # list.) ``_ML_SAMPLES`` is functional demo/eval text (like ``_ZH_SAMPLE``); the diff --git a/backend/core/describe_voice.py b/backend/core/describe_voice.py index 8e95ea3d0..9af857d7a 100644 --- a/backend/core/describe_voice.py +++ b/backend/core/describe_voice.py @@ -31,7 +31,7 @@ Design notes Localization note (CLAUDE.md): the only hardcoded CJK here is ``DIALECT_PINYIN`` — a functional pinyin → Chinese-dialect-token mapping -(model vocabulary, like ``frontend/src/utils/constants.js``). Registered in +(model vocabulary, like ``electron/src/shared/utils/constants.js``). Registered in ``tests/test_no_hardcoded_cjk.py``'s allowlist with this justification. """ from __future__ import annotations diff --git a/backend/core/error_docs_map.py b/backend/core/error_docs_map.py index 72a0ed485..4586a9229 100644 --- a/backend/core/error_docs_map.py +++ b/backend/core/error_docs_map.py @@ -1,7 +1,7 @@ """Error class → docs URL mapping for the in-app deeplink button. Used by the React ErrorBoundary's "Open docs for this error" button (via the -TypeScript mirror at `frontend/src/utils/errorDocsMap.ts`) and by the Phase 5 +TypeScript mirror at `electron/src/shared/utils/errorDocsMap.ts`) and by the Phase 5 bug-reporter for "this error has a docs page" links. The error taxonomy below is the contract — Phase 5 reporter consumes it, @@ -10,7 +10,7 @@ locks the key set. To add a new class: 1. Pick a stable ALL_CAPS key (the API will live forever). 2. Add the entry here. - 3. Mirror it in `frontend/src/utils/errorDocsMap.ts`. + 3. Mirror it in `electron/src/shared/utils/errorDocsMap.ts`. 4. Update the `test_keys_match_taxonomy` set and the TS-side keys-sync test. """ from __future__ import annotations diff --git a/backend/core/scrub.py b/backend/core/scrub.py index 152198b20..08b6f0626 100644 --- a/backend/core/scrub.py +++ b/backend/core/scrub.py @@ -3,7 +3,7 @@ Everything VoiceStudio renders into a bug report or diagnostic dump goes through ``scrub_text()`` before it can reach a prefilled GitHub Issues URL (the only outbound path — see CLAUDE.md Capability 2). The scrubber is the -backend twin of ``frontend/src/utils/bugReport.js``'s ``scrubText`` and +backend twin of ``electron/src/shared/utils/bugReport.js``'s ``scrubText`` and must stay at least as strict: - home directories → ``~`` (macOS ``/Users/``, Linux ``/home/``, diff --git a/backend/services/admin_sessions.py b/backend/services/admin_sessions.py index 248869a88..41203b35a 100644 --- a/backend/services/admin_sessions.py +++ b/backend/services/admin_sessions.py @@ -34,7 +34,7 @@ _TOKEN_BYTES = 32 _ENCODED_TOKEN_LENGTH = 43 _TOKEN_BODY_RE = re.compile(rf"^[A-Za-z0-9_-]{{{_ENCODED_TOKEN_LENGTH}}}$") # Every ticketed WebSocket route. The first-party mirror is ``ALLOWED_WS_PATHS`` -# in frontend/src/api/authSession.ts — a route missing here mints a 422 and the +# in electron/src/shared/api/authSession.ts — a route missing here mints a 422 and the # UI consumer fails silently (#1769 added /ws/tts for the live dub preview). _ALLOWED_WS_PATHS = frozenset( {"/ws/events", "/ws/transcribe", "/ws/tts", "/v1/audio/transcriptions/stream"} diff --git a/backend/services/longform_parser.py b/backend/services/longform_parser.py index 0c507b2fa..71b795a06 100644 --- a/backend/services/longform_parser.py +++ b/backend/services/longform_parser.py @@ -3,7 +3,7 @@ The longform marker dialect (``# heading``, ``[voice:NAME]``, ``[pause …]``, ``[slow]/[fast]/[emphasis]/[spell]``) was parsed by three independent code paths that disagreed (client/server/regex-level). This module is the one -canonical Python parser; ``frontend/src/utils/longformParser.js`` is its +canonical Python parser; ``electron/src/shared/utils/longformParser.js`` is its mechanically-mirrored JS twin, and ``tests/fixtures/longform_parser_cases.json`` is the shared golden corpus asserted byte-for-byte against both. diff --git a/backend/services/srt_parser.py b/backend/services/srt_parser.py index ce8338157..f3b6b260d 100644 --- a/backend/services/srt_parser.py +++ b/backend/services/srt_parser.py @@ -226,7 +226,7 @@ _WEBVTT_TAG_RE = re.compile(r"<[^<>\n]*>") # SubRip has no escaping, so `ad` is dialogue. Only exact tag # shapes are markup: ``/``/``, ``, ``, # `` and karaoke timestamps. Mirrored in -# frontend/src/utils/importStory.js (CUE_MARKUP); keep the two in step. +# electron/src/shared/utils/importStory.js (CUE_MARKUP); keep the two in step. _SRT_MARKUP_RE = re.compile( r"]+)*>" r"|<(?:v|lang)(?:\.[^\s.<>]+)*[ \t][^<>\n]*>|" diff --git a/backend/services/text_normalization.py b/backend/services/text_normalization.py index 17d9210a6..08e83f212 100644 --- a/backend/services/text_normalization.py +++ b/backend/services/text_normalization.py @@ -19,7 +19,7 @@ Design rules (load-bearing): pass through a pipeline is harmless. * **Per-language.** Numbers go through ``num2words`` only for languages it supports (``_NUM2WORDS_LANGS``; the request's ``language`` is a full - display name from frontend/src/languages.json or an ISO-ish code — both + display name from electron/src/shared/languages.json or an ISO-ish code — both resolve via :func:`_num2words_lang`), or through a hand-written native verbalizer for languages num2words lacks (``_NATIVE_VERBALIZERS``, e.g. Malayalam). Everything else keeps its digits. @@ -75,7 +75,7 @@ PREF_KEY = "text_normalization_enabled" # ── Language resolution ─────────────────────────────────────────────────────── # # The `language` kwarg across the app is normally a full display name from -# frontend/src/languages.json ("English", "German", …) — see +# electron/src/shared/languages.json ("English", "German", …) — see # resolve_kokoro_lang_code in services/tts_backend.py — but ISO-ish codes # ("en", "pt-BR") also flow through dub/API callers. Map both to a num2words # locale; anything unmapped keeps its digits (false negatives are fine). diff --git a/backend/services/tts_backend.py b/backend/services/tts_backend.py index 3a18b5866..17a07cec5 100644 --- a/backend/services/tts_backend.py +++ b/backend/services/tts_backend.py @@ -2230,7 +2230,7 @@ class KittenTTSBackend(TTSBackend): # #977: Kokoro's own ALIASES table (mlx_audio.tts.models.kokoro.pipeline) only # recognizes ISO-ish tokens ("en", "es", "fr-fr", "pt-br", …) — it has no idea # what a full language name is. OmniVoice's `language` kwarg is normally a -# full display name from frontend/src/languages.json (e.g. "Dutch", +# full display name from electron/src/shared/languages.json (e.g. "Dutch", # "Spanish"), forwarded verbatim by the frontend and by # `OmniVoiceBackend.generate()`. Translate the subset Kokoro actually # supports to the ISO token its own ALIASES expects; a caller that already diff --git a/bun.lock b/bun.lock index a41ace77d..2601580cb 100644 --- a/bun.lock +++ b/bun.lock @@ -4,9 +4,6 @@ "workspaces": { "": { "name": "omnivoice-studio-monorepo", - "dependencies": { - "posthog-js": "^1.434.14", - }, "devDependencies": { "concurrently": "^10", "playwright": "^1.63.0", @@ -24,37 +21,57 @@ "@electron-toolkit/preload": "^3.0.2", "@electron-toolkit/utils": "^4.0.0", "@fontsource-variable/inter": "^5.3.0", + "@fontsource-variable/source-serif-4": "^5.3.0", "@fontsource/ibm-plex-mono": "^5.3.0", "@lobehub/icons-static-svg": "^1.95.0", + "@radix-ui/react-dialog": "^1.1.23", + "@radix-ui/react-dropdown-menu": "^2.1.24", + "@radix-ui/react-progress": "^1.1.16", + "@radix-ui/react-select": "^2.3.7", + "@radix-ui/react-slider": "^1.4.7", + "@radix-ui/react-slot": "^1.3.3", + "@radix-ui/react-tabs": "^1.1.21", + "@radix-ui/react-toggle": "^1.1.18", + "@radix-ui/react-toggle-group": "^1.1.19", + "@radix-ui/react-tooltip": "^1.2.16", "@scalar/api-reference-react": "^0.9.67", "@tanstack/react-form": "^1.33.5", "@tanstack/react-pacer": "^0.23.0", "@tanstack/react-query": "^5.102.8", "@tanstack/react-router": "^1.170.36", "@tanstack/react-store": "^0.11.1", + "@tanstack/react-table": "^8.21.3", "@tanstack/react-virtual": "^3.14.13", "@tanstack/store": "^0.11.1", "@vidstack/react": "1.15.6", "@xyflow/react": "^12.12.0", "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", "cn": "^0.3.0", + "country-flag-icons": "^1.6.20", "dashjs": "^5.2.1", "electron-updater": "^6.8.9", "hls.js": "^1.7.3", + "html-entities": "^2.6.0", "i18next": "^26.4.2", + "i18next-browser-languagedetector": "^8.2.1", "lucide-react": "^1.46.0", "posthog-js": "^1.434.14", "proxy-agent": "6.5.0", "qrcode": "^1.5.4", "react": "^19.3.0", "react-dom": "^19.3.0", + "react-hot-toast": "^2.6.0", "react-i18next": "^17.0.14", + "react-window": "^2.3.1", "remotion": "4.0.524", "shadcn": "^4.21.0", "sonner": "^2.0.8", + "tailwind-merge": "^3.6.0", "tw-animate-css": "^1.4.0", "wavesurfer.js": "^7.12.12", "word-extractor": "1.0.4", + "zustand": "^5.0.15", }, "devDependencies": { "@tailwindcss/vite": "^4.3.3", @@ -297,6 +314,8 @@ "@fontsource-variable/inter": ["@fontsource-variable/inter@5.3.0", "", {}, "sha512-OupL48va4JNofb97w6NYeF9S7W/kHNKM0Er8Dem5nqi4jeOLrVJDoE8tZEpnMJmtkvNbB1EIPPwHcdkF6b1oUA=="], + "@fontsource-variable/source-serif-4": ["@fontsource-variable/source-serif-4@5.3.0", "", {}, "sha512-9vch9WqxjaaA+1o9Ur8pOgIGbCYLjRReOUel23A6lOpD1syptgjtkORevvNmldJ5kGXQL29onQUqI5Ltz0s3bQ=="], + "@fontsource/ibm-plex-mono": ["@fontsource/ibm-plex-mono@5.3.0", "", {}, "sha512-eTgnZjZEGk1QtD3ZstF+Vclo2HLAni8YMy34/DxllwZvyz1lR/1RF/xTiAquOBO7MvqBx8D2Ig2WCPMVfdZu7Q=="], "@hapi/address": ["@hapi/address@5.1.1", "", { "dependencies": { "@hapi/hoek": "^11.0.2" } }, "sha512-A+po2d/dVoY7cYajycYI43ZbYMXukuopIsqCjh5QzsBCipDtdofHntljDlpccMjIfTy6UOkg+5KPriwYch2bXA=="], @@ -487,6 +506,80 @@ "@quansync/fs": ["@quansync/fs@1.0.0", "", { "dependencies": { "quansync": "^1.0.0" } }, "sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ=="], + "@radix-ui/number": ["@radix-ui/number@1.1.3", "", {}, "sha512-Road2bidD0uu/1BGDOWNdPI06g0lIRy6IF9GZcIrDK2KGItfor8IQwQa+yM2ERgHM1MmHxaxpTzk0/Jp42lNfA=="], + + "@radix-ui/primitive": ["@radix-ui/primitive@1.1.7", "", {}, "sha512-rqWnm76nYT8HoNNqEjpgJ7Pw/DrBj5iBTrmEPo6HTX5+VJyBNOqTdv4g89G63HuR5g0AaENoAcH7Is5fF2kZ8Q=="], + + "@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.15", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.10" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-v4zggRcjadnI+ClKDuijlQEW4tw3NoaeHc/PwpKnLoLLKNUG4InLegkstooLcRIUWCs+8L22dGURCVuFfOKfnA=="], + + "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.15", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-slot": "1.3.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9W+B9NPF0NaaPh/1NJd3+KqsnlLqU9H7T2rvww+fp+T/evVXdNAyYcnfRQZFOjkR1ajQp3yORlqnI8soawLvNA=="], + + "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.5", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA=="], + + "@radix-ui/react-context": ["@radix-ui/react-context@1.2.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RHCUGwKHDr0hDGg4X7ma4JG4/+12qxw8rkh5QKdDldlCvtja6nUx1Ef/8HVrJze81lEsgLQlqjzjGNHantgnQA=="], + + "@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.23", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-focus-guards": "1.1.6", "@radix-ui/react-focus-scope": "1.1.16", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-slot": "1.3.3", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-layout-effect": "1.1.4", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Ksw4WeROkO4rC9k/onilX/Ao2Cr1ku1unMNH+XSCcP4jSXYu7HDsg9n4ojMjVb22XpYjAQ9qfrFlVbru1vXDUA=="], + + "@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-5pzg4FGQNpExhnhT2zlrP1wZFaYCd1K0nYWoFAdcYoYK868IEigqMX3B3f8yIoRlAhAeDWciLI6ZdCKHF9P4Vg=="], + + "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.19", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-effect-event": "0.0.5" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-8g4pfOL9HoKKLWGiypT+dphVqjFfmcXO5GBnhsG6zI+lxAx/8feQpr+1LSN8Re3hiZ+XkLNS4O9ztK11/LzQ6w=="], + + "@radix-ui/react-dropdown-menu": ["@radix-ui/react-dropdown-menu@2.1.24", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-menu": "2.1.24", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-geq8l2rJkxvkXsT9RMgtUE3P8pITFpTsvYpbySi1IH4fZEABD/Gp85myayFgxk0ktljGMJnCbeFkyTusvSvv7g=="], + + "@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.6", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RNOJjfZMTyBM6xYmV3IVGXkPjIhcBAuv48POevAXwrGJhkWZ9p1rFoIS1JFooPuT193AZmRsCPhpoVJxx6OPoQ=="], + + "@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.16", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-wmRZ2WWLvmt6KHy2rNPOdPUjwq5xOHY02+m+udwJTn0aNIox/rkskAvJTyTLGhPK6KgrUjlJUJpgmx/+wFiFIQ=="], + + "@radix-ui/react-id": ["@radix-ui/react-id@1.1.4", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA=="], + + "@radix-ui/react-menu": ["@radix-ui/react-menu@2.1.24", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-focus-guards": "1.1.6", "@radix-ui/react-focus-scope": "1.1.16", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-popper": "1.3.7", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-slot": "1.3.3", "@radix-ui/react-use-callback-ref": "1.1.4", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-uW7RVuU6Lp/ZtfeY4b3kL32zccgEWvPv1+cf17ubYzHa9cL8AHokmk36cG/XEiH/smbQvumnieXX9j/e9RqJWA=="], + + "@radix-ui/react-popper": ["@radix-ui/react-popper@1.3.7", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-layout-effect": "1.1.4", "@radix-ui/react-use-rect": "1.1.4", "@radix-ui/react-use-size": "1.1.4", "@radix-ui/rect": "1.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-UsJrrd7w4wuKKTdvd/DNERVlwSlUcyXzjhyDwBk+3aPOsCjOY6ZSbxuw8E6lZTjjfP8Cpd0J8VVkrYUWyGYXyg=="], + + "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.17", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-vKQLcWypUnwZVvfV7UkGahH2g6ySe8M8R+zYBwPrv5byZ9QAW6cQVvNKo7GgmD+p8aYb6D9JBuvy8/WhOno2wQ=="], + + "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.10", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-3wyzCQ6+ubRA+D4uv9m95JYLXxmOHp05qjrkjeA7uKHHtjpPggQzc6DAb0URl7j67oR0K2foO4ip27TiX037Bw=="], + + "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.10", "", { "dependencies": { "@radix-ui/react-slot": "1.3.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-MucOnzh6hR5mid6VpkbglRAMYMjKLqRnGBbjXkzjK52fuQDd1qbkx78a5P40mkcnVXJdEVxm26E9OPAiUq7nBg=="], + + "@radix-ui/react-progress": ["@radix-ui/react-progress@1.1.16", "", { "dependencies": { "@radix-ui/react-context": "1.2.2", "@radix-ui/react-primitive": "2.1.10" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-5XnomAsoZZCY+KNTxbIghpGqPruZvKFNlvcAljVAOdDRDsH4/OZQxhtwo5wdtoDM5R6MhJBb2sPnDuRFep3lzg=="], + + "@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.19", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-is-hydrated": "0.1.3", "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-V9jI6hDjT7l3jsCQD9bLNvDLM3tH/gdbOTp7Tefp3hbbgCGQoK7tUvrWiRlcoBHIZ809ElXwNQwVo0B98LuTXQ=="], + + "@radix-ui/react-select": ["@radix-ui/react-select@2.3.7", "", { "dependencies": { "@radix-ui/number": "1.1.3", "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-focus-guards": "1.1.6", "@radix-ui/react-focus-scope": "1.1.16", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-popper": "1.3.7", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-slot": "1.3.3", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-layout-effect": "1.1.4", "@radix-ui/react-use-previous": "1.1.4", "@radix-ui/react-visually-hidden": "1.2.11", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-WFGImkmbzcfxeIwq/+4HvRN0pizBwbwQUED4I13ezQsDdfl38ZntN6TmR8XaSzPBqoCToe8rF75j6NPNDSzhbg=="], + + "@radix-ui/react-slider": ["@radix-ui/react-slider@1.4.7", "", { "dependencies": { "@radix-ui/number": "1.1.3", "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-layout-effect": "1.1.4", "@radix-ui/react-use-previous": "1.1.4", "@radix-ui/react-use-size": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-mTSLf1GC/C0moWjTbvCM6Qn/gBjvlFt1azuWF2v7MN5C3Zq2U2J2lN3ZEYkpujuOU5Ro7A28wkviSxaKnG0BYg=="], + + "@radix-ui/react-slot": ["@radix-ui/react-slot@1.3.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.5" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-qx7oqnYbxnK9kYI9m317qmFmEgo6ywqWvbTogdj7cL9p3/yx4M48p7Rnw5z3H890cL/ow/EeWJsuTykeZVXP5Q=="], + + "@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.21", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-use-controllable-state": "1.2.6" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-UKxJlZid7FVtsk/WTxj4i4uSEgj2Au+KBbS7SQyTlzMhhn+86Cz3tISZdTa87bfEfcuvZezf2ZsxD4xuEKtkog=="], + + "@radix-ui/react-toggle": ["@radix-ui/react-toggle@1.1.18", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7lonPlKfSacd20GlOBx2ltuVKz9oqWYZz+oMQyOltw6t1y2nyftj2ZmwwUHYn49kqfDWcp8dNZm5NgV+5Z+mug=="], + + "@radix-ui/react-toggle-group": ["@radix-ui/react-toggle-group@1.1.19", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-toggle": "1.1.18", "@radix-ui/react-use-controllable-state": "1.2.6" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-OtnwuSVjd1Ofi+AdnvhsjQdyuhCDwYs1w9RyB5BN/OavXOVQo42SYqQjwUnbPnaiPFBpQ9aX70dWeee+v2oBLA=="], + + "@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.2.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-popper": "1.3.7", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-slot": "1.3.3", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-layout-effect": "1.1.4", "@radix-ui/react-visually-hidden": "1.2.11" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-6EamKFRRnlpdadndbZ6LMwycfwkwPte1B42hs6QA0gYhjaOKqW4PZ4pjaW9UrlDX5eVt/OjncE7BFTPL5nmZhg=="], + + "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-R6OUY2e2fA6Yn6s+VSx5KBV6Nx8LQEhu+cz7LCej18rQ1HLyg9PSC9jP/ZNx0o6FAIK9c0F1kHylzSxKsdlkrQ=="], + + "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.6", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-use-effect-event": "0.0.5", "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-uEQJGT97ZA/TgP/Hydw47lHu+/vQj6z/0jA+WeTbK1o9Rx45GImjpD0tc3W5ad3D6XTSR6e1yEO0FvGq6WQfVQ=="], + + "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.5", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg=="], + + "@radix-ui/react-use-is-hydrated": ["@radix-ui/react-use-is-hydrated@0.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-umO/aJ+82CpOnhDZUTbILCQf7kU/g0iv+oGs/Q8jw7IkhWBzaEP4sA268PhFAJTFetbwp3ICc6ktpI4TqtxcIw=="], + + "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw=="], + + "@radix-ui/react-use-previous": ["@radix-ui/react-use-previous@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-XoSLhbRbqxFtgJoi2fNHA3C6pDlY34x508vUpUGoFZfvePfHXHbE1lC4FYFMnJWgiCRroSTw6fOsXQoVS9RwZg=="], + + "@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.4", "", { "dependencies": { "@radix-ui/rect": "1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-cSOCh6JlkmfjLyNcLiu2nB4v+nm+dkZ+Q5KHWk/soo4U7ZLiEQFKHK9/YmtBHjfCEaU43IBKQOc4/uJmCaiCTQ=="], + + "@radix-ui/react-use-size": ["@radix-ui/react-use-size@1.1.4", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-D3anSY15EJoxrihpsXI6SMrmmonnQtR2ni7arO+Lfdg3O95b9hNXxONk8jA5C8ANdF/h5HMAxejgs8PWJ6rlhw=="], + + "@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.2.11", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.10" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-NFS86RYYZb4/exihaESBGOpMJFz8MGLAfu3mOBSGByVnVPC9JPASfYubxd/8KbkQK0sYAv8lVQDEQukDX/qXvQ=="], + + "@radix-ui/rect": ["@radix-ui/rect@1.1.3", "", {}, "sha512-JtyZR+mqgBibTo8xea3B6ZRmzZiM/YeVBtUkas6zMuXjAlfIFIW2FgqeM9eLyvEaYX66vr6DJMK+4U6LV0KhNw=="], + "@replit/codemirror-css-color-picker": ["@replit/codemirror-css-color-picker@6.3.0", "", { "peerDependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0" } }, "sha512-19biDANghUm7Fz7L1SNMIhK48tagaWuCOHj4oPPxc7hxPGkTVY2lU/jVZ8tsbTKQPVG7BO2CBDzs7CBwb20t4A=="], "@rolldown/binding-android-arm-eabi": ["@rolldown/binding-android-arm-eabi@1.2.7", "", { "os": "android", "cpu": "arm" }, "sha512-EypzgnYCwyVY4NDHKzGmNJT5b+XaQEBniHxsMdeIQLB/tcCzZnhqrzHpZFbX9iaxx+5RiB8caATBtfvZP7zVxQ=="], @@ -661,6 +754,8 @@ "@tanstack/react-store": ["@tanstack/react-store@0.11.1", "", { "dependencies": { "@tanstack/store": "0.11.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-HaIGKI3YLmjBYIvy5DFDY23oNaYZIsTZfngey07Uh5iLVJgM3bIGCnZeOFOqzjFld9JHWcaHJnasD/bKoGKwJQ=="], + "@tanstack/react-table": ["@tanstack/react-table@8.21.3", "", { "dependencies": { "@tanstack/table-core": "8.21.3" }, "peerDependencies": { "react": ">=16.8", "react-dom": ">=16.8" } }, "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww=="], + "@tanstack/react-virtual": ["@tanstack/react-virtual@3.14.13", "", { "dependencies": { "@tanstack/virtual-core": "3.17.11" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-JbDTAwtzZ99aOeCrAfW5EsE5KSq5RWh6Af2dtFwyLIIk48Ja7vm6n4axu/43T3vfjFnEGJalxJ1wyYjSQD6bSg=="], "@tanstack/router-core": ["@tanstack/router-core@1.171.30", "", { "dependencies": { "@tanstack/history": "1.162.4", "cookie-es": "^3.0.0", "seroval": "^1.6.2", "seroval-plugins": "^1.6.2" } }, "sha512-wtS1yCAb/k5CJBauvrCyqf2n4/kRc3aiz81tFBJ1QXH4Utsu81xFTMq15AdmNWgWmt2UstUSMfWi4Ua7ph2F+w=="], @@ -669,6 +764,8 @@ "@tanstack/store": ["@tanstack/store@0.11.1", "", {}, "sha512-mzTOBhypOuDJAy/D8n2MfUZ1HFkXnmSETviRyhqEC8LUE7/IZQExOTxMANj3KjTofYTkFNpBY67qaVrT41YccA=="], + "@tanstack/table-core": ["@tanstack/table-core@8.21.3", "", {}, "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg=="], + "@tanstack/virtual-core": ["@tanstack/virtual-core@3.17.11", "", {}, "sha512-+ILjvtHup6Y2hzQ6YzwMgX1Q+oQpxEGOXCEsCNaPoIP0VxMbizIBTmYTDtkerkIQS8/CbP1BRuyt8V/8BCsy1g=="], "@tanstack/vue-virtual": ["@tanstack/vue-virtual@3.13.36", "", { "dependencies": { "@tanstack/virtual-core": "3.17.8" }, "peerDependencies": { "vue": "^2.7.0 || ^3.0.0" } }, "sha512-gKpExv4RbB9luVG+SucTXoqPZv/gzu/Yvz6BNO+8kpNxJ2x+I/ulryzl5W9BRciahZGp5Tls3Dp5XP1ztVGbMw=="], @@ -1097,6 +1194,8 @@ "cosmiconfig": ["cosmiconfig@9.0.2", "", { "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg=="], + "country-flag-icons": ["country-flag-icons@1.6.20", "", {}, "sha512-py8JiEKzjhYw6HPJ0L7SxLgCYim36UPRTZX43/kqGueUCZLSvnrqAiwW8HtQibur7mdkFQUkjOgdK+o/9FBtaw=="], + "crelt": ["crelt@1.0.7", "", {}, "sha512-aK6BbWfhf4U/wCcLHKPJl/xa6VkVstRaPywWtMKGwuOLc/wZTyQYuoxgvZnNsBvv7Kg3YTBQYYBCggcviQczuA=="], "cross-dirname": ["cross-dirname@0.1.0", "", {}, "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q=="], @@ -1181,6 +1280,8 @@ "detect-node": ["detect-node@2.1.0", "", {}, "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g=="], + "detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="], + "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], "diff": ["diff@8.0.4", "", {}, "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw=="], @@ -1351,6 +1452,8 @@ "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], + "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="], + "get-own-enumerable-keys": ["get-own-enumerable-keys@1.0.0", "", {}, "sha512-PKsK2FSrQCyxcGHsGrLDcK0lx+0Ke+6e8KFFozA9/fIQLhQzPaRvJFdcz7+Axg3jUH/Mq+NI4xa5u/UT2tQskA=="], "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], @@ -1455,6 +1558,8 @@ "i18next": ["i18next@26.4.2", "", { "peerDependencies": { "typescript": "^5 || ^6 || ^7" }, "optionalPeers": ["typescript"] }, "sha512-RX+R0VLg13IbvRuJSxnqykUFS9vQZTl8wYpWPCIUDWVrSGjsQywB5Y+pjzrkboxGAuYfJZVH1InFTdgBdxq6ug=="], + "i18next-browser-languagedetector": ["i18next-browser-languagedetector@8.2.1", "", { "dependencies": { "@babel/runtime": "^7.23.2" } }, "sha512-bZg8+4bdmaOiApD7N7BPT9W8MLZG+nPTOFlLiJiT8uzKXFjhxw4v2ierCXOwB5sFDMtuA5G4kgYZ0AznZxQ/cw=="], + "iconv-lite": ["iconv-lite@0.7.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ=="], "identifier-regex": ["identifier-regex@1.1.0", "", { "dependencies": { "reserved-identifiers": "^1.0.0" } }, "sha512-SLX4H/vtcYlYnL7XqnuJKHU7Z8517TgsW9nmQiGOgMCjQ8V/deLYu6bEmbGoXe7WMMhc9+EUGyFFneHja8KabA=="], @@ -1935,10 +2040,20 @@ "react-dom": ["react-dom@19.3.0", "", { "dependencies": { "scheduler": "^0.28.0" }, "peerDependencies": { "react": "^19.3.0" } }, "sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q=="], + "react-hot-toast": ["react-hot-toast@2.6.1", "", { "dependencies": { "csstype": "^3.1.3", "goober": "^2.1.16" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": ">=16", "react-dom": ">=16" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-gjFsf05dxcku0FkyMtFH+XmYFdA2odXfBVknEr/IZ+XpUjwsgvtY2616sOpUynK+l9ykQDRNpaJ1hYfuximUiA=="], + "react-i18next": ["react-i18next@17.0.14", "", { "dependencies": { "@babel/runtime": "^7.29.7", "html-parse-stringify": "^4.0.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "i18next": ">= 26.2.0", "react": ">= 16.8.0", "react-dom": "*", "react-native": "*", "typescript": "^5 || ^6 || ^7" }, "optionalPeers": ["react-dom", "react-native", "typescript"] }, "sha512-ZpMBfJL3BiXPuYHj5QMY1GwvKJNhE1vCxOJQ8BoMBdHP5XONTfi/Qss1nuRlnFdIl72PKo2jPmw+fxuLjRFgaQ=="], "react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="], + "react-remove-scroll": ["react-remove-scroll@2.7.2", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q=="], + + "react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="], + + "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="], + + "react-window": ["react-window@2.3.3", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-uu/dTwysXp+YL+i5GW/cC/3JrqyE7oE6DYXYVlTeMaDSDgCI+UGo+XCKwXfS8uoFPih8TJYTnikqjAnbDvn75Q=="], + "read-binary-file-arch": ["read-binary-file-arch@1.0.6", "", { "dependencies": { "debug": "^4.3.4" }, "bin": { "read-binary-file-arch": "cli.js" } }, "sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg=="], "readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], @@ -2131,7 +2246,7 @@ "tagged-tag": ["tagged-tag@1.0.0", "", {}, "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng=="], - "tailwind-merge": ["tailwind-merge@3.5.0", "", {}, "sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A=="], + "tailwind-merge": ["tailwind-merge@3.7.0", "", {}, "sha512-XPPUyAc+cvspz3lHTcR/QgPfW2A0lv/xQNIjX3HGhLR+Nq2lHaLq5MtTesHn8GUr3W3DguT2KT5x3NVgRtYwmA=="], "tailwindcss": ["tailwindcss@4.3.3", "", {}, "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ=="], @@ -2243,6 +2358,10 @@ "update-browserslist-db": ["update-browserslist-db@1.3.2", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UQ+MSxlhRm1bzjhU+DcuXfjFO1FzNtqhK5+9Yvlp90ItDLk5vT932A0rFu619nf7RVS+Y/VeaUW1jaRDqZ8VJw=="], + "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="], + + "use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="], + "use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="], "utf8-byte-length": ["utf8-byte-length@1.0.5", "", {}, "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA=="], @@ -2351,7 +2470,7 @@ "zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="], - "zustand": ["zustand@4.5.7", "", { "dependencies": { "use-sync-external-store": "^1.2.2" }, "peerDependencies": { "@types/react": ">=16.8", "immer": ">=9.0.6", "react": ">=16.8" }, "optionalPeers": ["@types/react", "immer", "react"] }, "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw=="], + "zustand": ["zustand@5.0.15", "", { "peerDependencies": { "@types/react": ">=18.0.0", "immer": ">=9.0.6", "react": ">=18.0.0", "use-sync-external-store": ">=1.2.0" }, "optionalPeers": ["@types/react", "immer", "react", "use-sync-external-store"] }, "sha512-MpSEjRiBkA9crSYeOUH32rJC7SVqAbm0Fqcqge/bUi2PPoLcBWKOsG+C8mevmpr8TwXHBVkChbbJiyvkE+i/3A=="], "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], @@ -2419,6 +2538,8 @@ "@scalar/types/zod": ["zod@4.5.4", "", {}, "sha512-sC95tT5iHHH9gtpj6A81kh+NEaRAUFN+qlUPDUbRfOMvNf5QCBqsb3WgvnpVtK5Y+4UfA6KqufotuTvMGiTlsA=="], + "@scalar/use-hooks/tailwind-merge": ["tailwind-merge@3.5.0", "", {}, "sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A=="], + "@tailwindcss/node/lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="], "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" }, "bundled": true }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="], @@ -2457,6 +2578,8 @@ "@vue/compiler-sfc/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + "@xyflow/react/zustand": ["zustand@4.5.7", "", { "dependencies": { "use-sync-external-store": "^1.2.2" }, "peerDependencies": { "@types/react": ">=16.8", "immer": ">=9.0.6", "react": ">=16.8" }, "optionalPeers": ["@types/react", "immer", "react"] }, "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw=="], + "accepts/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], "app-builder-lib/@electron/get": ["@electron/get@3.1.0", "", { "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", "fs-extra": "^8.1.0", "got": "^11.8.5", "progress": "^2.0.3", "semver": "^6.2.0", "sumchecker": "^3.0.1" }, "optionalDependencies": { "global-agent": "^3.0.0" } }, "sha512-F+nKc0xW+kVbBRhFzaMgPy3KwmuNTYX1fx6+FxxoSnNgwYX6LD7AKBTWkU0MQ6IBoe7dz069CNkR673sPAgkCQ=="], diff --git a/deploy/Dockerfile b/deploy/Dockerfile index 3098885fe..e97f5d58b 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -19,7 +19,7 @@ COPY electron/package.json ./electron/ RUN bun install --frozen-lockfile -# Build the maintained Electron renderer as the browser UI. `frontend/src` +# Build the maintained Electron renderer as the browser UI. `electron/src/shared` # contains transitional shared modules only; it has no app entry point. COPY frontend/ ./frontend/ COPY electron/ ./electron/ diff --git a/electron/CONTRACT.md b/electron/CONTRACT.md index f442132bf..2ef05dcd2 100644 --- a/electron/CONTRACT.md +++ b/electron/CONTRACT.md @@ -53,7 +53,7 @@ Live dictation uses a WebSocket, which cannot pass through the app protocol HTTP `apiJson(path, init?)`; `audioUrl(filename)` → `/api/audio/`; `profileAudioUrl(id)` → `/api/profiles//audio`. - `@/lib/api/generate.ts`: `generateClone(input: CloneGenerateInput, opts?: { signal?: AbortSignal; onProgress?: (pct: number|null) => void }): Promise`; - `sanitizeInstruct(free: string): { instruct: string; unsupported: string[]; duplicates: string[]; conflicts: string[] }` (port of frontend/src/utils/voiceInstruct.js buildDesignInstruct with empty vdStates); + `sanitizeInstruct(free: string): { instruct: string; unsupported: string[]; duplicates: string[]; conflicts: string[] }` (port of electron/src/shared/utils/voiceInstruct.js buildDesignInstruct with empty vdStates); `CLONE_MAX_SECONDS = 15`, `REF_HARD_MAX_SECONDS = 75`. - `@/lib/api/profiles.ts`: `listProfiles()`, `createCloneProfile({ name, refAudio, refAudioName, refText, instruct, language })`, `deleteProfile(id)`. - `@/lib/api/history.ts`: `listHistory()`, `clearHistory()`, `deleteHistoryItem(id)`, `setHistoryStarred(id, starred)`. diff --git a/electron/electron.vite.config.ts b/electron/electron.vite.config.ts index 3b076932e..f97531ac2 100644 --- a/electron/electron.vite.config.ts +++ b/electron/electron.vite.config.ts @@ -75,6 +75,7 @@ export default defineConfig({ resolve: { alias: { '@': resolve(__dirname, 'src/renderer/src'), + '@shared': resolve(__dirname, 'src/shared'), // Scalar's optional AI client reaches a CommonJS browser entry that // native ESM cannot import by name. Mirror its browser API as real ESM. '@vercel/oidc': resolve(__dirname, 'src/renderer/src/lib/vercel-oidc-browser.ts'), diff --git a/electron/package.json b/electron/package.json index 0252e69eb..9e83149c9 100644 --- a/electron/package.json +++ b/electron/package.json @@ -39,12 +39,24 @@ "@electron-toolkit/preload": "^3.0.2", "@electron-toolkit/utils": "^4.0.0", "@fontsource-variable/inter": "^5.3.0", + "@fontsource-variable/source-serif-4": "^5.3.0", "@fontsource/ibm-plex-mono": "^5.3.0", "@lobehub/icons-static-svg": "^1.95.0", + "@radix-ui/react-dialog": "^1.1.23", + "@radix-ui/react-dropdown-menu": "^2.1.24", + "@radix-ui/react-progress": "^1.1.16", + "@radix-ui/react-select": "^2.3.7", + "@radix-ui/react-slider": "^1.4.7", + "@radix-ui/react-slot": "^1.3.3", + "@radix-ui/react-tabs": "^1.1.21", + "@radix-ui/react-toggle": "^1.1.18", + "@radix-ui/react-toggle-group": "^1.1.19", + "@radix-ui/react-tooltip": "^1.2.16", "@scalar/api-reference-react": "^0.9.67", "@tanstack/react-form": "^1.33.5", "@tanstack/react-pacer": "^0.23.0", "@tanstack/react-query": "^5.102.8", + "@tanstack/react-table": "^8.21.3", "@tanstack/react-router": "^1.170.36", "@tanstack/react-store": "^0.11.1", "@tanstack/react-virtual": "^3.14.13", @@ -52,24 +64,32 @@ "@vidstack/react": "1.15.6", "@xyflow/react": "^12.12.0", "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", "cn": "^0.3.0", + "country-flag-icons": "^1.6.20", "dashjs": "^5.2.1", "electron-updater": "^6.8.9", "hls.js": "^1.7.3", + "html-entities": "^2.6.0", "i18next": "^26.4.2", + "i18next-browser-languagedetector": "^8.2.1", "lucide-react": "^1.46.0", "posthog-js": "^1.434.14", "proxy-agent": "6.5.0", "qrcode": "^1.5.4", "react": "^19.3.0", "react-dom": "^19.3.0", + "react-hot-toast": "^2.6.0", "react-i18next": "^17.0.14", + "react-window": "^2.3.1", "remotion": "4.0.524", "shadcn": "^4.21.0", "sonner": "^2.0.8", + "tailwind-merge": "^3.6.0", "tw-animate-css": "^1.4.0", "wavesurfer.js": "^7.12.12", - "word-extractor": "1.0.4" + "word-extractor": "1.0.4", + "zustand": "^5.0.15" }, "devDependencies": { "@tailwindcss/vite": "^4.3.3", diff --git a/electron/src/main/crash-journal.ts b/electron/src/main/crash-journal.ts index f82ac19ca..d79f85869 100644 --- a/electron/src/main/crash-journal.ts +++ b/electron/src/main/crash-journal.ts @@ -1,7 +1,7 @@ import { readFileSync, writeFileSync, renameSync } from 'node:fs'; import type { NativeCrashRecord } from '../preload/index.d'; -import { nativeCrashExcerpt } from '../../../frontend/src/utils/crashReport'; -import { scrubText } from '../../../frontend/src/utils/scrub'; +import { nativeCrashExcerpt } from '../shared/utils/crashReport'; +import { scrubText } from '../shared/utils/scrub'; /** Small version-scoped local journal. Read failures must never block startup. */ export class CrashJournal { diff --git a/electron/src/main/crash-report.test.ts b/electron/src/main/crash-report.test.ts index 37062dd57..3270207d8 100644 --- a/electron/src/main/crash-report.test.ts +++ b/electron/src/main/crash-report.test.ts @@ -1,6 +1,6 @@ // @vitest-environment node import { expect, it } from 'vitest'; -import { clampCrashTail } from '../../../frontend/src/utils/crashReport'; +import { clampCrashTail } from '../shared/utils/crashReport'; it.each(['Fatal Python error: Segmentation fault', 'Windows fatal exception: access violation'])( 'preserves native fault frames under the report character limit: %s', diff --git a/electron/src/main/main-error-journal.ts b/electron/src/main/main-error-journal.ts index b3cb51300..23d7cfb95 100644 --- a/electron/src/main/main-error-journal.ts +++ b/electron/src/main/main-error-journal.ts @@ -1,6 +1,6 @@ import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'; import { dirname } from 'node:path'; -import { scrubText } from '../../../frontend/src/utils/scrub'; +import { scrubText } from '../shared/utils/scrub'; const MAX_RECORDS = 20; const MAX_DETAIL = 20_000; diff --git a/electron/src/renderer/src/components/analytics-consent.tsx b/electron/src/renderer/src/components/analytics-consent.tsx index 710e9b949..c12d43427 100644 --- a/electron/src/renderer/src/components/analytics-consent.tsx +++ b/electron/src/renderer/src/components/analytics-consent.tsx @@ -12,7 +12,7 @@ import { capturePageview, disableAnalytics, enableAnalytics, -} from '../../../../../frontend/src/utils/analytics'; +} from '@shared/utils/analytics'; import { routeBreadcrumb } from '@/lib/report-breadcrumb'; interface AnalyticsState { diff --git a/electron/src/renderer/src/components/app-shell/repair-agent-dock.tsx b/electron/src/renderer/src/components/app-shell/repair-agent-dock.tsx index 2296271db..df331dd37 100644 --- a/electron/src/renderer/src/components/app-shell/repair-agent-dock.tsx +++ b/electron/src/renderer/src/components/app-shell/repair-agent-dock.tsx @@ -27,7 +27,7 @@ import { getBridge } from '@/components/bridge'; import { Button } from '@/components/ui/button'; import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'; import { cn } from '@/lib/utils'; -import { getFrontendLogs } from '../../../../../../frontend/src/utils/consoleBuffer'; +import { getFrontendLogs } from '@shared/utils/consoleBuffer'; import { useBackendStatus } from '@/hooks/use-backend-status'; import type { RepairAgentId, diff --git a/electron/src/renderer/src/components/app-shell/status-bar.tsx b/electron/src/renderer/src/components/app-shell/status-bar.tsx index 321a39841..a3c07be70 100644 --- a/electron/src/renderer/src/components/app-shell/status-bar.tsx +++ b/electron/src/renderer/src/components/app-shell/status-bar.tsx @@ -34,7 +34,7 @@ import { ComputeVendorIcon, formatComputeRuntime } from '@/components/compute-ve import { Popover, PopoverContent, PopoverTrigger } from '@/components/popover'; import { ComputeTargetChoices } from '@/components/compute-target-choices'; import { useComputeRuntime, useComputeTarget } from '@/hooks/use-compute-target'; -import type { BatchJob } from '../../../../../../frontend/src/api/batch-types'; +import type { BatchJob } from '@shared/api/batch-types'; import { IDLE_STATUS_POLL_MS, batchStatusPollMs, diff --git a/electron/src/renderer/src/components/crash-details.tsx b/electron/src/renderer/src/components/crash-details.tsx index cb64b4192..0659a3d7b 100644 --- a/electron/src/renderer/src/components/crash-details.tsx +++ b/electron/src/renderer/src/components/crash-details.tsx @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; import { useBackendStatus } from '@/hooks/use-backend-status'; -import { scrubText } from '../../../../../frontend/src/utils/scrub'; -import { describeExitCode } from '../../../../../frontend/src/utils/nativeExit'; +import { scrubText } from '@shared/utils/scrub'; +import { describeExitCode } from '@shared/utils/nativeExit'; import { ReportBug } from './report-bug'; import { getBridge } from './bridge'; diff --git a/electron/src/renderer/src/components/dictation-demo.tsx b/electron/src/renderer/src/components/dictation-demo.tsx index 91e3c91a8..4beaebbfe 100644 --- a/electron/src/renderer/src/components/dictation-demo.tsx +++ b/electron/src/renderer/src/components/dictation-demo.tsx @@ -1,7 +1,7 @@ import { useEffect, useRef, useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; -import { DICTATION_SCRIPTS } from '../../../../../frontend/src/utils/dictationScripts'; +import { DICTATION_SCRIPTS } from '@shared/utils/dictationScripts'; import { apiFetch, apiJson, apiPath, ApiError } from '@/lib/api/client'; import { Button } from './ui/button'; import { AudioPreviewButton } from './audio-preview-button'; diff --git a/electron/src/renderer/src/components/error-boundary.tsx b/electron/src/renderer/src/components/error-boundary.tsx index d57e251ab..6274e78da 100644 --- a/electron/src/renderer/src/components/error-boundary.tsx +++ b/electron/src/renderer/src/components/error-boundary.tsx @@ -2,17 +2,17 @@ import { classifyError, urlFor, type ErrorClass, -} from '../../../../../frontend/src/utils/errorDocsMap'; +} from '@shared/utils/errorDocsMap'; import { ExternalLink } from './external-link'; -import { buildIssueSearchUrl } from '../../../../../frontend/src/utils/bugReportDocument'; +import { buildIssueSearchUrl } from '@shared/utils/bugReportDocument'; import { Component, useEffect, type ReactNode, type ErrorInfo } from 'react'; import { useTranslation } from 'react-i18next'; import { BotIcon, CircleAlertIcon } from 'lucide-react'; -import { scrubText } from '../../../../../frontend/src/utils/scrub'; +import { scrubText } from '@shared/utils/scrub'; import { ReportBug } from './report-bug'; import { Button } from './ui/button'; import { openRepairAgent } from '@/lib/repair-agent-events'; -import { captureException } from '../../../../../frontend/src/utils/analytics'; +import { captureException } from '@shared/utils/analytics'; const MODULE_RETRY_PREFIX = 'voicestudio.moduleRetry:'; const reloadRenderer = () => window.location.reload(); diff --git a/electron/src/renderer/src/components/first-sound-handoff.tsx b/electron/src/renderer/src/components/first-sound-handoff.tsx index a1c9ba3f6..ebe2fc790 100644 --- a/electron/src/renderer/src/components/first-sound-handoff.tsx +++ b/electron/src/renderer/src/components/first-sound-handoff.tsx @@ -3,12 +3,12 @@ import { useTranslation } from 'react-i18next'; import { useGenerateClone } from '@/hooks/use-generate'; import { router } from '@/router'; import { writeDraft } from '@/features/design/design-draft'; -import defaults from '../../../../../frontend/src/utils/firstSound.json'; +import defaults from '@shared/utils/firstSound.json'; import { instructToVdStates, mergeDescribedAttrs, -} from '../../../../../frontend/src/utils/voiceInstruct'; -import { pickDesignSeed } from '../../../../../frontend/src/utils/seed'; +} from '@shared/utils/voiceInstruct'; +import { pickDesignSeed } from '@shared/utils/seed'; import { FIRST_SOUND_EVENT } from '@/lib/first-sound'; /** diff --git a/electron/src/renderer/src/components/markdown-lite.tsx b/electron/src/renderer/src/components/markdown-lite.tsx index ea8b2bce0..58aca9f6e 100644 --- a/electron/src/renderer/src/components/markdown-lite.tsx +++ b/electron/src/renderer/src/components/markdown-lite.tsx @@ -3,7 +3,7 @@ import { inlineSegments, parseBlocks, type MarkdownBlock, -} from '../../../../../frontend/src/utils/markdownLite'; +} from '@shared/utils/markdownLite'; function InlineMarkdown({ text }: { text: string }) { return inlineSegments(text).map((segment, index) => { diff --git a/electron/src/renderer/src/components/media-player.tsx b/electron/src/renderer/src/components/media-player.tsx index ccf6a13db..204ed7213 100644 --- a/electron/src/renderer/src/components/media-player.tsx +++ b/electron/src/renderer/src/components/media-player.tsx @@ -17,7 +17,7 @@ import { RemotionProviderLoader } from '@vidstack/react/player/remotion'; import { useEffect, useMemo, useRef, type RefObject } from 'react'; import { claimPlayback } from '@/lib/audio/playback'; import { useAecEnabled } from '@/lib/store/dictation-settings'; -import { attachPlaybackTap } from '../../../../../frontend/src/utils/aec/playbackTap'; +import { attachPlaybackTap } from '@shared/utils/aec/playbackTap'; export type { MediaPlayerInstance }; export { useMediaState } from '@vidstack/react'; diff --git a/electron/src/renderer/src/components/pipeline-failure.tsx b/electron/src/renderer/src/components/pipeline-failure.tsx index 54d1820d4..5511da65a 100644 --- a/electron/src/renderer/src/components/pipeline-failure.tsx +++ b/electron/src/renderer/src/components/pipeline-failure.tsx @@ -2,7 +2,7 @@ import { AlertCircleIcon, CopyIcon, XIcon } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import type { ReactNode } from 'react'; import { toast } from 'sonner'; -import { urlFor } from '../../../../../frontend/src/utils/errorDocsMap'; +import { urlFor } from '@shared/utils/errorDocsMap'; import type { PublicFailure } from '@/lib/api/failure'; import { cn } from '@/lib/utils'; import { ExternalLink } from './external-link'; diff --git a/electron/src/renderer/src/components/report-bug.test.tsx b/electron/src/renderer/src/components/report-bug.test.tsx index 7a5d5c5d8..8ef5638ab 100644 --- a/electron/src/renderer/src/components/report-bug.test.tsx +++ b/electron/src/renderer/src/components/report-bug.test.tsx @@ -14,11 +14,11 @@ vi.mock('@/hooks/use-backend-status', () => ({ })); import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'; import { afterEach, beforeEach, expect, it, vi } from 'vitest'; -import { addBreadcrumb, clearBreadcrumbs } from '../../../../../frontend/src/utils/breadcrumbs'; +import { addBreadcrumb, clearBreadcrumbs } from '@shared/utils/breadcrumbs'; import { _resetBackendContactForTests, recordBackendContact, -} from '../../../../../frontend/src/utils/backendContact'; +} from '@shared/utils/backendContact'; const mock = vi.hoisted(() => ({ crashed: false, native: true, diff --git a/electron/src/renderer/src/components/report-bug.tsx b/electron/src/renderer/src/components/report-bug.tsx index 95464aaa7..67aacf66d 100644 --- a/electron/src/renderer/src/components/report-bug.tsx +++ b/electron/src/renderer/src/components/report-bug.tsx @@ -1,15 +1,15 @@ import { useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { composeBugReportUrl } from '../../../../../frontend/src/utils/bugReportDocument'; -import { formatBreadcrumbs } from '../../../../../frontend/src/utils/breadcrumbs'; -import { contactAge, lastBackendContact } from '../../../../../frontend/src/utils/backendContact'; -import { clampCrashTail } from '../../../../../frontend/src/utils/crashReport'; -import { scrubText } from '../../../../../frontend/src/utils/scrub'; -import { describeExitCode, isNativeFaultExit } from '../../../../../frontend/src/utils/nativeExit'; +import { composeBugReportUrl } from '@shared/utils/bugReportDocument'; +import { formatBreadcrumbs } from '@shared/utils/breadcrumbs'; +import { contactAge, lastBackendContact } from '@shared/utils/backendContact'; +import { clampCrashTail } from '@shared/utils/crashReport'; +import { scrubText } from '@shared/utils/scrub'; +import { describeExitCode, isNativeFaultExit } from '@shared/utils/nativeExit'; import { _adaptLastRunCrash, type LastRunCrashRecord, -} from '../../../../../frontend/src/utils/runCrashRecord'; +} from '@shared/utils/runCrashRecord'; import { getBackendStatusSnapshot } from '@/hooks/use-backend-status'; import { apiJson } from '@/lib/api/client'; import { router } from '@/router'; diff --git a/electron/src/renderer/src/components/setup-gate.tsx b/electron/src/renderer/src/components/setup-gate.tsx index 1762a0259..7f3230c45 100644 --- a/electron/src/renderer/src/components/setup-gate.tsx +++ b/electron/src/renderer/src/components/setup-gate.tsx @@ -6,7 +6,7 @@ import { useQuery, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { Button } from '@/components/ui/button'; import { apiJson } from '@/lib/api/client'; -import type { PreflightReport } from '../../../../../frontend/src/api/setup-types'; +import type { PreflightReport } from '@shared/api/setup-types'; import { SystemPreflight } from '@/features/settings/system-preflight'; import { PermissionsSettings } from '@/features/settings/permissions-settings'; import { SetupMediaEngine } from '@/features/settings/media-tools'; diff --git a/electron/src/renderer/src/components/web-auth-gate.tsx b/electron/src/renderer/src/components/web-auth-gate.tsx index 55bec87ad..d145c4153 100644 --- a/electron/src/renderer/src/components/web-auth-gate.tsx +++ b/electron/src/renderer/src/components/web-auth-gate.tsx @@ -1,7 +1,7 @@ import { useEffect, useRef, useState, type FormEvent, type ReactNode } from 'react'; import { useTranslation } from 'react-i18next'; import { KeyRoundIcon } from 'lucide-react'; -import { exchangeApiKey } from '../../../../../frontend/src/api/authSession'; +import { exchangeApiKey } from '@shared/api/authSession'; import { absoluteApiBase, ApiError, apiFetch } from '@/lib/api/client'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; diff --git a/electron/src/renderer/src/features/batch/batch-page.tsx b/electron/src/renderer/src/features/batch/batch-page.tsx index 7d7a1f7c9..402d3b32c 100644 --- a/electron/src/renderer/src/features/batch/batch-page.tsx +++ b/electron/src/renderer/src/features/batch/batch-page.tsx @@ -32,10 +32,10 @@ import { useTtsReadiness } from '@/hooks/use-tts-readiness'; import { getBridge } from '@/components/bridge'; import { apiJson, apiPath, describeError } from '@/lib/api/client'; import { saveExport } from '@/lib/export-history'; -import { LANG_CODES } from '../../../../../../frontend/src/utils/languages'; -import { PRESETS } from '../../../../../../frontend/src/utils/constants'; -import type { BatchJob } from '../../../../../../frontend/src/api/batch-types'; -import { generationFailureMessage } from '../../../../../../frontend/src/utils/generationFailureMessage'; +import { LANG_CODES } from '@shared/utils/languages'; +import { PRESETS } from '@shared/utils/constants'; +import type { BatchJob } from '@shared/api/batch-types'; +import { generationFailureMessage } from '@shared/utils/generationFailureMessage'; import { enqueueVideos } from './enqueue'; import { useTranslationEngines } from '@/features/settings/translation-settings'; const languageOptions = LANG_CODES.map((item) => item.label); diff --git a/electron/src/renderer/src/features/batch/watch-folder.tsx b/electron/src/renderer/src/features/batch/watch-folder.tsx index 0367d2ee9..48a6337c1 100644 --- a/electron/src/renderer/src/features/batch/watch-folder.tsx +++ b/electron/src/renderer/src/features/batch/watch-folder.tsx @@ -8,7 +8,7 @@ import { describeError } from '@/lib/api/client'; import { createIngestTracker, WATCH_POLL_MS, -} from '../../../../../../frontend/src/utils/watchFolderTracker'; +} from '@shared/utils/watchFolderTracker'; import type { WatchSelection } from '../../../../preload/index.d'; export function WatchFolder({ diff --git a/electron/src/renderer/src/features/clone/profile-usage.tsx b/electron/src/renderer/src/features/clone/profile-usage.tsx index 970aa386c..8bc2125d7 100644 --- a/electron/src/renderer/src/features/clone/profile-usage.tsx +++ b/electron/src/renderer/src/features/clone/profile-usage.tsx @@ -3,7 +3,7 @@ import { useQuery } from '@tanstack/react-query'; import { useNavigate } from '@tanstack/react-router'; import { useTranslation } from 'react-i18next'; import { FolderOpenIcon } from 'lucide-react'; -import type { ProfileUsage } from '../../../../../../frontend/src/api/types'; +import type { ProfileUsage } from '@shared/api/types'; import { apiJson, describeError } from '@/lib/api/client'; import { Button } from '@/components/ui/button'; import { PipelineFailure } from '@/components/pipeline-failure'; diff --git a/electron/src/renderer/src/features/design/design-draft.ts b/electron/src/renderer/src/features/design/design-draft.ts index 003ab8d6c..aba240d2a 100644 --- a/electron/src/renderer/src/features/design/design-draft.ts +++ b/electron/src/renderer/src/features/design/design-draft.ts @@ -2,8 +2,8 @@ import type { HistoryItem, Profile } from '@/lib/api/types'; import { instructToVdStates, mergeDescribedAttrs, -} from '../../../../../../frontend/src/utils/voiceInstruct'; -import { pickDesignSeed } from '../../../../../../frontend/src/utils/seed'; +} from '@shared/utils/voiceInstruct'; +import { pickDesignSeed } from '@shared/utils/seed'; export const STORAGE = 'voicestudio.design.v1'; export const DESIGN_DRAFT_EVENT = 'voicestudio:design-draft'; diff --git a/electron/src/renderer/src/features/design/design-page.tsx b/electron/src/renderer/src/features/design/design-page.tsx index 1d6b1c1d8..4ad1e81ef 100644 --- a/electron/src/renderer/src/features/design/design-page.tsx +++ b/electron/src/renderer/src/features/design/design-page.tsx @@ -50,13 +50,13 @@ import { queryKeys } from '@/lib/query'; import { cn } from '@/lib/utils'; import { cloneSettingsStore } from '@/lib/store/clone-settings'; import type { Profile } from '@/lib/api/types'; -import { CATEGORIES, PRESETS } from '../../../../../../frontend/src/utils/constants'; +import { CATEGORIES, PRESETS } from '@shared/utils/constants'; import { applyVdState, buildDesignInstruct, mergeDescribedAttrs, -} from '../../../../../../frontend/src/utils/voiceInstruct'; -import { pickDesignSeed } from '../../../../../../frontend/src/utils/seed'; +} from '@shared/utils/voiceInstruct'; +import { pickDesignSeed } from '@shared/utils/seed'; export function DesignPage() { const { t } = useTranslation(); const selectedTake = useSelectedTake(); diff --git a/electron/src/renderer/src/features/design/personality-presets.tsx b/electron/src/renderer/src/features/design/personality-presets.tsx index 6b2fa8c30..4e77ea811 100644 --- a/electron/src/renderer/src/features/design/personality-presets.tsx +++ b/electron/src/renderer/src/features/design/personality-presets.tsx @@ -12,7 +12,7 @@ import { useQuery } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { Button } from '@/components/ui/button'; import { apiJson } from '@/lib/api/client'; -import { instructToVdStates } from '../../../../../../frontend/src/utils/voiceInstruct'; +import { instructToVdStates } from '@shared/utils/voiceInstruct'; interface Personality { id: string; diff --git a/electron/src/renderer/src/features/dub/casting-board.tsx b/electron/src/renderer/src/features/dub/casting-board.tsx index 8122af7a7..658233c29 100644 --- a/electron/src/renderer/src/features/dub/casting-board.tsx +++ b/electron/src/renderer/src/features/dub/casting-board.tsx @@ -15,12 +15,12 @@ import { import { ProfileAvatar } from '@/components/profile-avatar'; import type { Profile } from '@/lib/api/types'; import { cn } from '@/lib/utils'; -import { PRESETS } from '../../../../../../frontend/src/utils/constants'; +import { PRESETS } from '@shared/utils/constants'; import { autoProfileId, castParts, castSpeakers, -} from '../../../../../../frontend/src/utils/segments'; +} from '@shared/utils/segments'; import type { DubSegment } from './dub-session'; const DEFAULT_VOICE = '__default__'; diff --git a/electron/src/renderer/src/features/dub/dub-page.tsx b/electron/src/renderer/src/features/dub/dub-page.tsx index f7e79a636..36d21dcd4 100644 --- a/electron/src/renderer/src/features/dub/dub-page.tsx +++ b/electron/src/renderer/src/features/dub/dub-page.tsx @@ -7,18 +7,18 @@ import { AgentFixButton } from '@/components/agent-fix-button'; import { getBridge } from '@/components/bridge'; import { WorkspaceHeader } from '@/components/app-shell/workspace-header'; import { Switch } from '@/components/ui/switch'; -import { MAX_COOKIE_EXPORT_BYTES } from '../../../../../../frontend/src/utils/cookieExport'; +import { MAX_COOKIE_EXPORT_BYTES } from '@shared/utils/cookieExport'; import { hasCompleteTranslation, multiLangTargets, -} from '../../../../../../frontend/src/utils/multiLang'; -import { segmentGenInputs } from '../../../../../../frontend/src/utils/segments'; -import { clampSegmentEdit } from '../../../../../../frontend/src/utils/timeline'; +} from '@shared/utils/multiLang'; +import { segmentGenInputs } from '@shared/utils/segments'; +import { clampSegmentEdit } from '@shared/utils/timeline'; import { dialectLabel, dialectMatchesLang, dialectOptionsFor, -} from '../../../../../../frontend/src/api/dialects'; +} from '@shared/api/dialects'; import { DubExportPanel } from './dub-export-panel'; import { DubTimeline } from './dub-timeline'; import { PasteTranslation } from './paste-translation'; @@ -97,7 +97,7 @@ import { apiFetch, apiJson, apiPath, describeError, isAbortError } from '@/lib/a import { createObjectUrl, revokeObjectUrl } from '@/lib/audio/object-url'; import { requestPlaybackSeek } from '@/lib/audio/playback-clock'; import { beginAppActivity } from '@/lib/app-activity'; -import { LANG_CODES } from '../../../../../../frontend/src/utils/languages'; +import { LANG_CODES } from '@shared/utils/languages'; import { cn } from '@/lib/utils'; import { useDubSession, diff --git a/electron/src/renderer/src/features/dub/dub-session.ts b/electron/src/renderer/src/features/dub/dub-session.ts index 2a59321d7..3256ce9ff 100644 --- a/electron/src/renderer/src/features/dub/dub-session.ts +++ b/electron/src/renderer/src/features/dub/dub-session.ts @@ -3,7 +3,7 @@ import type { DubExportPreferences } from './dub-export'; import { MAX_COOKIE_EXPORT_BYTES, _cookieTransportAllowed, -} from '../../../../../../frontend/src/utils/cookieExport'; +} from '@shared/utils/cookieExport'; import { projectSession, type DubProject } from '../projects/project-format'; import { DUB_DRAFT_KEY, restoreDubDraft } from './dub-draft'; import { Store } from '@tanstack/store'; @@ -22,8 +22,8 @@ import { settleCueSources, withOriginalCueSource, withoutCueSource, -} from '../../../../../../frontend/src/utils/segments'; -import { hasCompleteTranslation } from '../../../../../../frontend/src/utils/multiLang'; +} from '@shared/utils/segments'; +import { hasCompleteTranslation } from '@shared/utils/multiLang'; import { ATTRIBUTION_FIELDS, applyAttribution, @@ -36,9 +36,9 @@ import { nextSegmentId, partsFor, type SegmentPart, -} from '../../../../../../frontend/src/utils/segmentParts'; -import { commitMoveResize } from '../../../../../../frontend/src/utils/timeline'; -import type { PasteTranslationRow } from '../../../../../../frontend/src/utils/pasteTranslations'; +} from '@shared/utils/segmentParts'; +import { commitMoveResize } from '@shared/utils/timeline'; +import type { PasteTranslationRow } from '@shared/utils/pasteTranslations'; import type { DubAgentTranslationRequest, DubAgentTranslationResult, diff --git a/electron/src/renderer/src/features/dub/dub-timeline.tsx b/electron/src/renderer/src/features/dub/dub-timeline.tsx index a7a2b1520..e21017610 100644 --- a/electron/src/renderer/src/features/dub/dub-timeline.tsx +++ b/electron/src/renderer/src/features/dub/dub-timeline.tsx @@ -7,7 +7,7 @@ import { nearestOnset, snapCandidates, snapTime, -} from '../../../../../../frontend/src/utils/timeline'; +} from '@shared/utils/timeline'; import { Button } from '@/components/ui/button'; import { cn } from '@/lib/utils'; import { diff --git a/electron/src/renderer/src/features/dub/dub-to-story.ts b/electron/src/renderer/src/features/dub/dub-to-story.ts index 4804e3f41..f19d8fcfc 100644 --- a/electron/src/renderer/src/features/dub/dub-to-story.ts +++ b/electron/src/renderer/src/features/dub/dub-to-story.ts @@ -2,11 +2,11 @@ * Carrying a finished dub into the Stories editor. * * The transform itself is shared with the browser app - * (`frontend/src/utils/dubToStory`); this is the Electron wiring around it, kept + * (`electron/src/shared/utils/dubToStory`); this is the Electron wiring around it, kept * out of `dub-page.tsx` so the rules that decide whether the action is offered, * and what it overwrites, can be tested without mounting the page. */ -import { dubToStory } from '../../../../../../frontend/src/utils/dubToStory'; +import { dubToStory } from '@shared/utils/dubToStory'; import { editLongform, longformSession, diff --git a/electron/src/renderer/src/features/dub/paste-translation.tsx b/electron/src/renderer/src/features/dub/paste-translation.tsx index 5cec376c3..97f8ff1ea 100644 --- a/electron/src/renderer/src/features/dub/paste-translation.tsx +++ b/electron/src/renderer/src/features/dub/paste-translation.tsx @@ -1,4 +1,4 @@ -import { readTextFile } from '../../../../../../frontend/src/utils/readTextFile'; +import { readTextFile } from '@shared/utils/readTextFile'; import { useEffect, useMemo, useRef, useState } from 'react'; import { AlertTriangleIcon, ClipboardPasteIcon, FileTextIcon, XIcon } from 'lucide-react'; import { useTranslation } from 'react-i18next'; @@ -10,7 +10,7 @@ import { detectPasteMode, type PasteTranslationCue, type PasteTranslationRow, -} from '../../../../../../frontend/src/utils/pasteTranslations'; +} from '@shared/utils/pasteTranslations'; import type { DubSegment } from './dub-session'; const PREVIEW_LIMIT = 120; diff --git a/electron/src/renderer/src/features/dub/use-dub-live-preview.ts b/electron/src/renderer/src/features/dub/use-dub-live-preview.ts index 2c6fe2b15..bef69f963 100644 --- a/electron/src/renderer/src/features/dub/use-dub-live-preview.ts +++ b/electron/src/renderer/src/features/dub/use-dub-live-preview.ts @@ -2,7 +2,7 @@ import { createStreamingPreview, supportsStreamingPreview } from '@/lib/audio/st import { backendWebSocketUrl } from '@/lib/api/websocket'; import { beginAppActivity } from '@/lib/app-activity'; import { acquireSynthesis } from '@/lib/synthesis-lock'; -import { segmentGenInputs } from '../../../../../../frontend/src/utils/segments'; +import { segmentGenInputs } from '@shared/utils/segments'; import { useCallback, useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { toast } from 'sonner'; diff --git a/electron/src/renderer/src/features/gallery/community-view.tsx b/electron/src/renderer/src/features/gallery/community-view.tsx index 119157f5f..a11b5d1ed 100644 --- a/electron/src/renderer/src/features/gallery/community-view.tsx +++ b/electron/src/renderer/src/features/gallery/community-view.tsx @@ -15,11 +15,11 @@ import { STORAGE, readDraft } from '@/features/design/design-draft'; import { instructToVdStates, mergeDescribedAttrs, -} from '../../../../../../frontend/src/utils/voiceInstruct'; +} from '@shared/utils/voiceInstruct'; import type { CommunityItem, CommunityPage, -} from '../../../../../../frontend/src/api/community-types'; +} from '@shared/api/community-types'; import type { Profile } from '@/lib/api/types'; import type { Mode } from '@/features/longform/longform-session'; import { placeLongformVoice } from './place-voice'; diff --git a/electron/src/renderer/src/features/gallery/favorites.ts b/electron/src/renderer/src/features/gallery/favorites.ts index 925e6293a..db7f1c137 100644 --- a/electron/src/renderer/src/features/gallery/favorites.ts +++ b/electron/src/renderer/src/features/gallery/favorites.ts @@ -1,5 +1,5 @@ import { apiJson } from '@/lib/api/client'; -import type { ArchetypePage } from '../../../../../../frontend/src/api/archetypes-types'; +import type { ArchetypePage } from '@shared/api/archetypes-types'; export const FAVORITES_KEY = 'voicestudio.gallery.favorites.v1'; export function readFavorites(): string[] { try { diff --git a/electron/src/renderer/src/features/gallery/gallery-page.tsx b/electron/src/renderer/src/features/gallery/gallery-page.tsx index a5595e8d5..65a6acdd7 100644 --- a/electron/src/renderer/src/features/gallery/gallery-page.tsx +++ b/electron/src/renderer/src/features/gallery/gallery-page.tsx @@ -16,7 +16,7 @@ import { VoiceDestinations } from './voice-destinations'; import { placeLongformVoice } from './place-voice'; import type { Mode } from '@/features/longform/longform-session'; import { ImportsView } from './imports-view'; -import { FACETS } from '../../../../../../frontend/src/components/gallery/facets'; +import { FACETS } from '@shared/components/gallery/facets'; import { FAVORITES_KEY, readFavorites, favoriteCatalogue } from './favorites'; import { useEffect, useRef, useState } from 'react'; import { useNavigate } from '@tanstack/react-router'; @@ -33,8 +33,8 @@ import type { Profile } from '@/lib/api/types'; import type { ArchetypePage, ArchetypeCategory, -} from '../../../../../../frontend/src/api/archetypes-types'; -import { mergeDescribedAttrs } from '../../../../../../frontend/src/utils/voiceInstruct'; +} from '@shared/api/archetypes-types'; +import { mergeDescribedAttrs } from '@shared/utils/voiceInstruct'; import { STORAGE, readDraft } from '@/features/design/design-draft'; import { setCloneSetting } from '@/lib/store/clone-settings'; diff --git a/electron/src/renderer/src/features/gallery/imports-api.ts b/electron/src/renderer/src/features/gallery/imports-api.ts index 1f0fca2a5..b1c268c97 100644 --- a/electron/src/renderer/src/features/gallery/imports-api.ts +++ b/electron/src/renderer/src/features/gallery/imports-api.ts @@ -3,8 +3,8 @@ import type { DownloadParams, GalleryVoice, YoutubeSearchResult, -} from '../../../../../../frontend/src/api/gallery-types'; -import type { PersonaImportResult } from '../../../../../../frontend/src/api/types'; +} from '@shared/api/gallery-types'; +import type { PersonaImportResult } from '@shared/api/types'; export type { GalleryVoice, YoutubeSearchResult }; export const importsApi = { list: (signal?: AbortSignal) => apiJson('/gallery/voices', { signal }), diff --git a/electron/src/renderer/src/features/gallery/trim-audio.tsx b/electron/src/renderer/src/features/gallery/trim-audio.tsx index f0123f3de..3b775701a 100644 --- a/electron/src/renderer/src/features/gallery/trim-audio.tsx +++ b/electron/src/renderer/src/features/gallery/trim-audio.tsx @@ -12,7 +12,7 @@ import { decodeToMonoLowRate, sliceToMono, encodeWav, -} from '../../../../../../frontend/src/utils/audioTrim'; +} from '@shared/utils/audioTrim'; const MAX_TRIM_SECONDS = 60; diff --git a/electron/src/renderer/src/features/integrations/integration-detail-page.test.tsx b/electron/src/renderer/src/features/integrations/integration-detail-page.test.tsx index 50b4df760..ed2b8e0ce 100644 --- a/electron/src/renderer/src/features/integrations/integration-detail-page.test.tsx +++ b/electron/src/renderer/src/features/integrations/integration-detail-page.test.tsx @@ -5,7 +5,7 @@ import '@/i18n'; import { IntegrationDetailPage } from './integration-detail-page'; import { INTEGRATION_SETUPS } from './setup-registry'; import en from '@/i18n/locales/en.json'; -vi.mock('../../../../../../frontend/src/config/sponsors', () => ({ +vi.mock('@shared/config/sponsors', () => ({ SPONSORS: [ { name: 'Example sponsor', url: 'https://example.org', logoUrl: '/example.svg', tier: 'gold' }, ], diff --git a/electron/src/renderer/src/features/integrations/integration-detail-page.tsx b/electron/src/renderer/src/features/integrations/integration-detail-page.tsx index 456db2ab3..54c638a5e 100644 --- a/electron/src/renderer/src/features/integrations/integration-detail-page.tsx +++ b/electron/src/renderer/src/features/integrations/integration-detail-page.tsx @@ -22,8 +22,8 @@ import { getIntegrationBySlug, integrationSlug, type IntegrationCatalogEntry, -} from '../../../../../../frontend/src/config/integration-catalog'; -import { SPONSORS } from '../../../../../../frontend/src/config/sponsors'; +} from '@shared/config/integration-catalog'; +import { SPONSORS } from '@shared/config/sponsors'; import './integrations-page.css'; /** Catalog entries and featured sponsors both have an in-app page. */ diff --git a/electron/src/renderer/src/features/integrations/integration-links.test.tsx b/electron/src/renderer/src/features/integrations/integration-links.test.tsx index 1bd2bea36..2596edc1f 100644 --- a/electron/src/renderer/src/features/integrations/integration-links.test.tsx +++ b/electron/src/renderer/src/features/integrations/integration-links.test.tsx @@ -18,7 +18,7 @@ vi.mock('@/components/app-shell/workspace-header', () => ({ vi.mock('@/hooks/use-backend-status', () => ({ useBackendStatus: () => ({ baseUrl: 'http://127.0.0.1:3912' }), })); -vi.mock('../../../../../../frontend/src/config/sponsors', () => ({ +vi.mock('@shared/config/sponsors', () => ({ SPONSORS: [ { name: 'Acme Voice', logoUrl: 'acme.svg', url: 'https://acme.example', tier: 'gold' }, ], diff --git a/electron/src/renderer/src/features/integrations/integration-setup.test.ts b/electron/src/renderer/src/features/integrations/integration-setup.test.ts index 2862a432e..56f672e80 100644 --- a/electron/src/renderer/src/features/integrations/integration-setup.test.ts +++ b/electron/src/renderer/src/features/integrations/integration-setup.test.ts @@ -3,7 +3,7 @@ import { INTEGRATION_CATALOG, integrationSlug, getIntegrationBySlug, -} from '../../../../../../frontend/src/config/integration-catalog'; +} from '@shared/config/integration-catalog'; import { INTEGRATION_CATEGORIES, integrationCategoryKey, diff --git a/electron/src/renderer/src/features/integrations/integrations-page.tsx b/electron/src/renderer/src/features/integrations/integrations-page.tsx index 49f5c98bc..24c59bd34 100644 --- a/electron/src/renderer/src/features/integrations/integrations-page.tsx +++ b/electron/src/renderer/src/features/integrations/integrations-page.tsx @@ -8,8 +8,8 @@ import { Input } from '@/components/ui/input'; import { INTEGRATION_CATALOG, integrationSlug, -} from '../../../../../../frontend/src/config/integration-catalog'; -import { SPONSORS } from '../../../../../../frontend/src/config/sponsors'; +} from '@shared/config/integration-catalog'; +import { SPONSORS } from '@shared/config/sponsors'; import { integrationSetup } from './setup-registry'; import { INTEGRATION_CATEGORIES, integrationCategoryKey } from './integration-categories'; import './integrations-page.css'; diff --git a/electron/src/renderer/src/features/longform/audiobook-markup-toolbar.tsx b/electron/src/renderer/src/features/longform/audiobook-markup-toolbar.tsx index 56996b46d..5cb9f029a 100644 --- a/electron/src/renderer/src/features/longform/audiobook-markup-toolbar.tsx +++ b/electron/src/renderer/src/features/longform/audiobook-markup-toolbar.tsx @@ -12,7 +12,7 @@ import { } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { Button, buttonVariants } from '@/components/ui/button'; -import { TAGS } from '../../../../../../frontend/src/utils/constants'; +import { TAGS } from '@shared/utils/constants'; export function AudiobookMarkupToolbar({ textareaRef, diff --git a/electron/src/renderer/src/features/longform/auto-cast.test.ts b/electron/src/renderer/src/features/longform/auto-cast.test.ts index 464806165..ab1c841cc 100644 --- a/electron/src/renderer/src/features/longform/auto-cast.test.ts +++ b/electron/src/renderer/src/features/longform/auto-cast.test.ts @@ -1,5 +1,5 @@ import { expect, it } from 'vitest'; -import { buildAutoCast } from '../../../../../../frontend/src/utils/autoCast'; +import { buildAutoCast } from '@shared/utils/autoCast'; it('preserves assigned character voices and appends only new speakers', () => { const cast = [{ id: 'existing', name: 'Mara', profileId: 'actor' }]; const result = buildAutoCast('[Mara] Hello.\n[Guest] Welcome.', cast, [{ id: 'narrator' }]); diff --git a/electron/src/renderer/src/features/longform/cue-sheet.test.ts b/electron/src/renderer/src/features/longform/cue-sheet.test.ts index 9bc9253e5..bdfe1d0ef 100644 --- a/electron/src/renderer/src/features/longform/cue-sheet.test.ts +++ b/electron/src/renderer/src/features/longform/cue-sheet.test.ts @@ -7,7 +7,7 @@ * occupies no time in the finished file. Give it a cue and every later * timestamp is wrong by that chapter's would-be duration. * - * The timecode maths lives in `frontend/src/utils/storyExport` and is tested + * The timecode maths lives in `electron/src/shared/utils/storyExport` and is tested * there; this pins the part that is specific to a render — which chapters * count, and when there is nothing worth downloading. */ diff --git a/electron/src/renderer/src/features/longform/cue-sheet.ts b/electron/src/renderer/src/features/longform/cue-sheet.ts index 3af50c6c3..52b8c0067 100644 --- a/electron/src/renderer/src/features/longform/cue-sheet.ts +++ b/electron/src/renderer/src/features/longform/cue-sheet.ts @@ -2,7 +2,7 @@ import { buildCueSheet, cueSheetFilename, cuesFromChapters, -} from '../../../../../../frontend/src/utils/storyExport'; +} from '@shared/utils/storyExport'; import type { AudiobookRenderChapter } from './longform-session'; const RENDERED: ReadonlySet = new Set(['done', 'cached']); diff --git a/electron/src/renderer/src/features/longform/longform-page.tsx b/electron/src/renderer/src/features/longform/longform-page.tsx index 7d7215562..a12bb74c3 100644 --- a/electron/src/renderer/src/features/longform/longform-page.tsx +++ b/electron/src/renderer/src/features/longform/longform-page.tsx @@ -1,4 +1,4 @@ -import { readTextFile } from '../../../../../../frontend/src/utils/readTextFile'; +import { readTextFile } from '@shared/utils/readTextFile'; import { ProfileAvatar } from '@/components/profile-avatar'; import { BookOpenTextIcon, @@ -12,7 +12,7 @@ import { AudioLinesIcon } from 'lucide-react'; import { SecondarySidebar } from '@/components/workspace-sidebar'; import { WorkspaceHeader } from '@/components/app-shell/workspace-header'; import { PipelineFailure } from '@/components/pipeline-failure'; -import { importToText } from '../../../../../../frontend/src/utils/importStory'; +import { importToText } from '@shared/utils/importStory'; import { cueSheetFor } from './cue-sheet'; import { saveLocalFile } from '@/lib/local-export'; import { StoryCast, StoryEditor } from './story-editor'; @@ -31,7 +31,7 @@ import { scriptStats, formatRuntimeClock, validateScript, -} from '../../../../../../frontend/src/utils/audiobookScript'; +} from '@shared/utils/audiobookScript'; import { BookSettings } from './book-settings'; import { duplicateWords } from './book-options'; import { useEffect, useMemo, useRef, useState } from 'react'; @@ -52,7 +52,7 @@ import { useProfiles } from '@/hooks/use-profiles'; import { apiJson, apiPath, describeError } from '@/lib/api/client'; import { saveExport } from '@/lib/export-history'; import { EngineLanguagePicker } from '@/features/clone/engine-language-picker'; -import { LANG_CODES } from '../../../../../../frontend/src/utils/languages'; +import { LANG_CODES } from '@shared/utils/languages'; import { editLongform, dismissLongformError, @@ -62,7 +62,7 @@ import { storiesImportEpoch, type Mode, } from './longform-session'; -import { SAMPLE_AUDIOBOOK_SCRIPT } from '../../../../../../frontend/src/data/sampleAudiobook'; +import { SAMPLE_AUDIOBOOK_SCRIPT } from '@shared/data/sampleAudiobook'; import { useTtsReadiness } from '@/hooks/use-tts-readiness'; interface Recovery { job_id: string; diff --git a/electron/src/renderer/src/features/longform/longform-session.ts b/electron/src/renderer/src/features/longform/longform-session.ts index 756e555f1..deca03fcb 100644 --- a/electron/src/renderer/src/features/longform/longform-session.ts +++ b/electron/src/renderer/src/features/longform/longform-session.ts @@ -2,16 +2,16 @@ import { DEFAULT_OVERRIDES, overridesToRequest, type Overrides, -} from '../../../../../../frontend/src/utils/longformOverrides'; +} from '@shared/utils/longformOverrides'; import { castVoice } from './cast-map'; -import { parseCastNames } from '../../../../../../frontend/src/utils/audiobookScript'; +import { parseCastNames } from '@shared/utils/audiobookScript'; import { restoreBookOptions, lexiconMap, type BookOptions } from './book-options'; -import { createCoalescedJsonStorage } from '../../../../../../frontend/src/utils/coalescedJsonStorage'; +import { createCoalescedJsonStorage } from '@shared/utils/coalescedJsonStorage'; import { Store } from '@tanstack/store'; import { useStore } from '@tanstack/react-store'; import { apiFetch } from '@/lib/api/client'; -import { consumeLongformStream } from '../../../../../../frontend/src/utils/longformStream'; -import { storyToSpans } from '../../../../../../frontend/src/utils/storyToSpans'; +import { consumeLongformStream } from '@shared/utils/longformStream'; +import { storyToSpans } from '@shared/utils/storyToSpans'; import { beginAppActivity } from '@/lib/app-activity'; import { publicFailureFromEvent, type PublicFailure } from '@/lib/api/failure'; export type Mode = 'stories' | 'audiobook'; diff --git a/electron/src/renderer/src/features/longform/production-settings.test.tsx b/electron/src/renderer/src/features/longform/production-settings.test.tsx index 7154baf69..a3a421253 100644 --- a/electron/src/renderer/src/features/longform/production-settings.test.tsx +++ b/electron/src/renderer/src/features/longform/production-settings.test.tsx @@ -5,7 +5,7 @@ import i18n from '@/i18n'; import { DEFAULT_OVERRIDES, overridesToRequest, -} from '../../../../../../frontend/src/utils/longformOverrides'; +} from '@shared/utils/longformOverrides'; import { ProductionSettings } from './production-settings'; it('shows effective legacy joins for untouched and reset drafts', () => { render( diff --git a/electron/src/renderer/src/features/longform/production-settings.tsx b/electron/src/renderer/src/features/longform/production-settings.tsx index 5f8907523..533ac4c3e 100644 --- a/electron/src/renderer/src/features/longform/production-settings.tsx +++ b/electron/src/renderer/src/features/longform/production-settings.tsx @@ -8,7 +8,7 @@ import { apiJson } from '@/lib/api/client'; import { DEFAULT_OVERRIDES, type Overrides, -} from '../../../../../../frontend/src/utils/longformOverrides'; +} from '@shared/utils/longformOverrides'; const knobs = [ { key: 'numStep', label: 'steps', min: 8, max: 64, step: 1, value: 32 }, { key: 'guidanceScale', label: 'cfg', min: 0, max: 4, step: 0.1, value: 2 }, diff --git a/electron/src/renderer/src/features/longform/project-library.test.ts b/electron/src/renderer/src/features/longform/project-library.test.ts index 7ba17b9fc..b2ccf9869 100644 --- a/electron/src/renderer/src/features/longform/project-library.test.ts +++ b/electron/src/renderer/src/features/longform/project-library.test.ts @@ -1,7 +1,7 @@ import { expect, it } from 'vitest'; import { createProjectLibrary } from './project-library'; import { blankLongformDraft } from './longform-session'; -import type { DurableLongformRecord } from '../../../../../../frontend/src/utils/indexedDbLongformStore'; +import type { DurableLongformRecord } from '@shared/utils/indexedDbLongformStore'; it('serializes simultaneous saves without losing a project and snapshots inputs', async () => { let record: DurableLongformRecord | null = null; const library = createProjectLibrary({ diff --git a/electron/src/renderer/src/features/longform/project-library.ts b/electron/src/renderer/src/features/longform/project-library.ts index 6c1367fcb..df560f081 100644 --- a/electron/src/renderer/src/features/longform/project-library.ts +++ b/electron/src/renderer/src/features/longform/project-library.ts @@ -1,7 +1,7 @@ import { createIndexedDbLongformStore, type LongformDurableStore, -} from '../../../../../../frontend/src/utils/indexedDbLongformStore'; +} from '@shared/utils/indexedDbLongformStore'; import type { Draft, Mode } from './longform-session'; export interface LongformProject { id: string; diff --git a/electron/src/renderer/src/features/longform/story-editor.tsx b/electron/src/renderer/src/features/longform/story-editor.tsx index bd7e302f4..82666af24 100644 --- a/electron/src/renderer/src/features/longform/story-editor.tsx +++ b/electron/src/renderer/src/features/longform/story-editor.tsx @@ -7,14 +7,14 @@ import { SPLIT_MODES, splitStoryText, type SplitMode, -} from '../../../../../../frontend/src/utils/splitStoryText'; +} from '@shared/utils/splitStoryText'; import { useEffect, useRef, useState } from 'react'; -import { buildAutoCast } from '../../../../../../frontend/src/utils/autoCast'; +import { buildAutoCast } from '@shared/utils/autoCast'; import { SAMPLE_STORY_CAST, SAMPLE_STORY_LINES, SAMPLE_STORY_NAME, -} from '../../../../../../frontend/src/data/sampleStory'; +} from '@shared/data/sampleStory'; import { useTranslation } from 'react-i18next'; import { ArrowDownIcon, @@ -46,7 +46,7 @@ import { } from '@/components/ui/select'; import { PipelineFailure } from '@/components/pipeline-failure'; import { describeError } from '@/lib/api/client'; -import { reorder } from '../../../../../../frontend/src/utils/storyReorder'; +import { reorder } from '@shared/utils/storyReorder'; import type { Draft } from './longform-session'; interface Props { draft: Draft; diff --git a/electron/src/renderer/src/features/longform/story-import.test.ts b/electron/src/renderer/src/features/longform/story-import.test.ts index 1acbe3c6d..8ffd388f8 100644 --- a/electron/src/renderer/src/features/longform/story-import.test.ts +++ b/electron/src/renderer/src/features/longform/story-import.test.ts @@ -1,9 +1,9 @@ import { expect, it } from 'vitest'; -import { importToText } from '../../../../../../frontend/src/utils/importStory'; +import { importToText } from '@shared/utils/importStory'; import { splitIntoChunks, splitStoryText, -} from '../../../../../../frontend/src/utils/splitStoryText'; +} from '@shared/utils/splitStoryText'; it('removes SRT metadata and retains spoken lines', () => { expect( importToText( @@ -43,7 +43,7 @@ it('split presets give one line per paragraph or per chapter, headings kept sepa }); it('decodes a UTF-16 manuscript before extracting subtitle speech', async () => { - const { readTextFile } = await import('../../../../../../frontend/src/utils/readTextFile'); + const { readTextFile } = await import('@shared/utils/readTextFile'); const text = '1\n00:00:01,000 --> 00:00:02,000\nCafé — hello'; const bytes = new Uint8Array(2 + text.length * 2); bytes.set([0xff, 0xfe]); diff --git a/electron/src/renderer/src/features/longform/story-inputs.ts b/electron/src/renderer/src/features/longform/story-inputs.ts index 1b4bea852..e687d04f1 100644 --- a/electron/src/renderer/src/features/longform/story-inputs.ts +++ b/electron/src/renderer/src/features/longform/story-inputs.ts @@ -1,4 +1,4 @@ -import { storyToSpans } from '../../../../../../frontend/src/utils/storyToSpans'; +import { storyToSpans } from '@shared/utils/storyToSpans'; import { castVoice } from './cast-map'; import type { Draft } from './longform-session'; export function storyVoicesReady(draft: Draft, profiles: { id: string }[]) { diff --git a/electron/src/renderer/src/features/longform/story-preview.test.ts b/electron/src/renderer/src/features/longform/story-preview.test.ts index 05699d272..945afd0cc 100644 --- a/electron/src/renderer/src/features/longform/story-preview.test.ts +++ b/electron/src/renderer/src/features/longform/story-preview.test.ts @@ -1,5 +1,5 @@ import { afterEach, expect, it, vi } from 'vitest'; -import { exportStoryAudio } from '../../../../../../frontend/src/utils/storyExport'; +import { exportStoryAudio } from '@shared/utils/storyExport'; import { storyChunkBody } from './story-preview'; import { blankLongformDraft } from './longform-session'; afterEach(() => vi.unstubAllGlobals()); diff --git a/electron/src/renderer/src/features/longform/story-preview.ts b/electron/src/renderer/src/features/longform/story-preview.ts index 0ca76e085..358463f89 100644 --- a/electron/src/renderer/src/features/longform/story-preview.ts +++ b/electron/src/renderer/src/features/longform/story-preview.ts @@ -1,6 +1,6 @@ import { apiFetch } from '@/lib/api/client'; -import { exportStoryAudio, exportStems } from '../../../../../../frontend/src/utils/storyExport'; -import { overridesToRequest } from '../../../../../../frontend/src/utils/longformOverrides'; +import { exportStoryAudio, exportStems } from '@shared/utils/storyExport'; +import { overridesToRequest } from '@shared/utils/longformOverrides'; import { resolveStoryVoice } from './story-inputs'; import type { Draft, Line } from './longform-session'; import { beginAppActivity } from '@/lib/app-activity'; diff --git a/electron/src/renderer/src/features/longform/synced-audiobook-player.tsx b/electron/src/renderer/src/features/longform/synced-audiobook-player.tsx index 4c7258b28..73a2635f2 100644 --- a/electron/src/renderer/src/features/longform/synced-audiobook-player.tsx +++ b/electron/src/renderer/src/features/longform/synced-audiobook-player.tsx @@ -15,7 +15,7 @@ import { cn } from '@/lib/utils'; import { activeWordIndex, buildLyricsTimeline, -} from '../../../../../../frontend/src/utils/audiobookLyrics'; +} from '@shared/utils/audiobookLyrics'; import type { AudiobookRenderChapter } from './longform-session'; interface TimelineWord { diff --git a/electron/src/renderer/src/features/projects/project-format.ts b/electron/src/renderer/src/features/projects/project-format.ts index 09ba313cd..2be986168 100644 --- a/electron/src/renderer/src/features/projects/project-format.ts +++ b/electron/src/renderer/src/features/projects/project-format.ts @@ -1,4 +1,4 @@ -import { LANG_CODES } from '../../../../../../frontend/src/utils/languages'; +import { LANG_CODES } from '@shared/utils/languages'; import { restoreDubDraft } from '../dub/dub-draft'; import type { DubSession } from '../dub/dub-session'; export interface DubProject { diff --git a/electron/src/renderer/src/features/projects/projects-page.tsx b/electron/src/renderer/src/features/projects/projects-page.tsx index a6e8deaa1..96ff63462 100644 --- a/electron/src/renderer/src/features/projects/projects-page.tsx +++ b/electron/src/renderer/src/features/projects/projects-page.tsx @@ -57,8 +57,8 @@ import { removeTranscription, subscribeTranscriptions, type TranscriptEntry, -} from '../../../../../../frontend/src/utils/transcriptionsStore'; -import { preferredTranscript } from '../../../../../../frontend/src/utils/transcriptionFormat'; +} from '@shared/utils/transcriptionsStore'; +import { preferredTranscript } from '@shared/utils/transcriptionFormat'; import { useDubSession, openDubProject, diff --git a/electron/src/renderer/src/features/projects/transcript-deletion.test.ts b/electron/src/renderer/src/features/projects/transcript-deletion.test.ts index 4cb8144c3..764d562c8 100644 --- a/electron/src/renderer/src/features/projects/transcript-deletion.test.ts +++ b/electron/src/renderer/src/features/projects/transcript-deletion.test.ts @@ -4,7 +4,7 @@ import { removeTranscription, subscribeTranscriptions, TRANSCRIPTIONS_KEY, -} from '../../../../../../frontend/src/utils/transcriptionsStore'; +} from '@shared/utils/transcriptionsStore'; beforeEach(() => localStorage.clear()); afterEach(() => vi.restoreAllMocks()); it('deletes from fresh storage and notifies mounted library subscribers', () => { diff --git a/electron/src/renderer/src/features/settings/credential-settings.tsx b/electron/src/renderer/src/features/settings/credential-settings.tsx index cd7756c0b..59e2d7f0d 100644 --- a/electron/src/renderer/src/features/settings/credential-settings.tsx +++ b/electron/src/renderer/src/features/settings/credential-settings.tsx @@ -8,7 +8,7 @@ import { Switch } from '@/components/ui/switch'; import { apiJson } from '@/lib/api/client'; import { SettingsSection, SettingsRow } from './settings-layout'; import { useSettingsAction } from './use-settings-action'; -import { PROVIDER_FIELDS } from '../../../../../../frontend/src/utils/translationProviderFields'; +import { PROVIDER_FIELDS } from '@shared/utils/translationProviderFields'; interface TokenState { active: string | null; sources: { diff --git a/electron/src/renderer/src/features/settings/data-directory-settings.tsx b/electron/src/renderer/src/features/settings/data-directory-settings.tsx index 5ac0978dd..af3d99cc3 100644 --- a/electron/src/renderer/src/features/settings/data-directory-settings.tsx +++ b/electron/src/renderer/src/features/settings/data-directory-settings.tsx @@ -15,7 +15,7 @@ import { } from '@/components/ui/dialog'; import { apiJson, describeError } from '@/lib/api/client'; import type { DataDirectorySelection, DataRelocationStage } from '../../../../preload/index.d'; -import { fmtBytes } from '../../../../../../frontend/src/components/settings/models/format'; +import { fmtBytes } from '@shared/components/settings/models/format'; import { SettingsRow, SettingsSection } from './settings-layout'; function relocationError(t: (key: string) => string, error: unknown): string { diff --git a/electron/src/renderer/src/features/settings/donation-goal.tsx b/electron/src/renderer/src/features/settings/donation-goal.tsx index 930b8522e..37bb4d1c7 100644 --- a/electron/src/renderer/src/features/settings/donation-goal.tsx +++ b/electron/src/renderer/src/features/settings/donation-goal.tsx @@ -6,7 +6,7 @@ import { progressPct, isGoalMet, formatMoney, -} from '../../../../../../frontend/src/api/donation'; +} from '@shared/api/donation'; import snapshotUrl from '../../../../../public/donation_progress.json?url'; export function DonationGoal() { diff --git a/electron/src/renderer/src/features/settings/log-settings.tsx b/electron/src/renderer/src/features/settings/log-settings.tsx index d6d525fc5..3e04713b2 100644 --- a/electron/src/renderer/src/features/settings/log-settings.tsx +++ b/electron/src/renderer/src/features/settings/log-settings.tsx @@ -14,7 +14,7 @@ import { cn } from '@/lib/utils'; import { getFrontendLogs, clearFrontendLogs, -} from '../../../../../../frontend/src/utils/consoleBuffer'; +} from '@shared/utils/consoleBuffer'; interface LogResponse { lines: string[]; path?: string; diff --git a/electron/src/renderer/src/features/settings/model-library.tsx b/electron/src/renderer/src/features/settings/model-library.tsx index b7c194732..c511447eb 100644 --- a/electron/src/renderer/src/features/settings/model-library.tsx +++ b/electron/src/renderer/src/features/settings/model-library.tsx @@ -37,7 +37,7 @@ import { SettingsSection, SettingsRow } from './settings-layout'; import { familyIcons, type ModelFamily } from './model-family'; import { useModelCatalogue, type CatalogueModel } from './model-catalogue-query'; import { resolvePerformanceModelPack } from './performance-model-packs'; -import { fmtBytes } from '../../../../../../frontend/src/components/settings/models/format'; +import { fmtBytes } from '@shared/components/settings/models/format'; import { engineSelectionFeedback, type EngineSelectionResult, diff --git a/electron/src/renderer/src/features/settings/network-settings.tsx b/electron/src/renderer/src/features/settings/network-settings.tsx index eebe3da84..4f9681bde 100644 --- a/electron/src/renderer/src/features/settings/network-settings.tsx +++ b/electron/src/renderer/src/features/settings/network-settings.tsx @@ -8,7 +8,7 @@ import { Input } from '@/components/ui/input'; import { apiJson } from '@/lib/api/client'; import { SettingsSection, SettingsRow } from './settings-layout'; import { useSettingsAction } from './use-settings-action'; -import { saveProxyPreference } from '../../../../../../frontend/src/utils/networkPreferences'; +import { saveProxyPreference } from '@shared/utils/networkPreferences'; export function NetworkSettings() { const { t } = useTranslation(); const client = useQueryClient(); diff --git a/electron/src/renderer/src/features/settings/privacy-settings.tsx b/electron/src/renderer/src/features/settings/privacy-settings.tsx index 29dba940d..4956f651e 100644 --- a/electron/src/renderer/src/features/settings/privacy-settings.tsx +++ b/electron/src/renderer/src/features/settings/privacy-settings.tsx @@ -9,7 +9,7 @@ import { Switch } from '@/components/ui/switch'; import { apiJson } from '@/lib/api/client'; import { SettingsSection, SettingsRow } from './settings-layout'; import { useSettingsAction } from './use-settings-action'; -import { translatorPrivacy } from '../../../../../../frontend/src/utils/translatorPrivacy'; +import { translatorPrivacy } from '@shared/utils/translatorPrivacy'; export function PrivacySettings({ showAnalytics = true }: { showAnalytics?: boolean } = {}) { const { t } = useTranslation(); const info = useQuery({ diff --git a/electron/src/renderer/src/features/settings/refinement-settings.tsx b/electron/src/renderer/src/features/settings/refinement-settings.tsx index 66bca3b67..e8b7ae39e 100644 --- a/electron/src/renderer/src/features/settings/refinement-settings.tsx +++ b/electron/src/renderer/src/features/settings/refinement-settings.tsx @@ -6,7 +6,7 @@ import { apiJson } from '@/lib/api/client'; import { Button } from '@/components/ui/button'; import { Switch } from '@/components/ui/switch'; import { SettingsSection, SettingsRow } from './settings-layout'; -import { refineFailureNoteKey } from '../../../../../../frontend/src/components/settings/refineStatus'; +import { refineFailureNoteKey } from '@shared/components/settings/refineStatus'; const flags = ['auto', 'smart_cleanup', 'self_correction', 'preserve_technical'] as const; type Config = Record<(typeof flags)[number], boolean> & { llm_ready: boolean; diff --git a/electron/src/renderer/src/features/settings/reset-settings.tsx b/electron/src/renderer/src/features/settings/reset-settings.tsx index 6c0a7763d..b166f7350 100644 --- a/electron/src/renderer/src/features/settings/reset-settings.tsx +++ b/electron/src/renderer/src/features/settings/reset-settings.tsx @@ -32,7 +32,7 @@ import { apiFetch, describeError } from '@/lib/api/client'; import { projectLibrary } from '@/features/longform/project-library'; import { clearLongformDraftForReset } from '@/features/longform/longform-session'; import { clearDubDraftForReset } from '@/features/dub/dub-session'; -import { fmtBytes } from '../../../../../../frontend/src/components/settings/models/format'; +import { fmtBytes } from '@shared/components/settings/models/format'; import { SettingsSection } from './settings-layout'; import { forgetSetupProgress } from '@/lib/setup-progress'; diff --git a/electron/src/renderer/src/features/settings/shortcut-settings.tsx b/electron/src/renderer/src/features/settings/shortcut-settings.tsx index 87d6e2a1a..a2040d1fa 100644 --- a/electron/src/renderer/src/features/settings/shortcut-settings.tsx +++ b/electron/src/renderer/src/features/settings/shortcut-settings.tsx @@ -13,7 +13,7 @@ import { import { keyEventToAccelerator, isPureModifierEvent, -} from '../../../../../../frontend/src/utils/shortcutAccelerator'; +} from '@shared/utils/shortcutAccelerator'; import { SettingsSection, SettingsRow } from './settings-layout'; export function ShortcutSettings() { diff --git a/electron/src/renderer/src/features/settings/storage-settings.tsx b/electron/src/renderer/src/features/settings/storage-settings.tsx index ed46714f2..e018bd3ed 100644 --- a/electron/src/renderer/src/features/settings/storage-settings.tsx +++ b/electron/src/renderer/src/features/settings/storage-settings.tsx @@ -10,7 +10,7 @@ import { getBridge } from '@/components/bridge'; import { SettingsSection } from './settings-layout'; import { HistoryRetention } from './privacy-settings'; import { useSettingsAction } from './use-settings-action'; -import { fmtBytes } from '../../../../../../frontend/src/components/settings/models/format'; +import { fmtBytes } from '@shared/components/settings/models/format'; import { ModelsDirectorySettings } from './models-directory-settings'; import { ResetSettings } from './reset-settings'; import { DataDirectorySettings } from './data-directory-settings'; @@ -18,7 +18,7 @@ import { UninstallSettings } from './uninstall-settings'; import { warningText, type StorageWarning, -} from '../../../../../../frontend/src/utils/storageWarnings'; +} from '@shared/utils/storageWarnings'; interface Item { id: string; path?: string; diff --git a/electron/src/renderer/src/features/settings/support-settings.tsx b/electron/src/renderer/src/features/settings/support-settings.tsx index 0b2ee6c11..c8e541099 100644 --- a/electron/src/renderer/src/features/settings/support-settings.tsx +++ b/electron/src/renderer/src/features/settings/support-settings.tsx @@ -20,12 +20,12 @@ import { brandIcon } from '@/lib/brand'; import { DonationGoal } from './donation-goal'; import { ReportBug } from '@/components/report-bug'; import { ExternalLink } from '@/components/external-link'; -import { KOFI_URL, PAYPAL_URL } from '../../../../../../frontend/src/utils/donateLinks'; +import { KOFI_URL, PAYPAL_URL } from '@shared/utils/donateLinks'; import { SPONSORS, SPONSOR_TIERS, SPONSOR_CONTACT, -} from '../../../../../../frontend/src/config/sponsors'; +} from '@shared/config/sponsors'; import { ISSUES_URL, DISCORD_URL, @@ -33,7 +33,7 @@ import { EMAIL, WEBSITE_URL, X_URL, -} from '../../../../../../frontend/src/utils/contactLinks'; +} from '@shared/utils/contactLinks'; import './support-settings.css'; export function SupportSettings() { diff --git a/electron/src/renderer/src/features/settings/system-preflight.tsx b/electron/src/renderer/src/features/settings/system-preflight.tsx index 041525a58..4aab0ba82 100644 --- a/electron/src/renderer/src/features/settings/system-preflight.tsx +++ b/electron/src/renderer/src/features/settings/system-preflight.tsx @@ -1,7 +1,7 @@ import { useQuery } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { CheckCircleIcon, TriangleAlertIcon, CircleXIcon, ScanSearchIcon } from 'lucide-react'; -import type { PreflightReport } from '../../../../../../frontend/src/api/setup-types'; +import type { PreflightReport } from '@shared/api/setup-types'; import { apiJson } from '@/lib/api/client'; import { Button } from '@/components/ui/button'; import { SettingsRow, SettingsSection } from './settings-layout'; diff --git a/electron/src/renderer/src/features/settings/uninstall-settings.tsx b/electron/src/renderer/src/features/settings/uninstall-settings.tsx index 2d1caa263..aa60fb6f1 100644 --- a/electron/src/renderer/src/features/settings/uninstall-settings.tsx +++ b/electron/src/renderer/src/features/settings/uninstall-settings.tsx @@ -25,7 +25,7 @@ import { import { Input } from '@/components/ui/input'; import { describeError } from '@/lib/api/client'; import type { UninstallTarget } from '../../../../preload/index.d'; -import { fmtBytes } from '../../../../../../frontend/src/components/settings/models/format'; +import { fmtBytes } from '@shared/components/settings/models/format'; import { SettingsSection } from './settings-layout'; const ICONS: Record = { diff --git a/electron/src/renderer/src/features/tools/compare-voices.tsx b/electron/src/renderer/src/features/tools/compare-voices.tsx index 77fc54740..58dfe0eda 100644 --- a/electron/src/renderer/src/features/tools/compare-voices.tsx +++ b/electron/src/renderer/src/features/tools/compare-voices.tsx @@ -13,7 +13,7 @@ import { cloneSettingsStore } from '@/lib/store/clone-settings'; import { acquireSynthesis } from '@/lib/synthesis-lock'; import { queryKeys } from '@/lib/query'; import { describeError } from '@/lib/api/client'; -import { PRESETS } from '../../../../../../frontend/src/utils/constants'; +import { PRESETS } from '@shared/utils/constants'; import { beginAppActivity } from '@/lib/app-activity'; import { useTtsReadiness } from '@/hooks/use-tts-readiness'; diff --git a/electron/src/renderer/src/features/tools/tools-page.tsx b/electron/src/renderer/src/features/tools/tools-page.tsx index e1d81584d..3599705f4 100644 --- a/electron/src/renderer/src/features/tools/tools-page.tsx +++ b/electron/src/renderer/src/features/tools/tools-page.tsx @@ -12,7 +12,7 @@ import { Input } from '@/components/ui/input'; import { PipelineFailure } from '@/components/pipeline-failure'; import { apiJson, describeError } from '@/lib/api/client'; import { LanguagePicker } from '@/features/clone/language-picker'; -import { LANG_CODES } from '../../../../../../frontend/src/utils/languages'; +import { LANG_CODES } from '@shared/utils/languages'; const options = LANG_CODES.map((item) => item.label); const tools = [ { diff --git a/electron/src/renderer/src/features/transcriptions/capture-widget.tsx b/electron/src/renderer/src/features/transcriptions/capture-widget.tsx index 10b916415..3042835df 100644 --- a/electron/src/renderer/src/features/transcriptions/capture-widget.tsx +++ b/electron/src/renderer/src/features/transcriptions/capture-widget.tsx @@ -4,7 +4,7 @@ import { CopyIcon, MicIcon, PauseIcon, PlayIcon, SquareIcon, XIcon } from 'lucid import { Button } from '@/components/ui/button'; import { useBackendStatus } from '@/hooks/use-backend-status'; import { LiveDictation } from './live-dictation'; -import { addTranscription } from '../../../../../../frontend/src/utils/transcriptionsStore'; +import { addTranscription } from '@shared/utils/transcriptionsStore'; /** Native recorder stays separate from page navigation and the script editor. */ export function CaptureWidget() { diff --git a/electron/src/renderer/src/features/transcriptions/dictation-setup.tsx b/electron/src/renderer/src/features/transcriptions/dictation-setup.tsx index b7fcc3c89..a3831fc0d 100644 --- a/electron/src/renderer/src/features/transcriptions/dictation-setup.tsx +++ b/electron/src/renderer/src/features/transcriptions/dictation-setup.tsx @@ -7,7 +7,7 @@ import { Button, buttonVariants } from '@/components/ui/button'; import { AgentFixButton } from '@/components/agent-fix-button'; import { Progress } from '@/components/ui/progress'; import { apiJson, describeError } from '@/lib/api/client'; -import { fmtBytes } from '../../../../../../frontend/src/components/settings/models/format'; +import { fmtBytes } from '@shared/components/settings/models/format'; interface DictationModel { id: string; diff --git a/electron/src/renderer/src/features/transcriptions/history.test.ts b/electron/src/renderer/src/features/transcriptions/history.test.ts index ec4c58154..a07774737 100644 --- a/electron/src/renderer/src/features/transcriptions/history.test.ts +++ b/electron/src/renderer/src/features/transcriptions/history.test.ts @@ -4,7 +4,7 @@ import { loadTranscriptions, TRANSCRIPTIONS_KEY, TRANSCRIPTION_EVENT, -} from '../../../../../../frontend/src/utils/transcriptionsStore'; +} from '@shared/utils/transcriptionsStore'; beforeEach(() => localStorage.clear()); it('preserves existing history and publishes a complete entry with nullable timings', () => { localStorage.setItem(TRANSCRIPTIONS_KEY, JSON.stringify([{ id: 1, text: 'Existing' }])); diff --git a/electron/src/renderer/src/features/transcriptions/live-dictation.test.ts b/electron/src/renderer/src/features/transcriptions/live-dictation.test.ts index 66dffae71..3f7ff24f8 100644 --- a/electron/src/renderer/src/features/transcriptions/live-dictation.test.ts +++ b/electron/src/renderer/src/features/transcriptions/live-dictation.test.ts @@ -5,7 +5,7 @@ vi.mock('@/hooks/use-backend-status', () => ({ getBackendStatusSnapshot: () => ({ baseUrl: 'http://127.0.0.1:3900' }), })); vi.mock('@/components/bridge', () => ({ getBridge: () => mocks.bridge })); -vi.mock('../../../../../../frontend/src/utils/aec/micCapture', () => ({ +vi.mock('@shared/utils/aec/micCapture', () => ({ startMicCapture: mocks.capture, })); import { LiveDictation } from './live-dictation'; diff --git a/electron/src/renderer/src/features/transcriptions/live-dictation.ts b/electron/src/renderer/src/features/transcriptions/live-dictation.ts index 7449802d3..7a241efa8 100644 --- a/electron/src/renderer/src/features/transcriptions/live-dictation.ts +++ b/electron/src/renderer/src/features/transcriptions/live-dictation.ts @@ -1,16 +1,16 @@ -import { startMicCapture } from '../../../../../../frontend/src/utils/aec/micCapture'; -import { subscribeFarEnd } from '../../../../../../frontend/src/utils/aec/farEndBus'; +import { startMicCapture } from '@shared/utils/aec/micCapture'; +import { subscribeFarEnd } from '@shared/utils/aec/farEndBus'; import { AEC_FAR, AEC_NEAR, floatToInt16, tagFrame, -} from '../../../../../../frontend/src/utils/aec/pcm'; +} from '@shared/utils/aec/pcm'; import { classifySherpaFinal, sherpaSummaryTail, -} from '../../../../../../frontend/src/utils/captureProtocol'; -import type { TranscriptEntry } from '../../../../../../frontend/src/utils/transcriptionsStore'; +} from '@shared/utils/captureProtocol'; +import type { TranscriptEntry } from '@shared/utils/transcriptionsStore'; import { apiJson } from '@/lib/api/client'; import { backendWebSocketUrl } from '@/lib/api/websocket'; import { beginAppActivity } from '@/lib/app-activity'; diff --git a/electron/src/renderer/src/features/transcriptions/transcriptions-page.tsx b/electron/src/renderer/src/features/transcriptions/transcriptions-page.tsx index e66391969..72b7eb75e 100644 --- a/electron/src/renderer/src/features/transcriptions/transcriptions-page.tsx +++ b/electron/src/renderer/src/features/transcriptions/transcriptions-page.tsx @@ -6,7 +6,7 @@ import { segTimeRange, formatTranscriptExport, preferredTranscript, -} from '../../../../../../frontend/src/utils/transcriptionFormat'; +} from '@shared/utils/transcriptionFormat'; import { RecordingInputs } from '@/components/recording-inputs'; import { AgentFixButton } from '@/components/agent-fix-button'; import { useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'; @@ -52,14 +52,14 @@ import { TRANSCRIPTIONS_KEY, TRANSCRIPTION_EVENT, type TranscriptEntry, -} from '../../../../../../frontend/src/utils/transcriptionsStore'; +} from '@shared/utils/transcriptionsStore'; import { beginAppActivity } from '@/lib/app-activity'; import { formatRelative } from '@/features/clone/format'; import { useModelCatalogue } from '@/features/settings/model-catalogue-query'; import { useNativeShortcut } from '@/hooks/use-native-dictation'; import { recordActionBreadcrumb } from '@/lib/report-breadcrumb'; import { saveLocalFile } from '@/lib/local-export'; -import { formatShortcut } from '../../../../../../frontend/src/utils/dictationShortcut'; +import { formatShortcut } from '@shared/utils/dictationShortcut'; type TranscriptionMode = 'fast' | 'accurate'; const TRANSCRIPTION_MODE_KEY = 'voicestudio.transcription.mode'; diff --git a/electron/src/renderer/src/features/workflows/workflow-inputs.tsx b/electron/src/renderer/src/features/workflows/workflow-inputs.tsx index becc98938..175dd380a 100644 --- a/electron/src/renderer/src/features/workflows/workflow-inputs.tsx +++ b/electron/src/renderer/src/features/workflows/workflow-inputs.tsx @@ -9,9 +9,9 @@ import { importScript, SCRIPT_ACCEPT } from '@/lib/import-script'; import { LANGUAGES } from '@/lib/languages'; // Shared application controls are JavaScript; keep their established voice/value contracts. // @ts-expect-error shared JSX component has no declaration file -import VoiceSelector from '../../../../../../frontend/src/components/VoiceSelector'; +import VoiceSelector from '@shared/components/VoiceSelector'; // @ts-expect-error shared JSX component has no declaration file -import SearchableSelect from '../../../../../../frontend/src/components/SearchableSelect'; +import SearchableSelect from '@shared/components/SearchableSelect'; import { deleteWorkflowArtifacts, saveWorkflowMedia } from './workflow-run-store'; import type { WorkflowStep } from './workflow-model'; diff --git a/electron/src/renderer/src/features/workflows/workflow-operations.ts b/electron/src/renderer/src/features/workflows/workflow-operations.ts index 4f684e846..e2dd89d18 100644 --- a/electron/src/renderer/src/features/workflows/workflow-operations.ts +++ b/electron/src/renderer/src/features/workflows/workflow-operations.ts @@ -2,7 +2,7 @@ import { apiFetch, apiJson } from '@/lib/api/client'; import { convertSpeech } from '@/lib/api/convert'; import { generateClone } from '@/lib/api/generate'; import { DEFAULT_CLONE_SETTINGS } from '@/lib/store/clone-settings'; -import { LANG_CODES } from '../../../../../../frontend/src/utils/languages'; +import { LANG_CODES } from '@shared/utils/languages'; import { loadWorkflowMedia } from './workflow-run-store'; import type { WorkflowOperations } from './workflow-runtime'; diff --git a/electron/src/renderer/src/lib/api/client.test.ts b/electron/src/renderer/src/lib/api/client.test.ts index c4024db20..55516966b 100644 --- a/electron/src/renderer/src/lib/api/client.test.ts +++ b/electron/src/renderer/src/lib/api/client.test.ts @@ -3,7 +3,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { _resetBackendContactForTests, lastBackendContact, -} from '../../../../../../frontend/src/utils/backendContact'; +} from '@shared/utils/backendContact'; import { ApiError, apiFetch, diff --git a/electron/src/renderer/src/lib/api/client.ts b/electron/src/renderer/src/lib/api/client.ts index 6bdafcf5a..503d3c78c 100644 --- a/electron/src/renderer/src/lib/api/client.ts +++ b/electron/src/renderer/src/lib/api/client.ts @@ -1,17 +1,17 @@ -import { generationFailureMessage } from '../../../../../../frontend/src/utils/generationFailureMessage.ts'; -import { languageRejectionMessage } from '../../../../../../frontend/src/utils/languageRejection.ts'; +import { generationFailureMessage } from '@shared/utils/generationFailureMessage.ts'; +import { languageRejectionMessage } from '@shared/utils/languageRejection.ts'; /** Native builds use Electron's `/api` protocol proxy. The production web * bundle is served by FastAPI itself, whose routes live at the origin root. */ import type { ApiErrorPayload } from './types'; import { tr } from '@/lib/i18n-text'; import { getBackendStatusSnapshot } from '@/hooks/use-backend-status'; -import { recordBackendContact } from '../../../../../../frontend/src/utils/backendContact'; +import { recordBackendContact } from '@shared/utils/backendContact'; import { clearAdminSession, CSRF_HEADER_NAME, getAdminSession, isSameOriginApi, -} from '../../../../../../frontend/src/api/authSession'; +} from '@shared/api/authSession'; import { joinApiPath } from '../../../../shared/web-api-routing'; export { joinApiPath } from '../../../../shared/web-api-routing'; diff --git a/electron/src/renderer/src/lib/api/event-stream.ts b/electron/src/renderer/src/lib/api/event-stream.ts index 49ef839fd..eeea21ace 100644 --- a/electron/src/renderer/src/lib/api/event-stream.ts +++ b/electron/src/renderer/src/lib/api/event-stream.ts @@ -1,5 +1,5 @@ import { apiFetch } from './client'; -import { splitSSEBuffer, parseSSELine } from '../../../../../../frontend/src/utils/sseParse'; +import { splitSSEBuffer, parseSSELine } from '@shared/utils/sseParse'; export class IncompleteTaskStreamError extends Error { constructor() { super('Task stream ended without a terminal event'); diff --git a/electron/src/renderer/src/lib/api/failure.ts b/electron/src/renderer/src/lib/api/failure.ts index f939b3dae..5ceda8dae 100644 --- a/electron/src/renderer/src/lib/api/failure.ts +++ b/electron/src/renderer/src/lib/api/failure.ts @@ -1,5 +1,5 @@ import i18next from 'i18next'; -import { generationFailureMessage } from '../../../../../../frontend/src/utils/generationFailureMessage.ts'; +import { generationFailureMessage } from '@shared/utils/generationFailureMessage.ts'; export interface PublicFailure { reason: string; errorClass?: string; diff --git a/electron/src/renderer/src/lib/api/generate.ts b/electron/src/renderer/src/lib/api/generate.ts index 77319e86a..9132f517c 100644 --- a/electron/src/renderer/src/lib/api/generate.ts +++ b/electron/src/renderer/src/lib/api/generate.ts @@ -1,6 +1,6 @@ -import { generationFailureMessage } from '../../../../../../frontend/src/utils/generationFailureMessage.ts'; +import { generationFailureMessage } from '@shared/utils/generationFailureMessage.ts'; import i18next from 'i18next'; -import { languageRejectionMessage } from '../../../../../../frontend/src/utils/languageRejection.ts'; +import { languageRejectionMessage } from '@shared/utils/languageRejection.ts'; import { ApiError, apiFetch, isAbortError } from './client'; import type { CloneGenerateInput, GenerateResult } from './types'; import { beginAppActivity } from '@/lib/app-activity'; diff --git a/electron/src/renderer/src/lib/api/websocket.ts b/electron/src/renderer/src/lib/api/websocket.ts index 4176858e3..f3a704f43 100644 --- a/electron/src/renderer/src/lib/api/websocket.ts +++ b/electron/src/renderer/src/lib/api/websocket.ts @@ -1,7 +1,7 @@ import { getBridge } from '@/components/bridge'; import { getBackendStatusSnapshot, type BackendStatus } from '@/hooks/use-backend-status'; import { absoluteApiBase } from './client'; -import { authenticatedWsUrl } from '../../../../../../frontend/src/api/authSession'; +import { authenticatedWsUrl } from '@shared/api/authSession'; export type BackendWebSocketPath = '/ws/events' | '/ws/transcribe' | '/ws/tts'; diff --git a/electron/src/renderer/src/lib/global-error-recovery.test.ts b/electron/src/renderer/src/lib/global-error-recovery.test.ts index 1c9cfde60..67d4a60d0 100644 --- a/electron/src/renderer/src/lib/global-error-recovery.test.ts +++ b/electron/src/renderer/src/lib/global-error-recovery.test.ts @@ -3,7 +3,7 @@ import { describe, expect, it, vi } from 'vitest'; const openRepairAgent = vi.fn(); const captureException = vi.fn(); vi.mock('@/lib/repair-agent-events', () => ({ openRepairAgent })); -vi.mock('../../../../../frontend/src/utils/analytics', () => ({ captureException })); +vi.mock('@shared/utils/analytics', () => ({ captureException })); describe('global renderer error recovery', () => { it('hands uncaught faults to repair once while ignoring cancellation and foreign noise', async () => { diff --git a/electron/src/renderer/src/lib/global-error-recovery.ts b/electron/src/renderer/src/lib/global-error-recovery.ts index c4fc5aef9..663a4a6e9 100644 --- a/electron/src/renderer/src/lib/global-error-recovery.ts +++ b/electron/src/renderer/src/lib/global-error-recovery.ts @@ -1,10 +1,10 @@ -import { isBenignWindowError } from '../../../../../frontend/src/utils/foreignErrors'; -import { scrubText } from '../../../../../frontend/src/utils/scrub'; +import { isBenignWindowError } from '@shared/utils/foreignErrors'; +import { scrubText } from '@shared/utils/scrub'; import { openRepairAgent } from '@/lib/repair-agent-events'; import { captureException, type AnalyticsExceptionStage, -} from '../../../../../frontend/src/utils/analytics'; +} from '@shared/utils/analytics'; const THROTTLE_MS = 30_000; const lastOpened = new Map(); diff --git a/electron/src/renderer/src/lib/import-script.ts b/electron/src/renderer/src/lib/import-script.ts index 22cc4fecb..675c71d14 100644 --- a/electron/src/renderer/src/lib/import-script.ts +++ b/electron/src/renderer/src/lib/import-script.ts @@ -1,6 +1,6 @@ import { getBridge } from '@/components/bridge'; import { apiJson } from '@/lib/api/client'; -import { decodeTextBytes } from '../../../../../frontend/src/utils/readTextFile'; +import { decodeTextBytes } from '@shared/utils/readTextFile'; export const SCRIPT_ACCEPT = '.txt,.md,.markdown,.doc,.docx,.pdf,.epub'; diff --git a/electron/src/renderer/src/lib/report-breadcrumb.test.ts b/electron/src/renderer/src/lib/report-breadcrumb.test.ts index 068bae63b..a1bb1b55f 100644 --- a/electron/src/renderer/src/lib/report-breadcrumb.test.ts +++ b/electron/src/renderer/src/lib/report-breadcrumb.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'; -import { clearBreadcrumbs, getBreadcrumbs } from '../../../../../frontend/src/utils/breadcrumbs'; +import { clearBreadcrumbs, getBreadcrumbs } from '@shared/utils/breadcrumbs'; import { recordActionBreadcrumb, recordRouteBreadcrumb, @@ -7,7 +7,7 @@ import { } from './report-breadcrumb'; const capture = vi.hoisted(() => vi.fn()); const capturePageview = vi.hoisted(() => vi.fn()); -vi.mock('../../../../../frontend/src/utils/analytics', () => ({ capture, capturePageview })); +vi.mock('@shared/utils/analytics', () => ({ capture, capturePageview })); beforeEach(() => { clearBreadcrumbs(); diff --git a/electron/src/renderer/src/lib/report-breadcrumb.ts b/electron/src/renderer/src/lib/report-breadcrumb.ts index cf4d862c4..783b1ce5b 100644 --- a/electron/src/renderer/src/lib/report-breadcrumb.ts +++ b/electron/src/renderer/src/lib/report-breadcrumb.ts @@ -1,5 +1,5 @@ -import { addBreadcrumb } from '../../../../../frontend/src/utils/breadcrumbs'; -import { capture, capturePageview } from '../../../../../frontend/src/utils/analytics'; +import { addBreadcrumb } from '@shared/utils/breadcrumbs'; +import { capture, capturePageview } from '@shared/utils/analytics'; const WORKSPACES = new Set([ 'home', diff --git a/electron/src/renderer/src/main.tsx b/electron/src/renderer/src/main.tsx index 88960aa78..d7713148a 100644 --- a/electron/src/renderer/src/main.tsx +++ b/electron/src/renderer/src/main.tsx @@ -1,5 +1,5 @@ import { CaptureWidget } from './features/transcriptions/capture-widget'; -import { installConsoleCapture } from '../../../../frontend/src/utils/consoleBuffer'; +import { installConsoleCapture } from '@shared/utils/consoleBuffer'; import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import '@fontsource-variable/inter'; diff --git a/electron/src/renderer/src/styles/globals.css b/electron/src/renderer/src/styles/globals.css index 33044d2d4..d57b94d45 100644 --- a/electron/src/renderer/src/styles/globals.css +++ b/electron/src/renderer/src/styles/globals.css @@ -3,8 +3,8 @@ @import 'shadcn/tailwind.css'; @import './t3-theme.css'; -@source '../../../../../frontend/src/components/SearchableSelect.jsx'; -@source '../../../../../frontend/src/components/VoiceSelector.jsx'; +@source '../../../shared/components/SearchableSelect.jsx'; +@source '../../../shared/components/VoiceSelector.jsx'; @custom-variant dark (&:is(.dark, .dark *)); diff --git a/frontend/src/api/archetypes-types.d.ts b/electron/src/shared/api/archetypes-types.d.ts similarity index 100% rename from frontend/src/api/archetypes-types.d.ts rename to electron/src/shared/api/archetypes-types.d.ts diff --git a/frontend/src/api/archetypes.ts b/electron/src/shared/api/archetypes.ts similarity index 100% rename from frontend/src/api/archetypes.ts rename to electron/src/shared/api/archetypes.ts diff --git a/frontend/src/api/audiobook.ts b/electron/src/shared/api/audiobook.ts similarity index 100% rename from frontend/src/api/audiobook.ts rename to electron/src/shared/api/audiobook.ts diff --git a/frontend/src/api/authCredentialHygiene.test.js b/electron/src/shared/api/authCredentialHygiene.test.js similarity index 100% rename from frontend/src/api/authCredentialHygiene.test.js rename to electron/src/shared/api/authCredentialHygiene.test.js diff --git a/frontend/src/api/authSession.test.ts b/electron/src/shared/api/authSession.test.ts similarity index 100% rename from frontend/src/api/authSession.test.ts rename to electron/src/shared/api/authSession.test.ts diff --git a/frontend/src/api/authSession.ts b/electron/src/shared/api/authSession.ts similarity index 100% rename from frontend/src/api/authSession.ts rename to electron/src/shared/api/authSession.ts diff --git a/frontend/src/api/authSessionWsTransport.test.ts b/electron/src/shared/api/authSessionWsTransport.test.ts similarity index 100% rename from frontend/src/api/authSessionWsTransport.test.ts rename to electron/src/shared/api/authSessionWsTransport.test.ts diff --git a/frontend/src/api/batch-types.d.ts b/electron/src/shared/api/batch-types.d.ts similarity index 100% rename from frontend/src/api/batch-types.d.ts rename to electron/src/shared/api/batch-types.d.ts diff --git a/frontend/src/api/batch.test.js b/electron/src/shared/api/batch.test.js similarity index 100% rename from frontend/src/api/batch.test.js rename to electron/src/shared/api/batch.test.js diff --git a/frontend/src/api/batch.ts b/electron/src/shared/api/batch.ts similarity index 100% rename from frontend/src/api/batch.ts rename to electron/src/shared/api/batch.ts diff --git a/frontend/src/api/client.apibase.test.ts b/electron/src/shared/api/client.apibase.test.ts similarity index 100% rename from frontend/src/api/client.apibase.test.ts rename to electron/src/shared/api/client.apibase.test.ts diff --git a/frontend/src/api/client.test.ts b/electron/src/shared/api/client.test.ts similarity index 100% rename from frontend/src/api/client.test.ts rename to electron/src/shared/api/client.test.ts diff --git a/frontend/src/api/client.ts b/electron/src/shared/api/client.ts similarity index 100% rename from frontend/src/api/client.ts rename to electron/src/shared/api/client.ts diff --git a/frontend/src/api/community-types.d.ts b/electron/src/shared/api/community-types.d.ts similarity index 100% rename from frontend/src/api/community-types.d.ts rename to electron/src/shared/api/community-types.d.ts diff --git a/frontend/src/api/community.ts b/electron/src/shared/api/community.ts similarity index 100% rename from frontend/src/api/community.ts rename to electron/src/shared/api/community.ts diff --git a/frontend/src/api/convert.ts b/electron/src/shared/api/convert.ts similarity index 100% rename from frontend/src/api/convert.ts rename to electron/src/shared/api/convert.ts diff --git a/frontend/src/api/dialects.test.ts b/electron/src/shared/api/dialects.test.ts similarity index 100% rename from frontend/src/api/dialects.test.ts rename to electron/src/shared/api/dialects.test.ts diff --git a/frontend/src/api/dialects.ts b/electron/src/shared/api/dialects.ts similarity index 100% rename from frontend/src/api/dialects.ts rename to electron/src/shared/api/dialects.ts diff --git a/frontend/src/api/donation.ts b/electron/src/shared/api/donation.ts similarity index 100% rename from frontend/src/api/donation.ts rename to electron/src/shared/api/donation.ts diff --git a/frontend/src/api/dub.transcribeUrl.test.ts b/electron/src/shared/api/dub.transcribeUrl.test.ts similarity index 100% rename from frontend/src/api/dub.transcribeUrl.test.ts rename to electron/src/shared/api/dub.transcribeUrl.test.ts diff --git a/frontend/src/api/dub.ts b/electron/src/shared/api/dub.ts similarity index 100% rename from frontend/src/api/dub.ts rename to electron/src/shared/api/dub.ts diff --git a/frontend/src/api/engines.ts b/electron/src/shared/api/engines.ts similarity index 100% rename from frontend/src/api/engines.ts rename to electron/src/shared/api/engines.ts diff --git a/frontend/src/api/exports.ts b/electron/src/shared/api/exports.ts similarity index 100% rename from frontend/src/api/exports.ts rename to electron/src/shared/api/exports.ts diff --git a/electron/src/shared/api/external.ts b/electron/src/shared/api/external.ts new file mode 100644 index 000000000..3d531090a --- /dev/null +++ b/electron/src/shared/api/external.ts @@ -0,0 +1,23 @@ +/** + * openExternal — open a URL in the user's default browser. + * + * Electron delegates to its validated main-process bridge. Browser builds + * fall back to a normal window.open call. + */ + +/** + * Open an external URL in the system default browser. + * @param {string} url — the URL to open + */ +export async function openExternal(url: string) { + if (window.voicestudio) { + try { + await window.voicestudio.files.openExternal(url); + return; + } catch (err) { + console.warn('[openExternal] Electron opener failed, falling back:', err); + } + } + // Fallback for browser dev mode + window.open(url, '_blank', 'noopener,noreferrer'); +} diff --git a/frontend/src/api/gallery-types.d.ts b/electron/src/shared/api/gallery-types.d.ts similarity index 100% rename from frontend/src/api/gallery-types.d.ts rename to electron/src/shared/api/gallery-types.d.ts diff --git a/frontend/src/api/gallery.ts b/electron/src/shared/api/gallery.ts similarity index 100% rename from frontend/src/api/gallery.ts rename to electron/src/shared/api/gallery.ts diff --git a/frontend/src/api/generate.ts b/electron/src/shared/api/generate.ts similarity index 100% rename from frontend/src/api/generate.ts rename to electron/src/shared/api/generate.ts diff --git a/frontend/src/api/glossary.ts b/electron/src/shared/api/glossary.ts similarity index 100% rename from frontend/src/api/glossary.ts rename to electron/src/shared/api/glossary.ts diff --git a/frontend/src/api/hooks.ts b/electron/src/shared/api/hooks.ts similarity index 100% rename from frontend/src/api/hooks.ts rename to electron/src/shared/api/hooks.ts diff --git a/frontend/src/api/profiles.persona.test.ts b/electron/src/shared/api/profiles.persona.test.ts similarity index 100% rename from frontend/src/api/profiles.persona.test.ts rename to electron/src/shared/api/profiles.persona.test.ts diff --git a/frontend/src/api/profiles.ts b/electron/src/shared/api/profiles.ts similarity index 100% rename from frontend/src/api/profiles.ts rename to electron/src/shared/api/profiles.ts diff --git a/frontend/src/api/projects.ts b/electron/src/shared/api/projects.ts similarity index 100% rename from frontend/src/api/projects.ts rename to electron/src/shared/api/projects.ts diff --git a/frontend/src/api/setup-types.d.ts b/electron/src/shared/api/setup-types.d.ts similarity index 100% rename from frontend/src/api/setup-types.d.ts rename to electron/src/shared/api/setup-types.d.ts diff --git a/frontend/src/api/setup.ts b/electron/src/shared/api/setup.ts similarity index 100% rename from frontend/src/api/setup.ts rename to electron/src/shared/api/setup.ts diff --git a/frontend/src/api/stories.ts b/electron/src/shared/api/stories.ts similarity index 100% rename from frontend/src/api/stories.ts rename to electron/src/shared/api/stories.ts diff --git a/frontend/src/api/system.ts b/electron/src/shared/api/system.ts similarity index 83% rename from frontend/src/api/system.ts rename to electron/src/shared/api/system.ts index ab86af566..5d1b8a59a 100644 --- a/frontend/src/api/system.ts +++ b/electron/src/shared/api/system.ts @@ -6,38 +6,6 @@ import type { SystemInfo, ModelStatus, LogsResponse, ClearTauriResponse } from ' // works when the Python backend is still booting. Falls back to HTTP when // running in browser dev mode (no Tauri shell). -let _invoke: ((cmd: string, args?: Record) => Promise) | null = null; - -async function getInvoke() { - if (_invoke !== null) return _invoke; - try { - const mod = await import('@tauri-apps/api/core'); - _invoke = mod.invoke; - return _invoke; - } catch { - // Not running inside Tauri (browser dev mode) - _invoke = null as any; - return null; - } -} - -/** Try Tauri invoke, fall back to HTTP. */ -async function invokeOrFetch( - command: string, - args: Record | undefined, - httpFallback: () => Promise, -): Promise { - try { - const invoke = await getInvoke(); - if (invoke) { - return (await invoke(command, args)) as T; - } - } catch { - // invoke failed — fall through to HTTP - } - return httpFallback(); -} - // ── System info (polled every 5s) ──────────────────────────────────────── export interface SysinfoData { @@ -56,9 +24,7 @@ const VRAM_CACHE_TTL = 15_000; export async function sysinfo(): Promise { // Rust provides CPU + RAM; VRAM stays at 0. We merge with the Python // endpoint to get GPU data when available. - const rustData = await invokeOrFetch('get_sysinfo', undefined, () => - apiJson('/sysinfo'), - ); + const rustData = await apiJson('/sysinfo'); // If we got data from Rust (vram=0), enrich with Python's VRAM data // but only re-fetch every 15s to avoid hammering the backend. @@ -166,15 +132,11 @@ export async function systemNotifications(): Promise { // ── Logs (polled every 5s) ─────────────────────────────────────────────── export async function systemLogs(tail: number = 300): Promise { - return invokeOrFetch('read_log_tail', { source: 'backend', tail }, () => - apiJson(`/system/logs?tail=${tail}`), - ); + return apiJson(`/system/logs?tail=${tail}`); } export async function systemLogsTauri(tail: number = 300): Promise { - return invokeOrFetch('read_log_tail', { source: 'tauri', tail }, () => - apiJson(`/system/logs/tauri?tail=${tail}`), - ); + return apiJson(`/system/logs/tauri?tail=${tail}`); } // ── Log clearing ───────────────────────────────────────────────────────── diff --git a/frontend/src/api/types.ts b/electron/src/shared/api/types.ts similarity index 100% rename from frontend/src/api/types.ts rename to electron/src/shared/api/types.ts diff --git a/frontend/src/api/watermark.ts b/electron/src/shared/api/watermark.ts similarity index 100% rename from frontend/src/api/watermark.ts rename to electron/src/shared/api/watermark.ts diff --git a/frontend/src/assets/hero.png b/electron/src/shared/assets/hero.png similarity index 100% rename from frontend/src/assets/hero.png rename to electron/src/shared/assets/hero.png diff --git a/frontend/src/assets/integrations/anthropic.png b/electron/src/shared/assets/integrations/anthropic.png similarity index 100% rename from frontend/src/assets/integrations/anthropic.png rename to electron/src/shared/assets/integrations/anthropic.png diff --git a/frontend/src/assets/integrations/assemblyai.ico b/electron/src/shared/assets/integrations/assemblyai.ico similarity index 100% rename from frontend/src/assets/integrations/assemblyai.ico rename to electron/src/shared/assets/integrations/assemblyai.ico diff --git a/frontend/src/assets/integrations/cartesia.png b/electron/src/shared/assets/integrations/cartesia.png similarity index 100% rename from frontend/src/assets/integrations/cartesia.png rename to electron/src/shared/assets/integrations/cartesia.png diff --git a/frontend/src/assets/integrations/codex.png b/electron/src/shared/assets/integrations/codex.png similarity index 100% rename from frontend/src/assets/integrations/codex.png rename to electron/src/shared/assets/integrations/codex.png diff --git a/frontend/src/assets/integrations/deepgram.ico b/electron/src/shared/assets/integrations/deepgram.ico similarity index 100% rename from frontend/src/assets/integrations/deepgram.ico rename to electron/src/shared/assets/integrations/deepgram.ico diff --git a/frontend/src/assets/integrations/docker.png b/electron/src/shared/assets/integrations/docker.png similarity index 100% rename from frontend/src/assets/integrations/docker.png rename to electron/src/shared/assets/integrations/docker.png diff --git a/frontend/src/assets/integrations/elevenlabs.ico b/electron/src/shared/assets/integrations/elevenlabs.ico similarity index 100% rename from frontend/src/assets/integrations/elevenlabs.ico rename to electron/src/shared/assets/integrations/elevenlabs.ico diff --git a/frontend/src/assets/integrations/ghcr.png b/electron/src/shared/assets/integrations/ghcr.png similarity index 100% rename from frontend/src/assets/integrations/ghcr.png rename to electron/src/shared/assets/integrations/ghcr.png diff --git a/frontend/src/assets/integrations/github.png b/electron/src/shared/assets/integrations/github.png similarity index 100% rename from frontend/src/assets/integrations/github.png rename to electron/src/shared/assets/integrations/github.png diff --git a/frontend/src/assets/integrations/hume.ico b/electron/src/shared/assets/integrations/hume.ico similarity index 100% rename from frontend/src/assets/integrations/hume.ico rename to electron/src/shared/assets/integrations/hume.ico diff --git a/frontend/src/assets/integrations/integration-generic.svg b/electron/src/shared/assets/integrations/integration-generic.svg similarity index 100% rename from frontend/src/assets/integrations/integration-generic.svg rename to electron/src/shared/assets/integrations/integration-generic.svg diff --git a/frontend/src/assets/integrations/inworld.ico b/electron/src/shared/assets/integrations/inworld.ico similarity index 100% rename from frontend/src/assets/integrations/inworld.ico rename to electron/src/shared/assets/integrations/inworld.ico diff --git a/frontend/src/assets/integrations/mcp.png b/electron/src/shared/assets/integrations/mcp.png similarity index 100% rename from frontend/src/assets/integrations/mcp.png rename to electron/src/shared/assets/integrations/mcp.png diff --git a/frontend/src/assets/integrations/murf.ico b/electron/src/shared/assets/integrations/murf.ico similarity index 100% rename from frontend/src/assets/integrations/murf.ico rename to electron/src/shared/assets/integrations/murf.ico diff --git a/frontend/src/assets/integrations/n8n.ico b/electron/src/shared/assets/integrations/n8n.ico similarity index 100% rename from frontend/src/assets/integrations/n8n.ico rename to electron/src/shared/assets/integrations/n8n.ico diff --git a/frontend/src/assets/integrations/plivo.svg b/electron/src/shared/assets/integrations/plivo.svg similarity index 100% rename from frontend/src/assets/integrations/plivo.svg rename to electron/src/shared/assets/integrations/plivo.svg diff --git a/frontend/src/assets/integrations/resemble.png b/electron/src/shared/assets/integrations/resemble.png similarity index 100% rename from frontend/src/assets/integrations/resemble.png rename to electron/src/shared/assets/integrations/resemble.png diff --git a/frontend/src/assets/integrations/speechify.ico b/electron/src/shared/assets/integrations/speechify.ico similarity index 100% rename from frontend/src/assets/integrations/speechify.ico rename to electron/src/shared/assets/integrations/speechify.ico diff --git a/frontend/src/assets/integrations/telnyx.ico b/electron/src/shared/assets/integrations/telnyx.ico similarity index 100% rename from frontend/src/assets/integrations/telnyx.ico rename to electron/src/shared/assets/integrations/telnyx.ico diff --git a/frontend/src/assets/integrations/twilio.png b/electron/src/shared/assets/integrations/twilio.png similarity index 100% rename from frontend/src/assets/integrations/twilio.png rename to electron/src/shared/assets/integrations/twilio.png diff --git a/frontend/src/assets/integrations/voicestudio.png b/electron/src/shared/assets/integrations/voicestudio.png similarity index 100% rename from frontend/src/assets/integrations/voicestudio.png rename to electron/src/shared/assets/integrations/voicestudio.png diff --git a/frontend/src/assets/integrations/wellsaid.png b/electron/src/shared/assets/integrations/wellsaid.png similarity index 100% rename from frontend/src/assets/integrations/wellsaid.png rename to electron/src/shared/assets/integrations/wellsaid.png diff --git a/frontend/src/assets/integrations/zapier.ico b/electron/src/shared/assets/integrations/zapier.ico similarity index 100% rename from frontend/src/assets/integrations/zapier.ico rename to electron/src/shared/assets/integrations/zapier.ico diff --git a/frontend/src/assets/react.svg b/electron/src/shared/assets/react.svg similarity index 100% rename from frontend/src/assets/react.svg rename to electron/src/shared/assets/react.svg diff --git a/frontend/src/assets/vite.svg b/electron/src/shared/assets/vite.svg similarity index 100% rename from frontend/src/assets/vite.svg rename to electron/src/shared/assets/vite.svg diff --git a/frontend/src/components/AnalyticsConsentBanner.jsx b/electron/src/shared/components/AnalyticsConsentBanner.jsx similarity index 100% rename from frontend/src/components/AnalyticsConsentBanner.jsx rename to electron/src/shared/components/AnalyticsConsentBanner.jsx diff --git a/frontend/src/components/AnalyticsConsentCard.jsx b/electron/src/shared/components/AnalyticsConsentCard.jsx similarity index 100% rename from frontend/src/components/AnalyticsConsentCard.jsx rename to electron/src/shared/components/AnalyticsConsentCard.jsx diff --git a/frontend/src/components/AsrModelChooser.jsx b/electron/src/shared/components/AsrModelChooser.jsx similarity index 100% rename from frontend/src/components/AsrModelChooser.jsx rename to electron/src/shared/components/AsrModelChooser.jsx diff --git a/frontend/src/components/AudioTrimmer.jsx b/electron/src/shared/components/AudioTrimmer.jsx similarity index 100% rename from frontend/src/components/AudioTrimmer.jsx rename to electron/src/shared/components/AudioTrimmer.jsx diff --git a/frontend/src/components/BackendCrashNotice.jsx b/electron/src/shared/components/BackendCrashNotice.jsx similarity index 100% rename from frontend/src/components/BackendCrashNotice.jsx rename to electron/src/shared/components/BackendCrashNotice.jsx diff --git a/frontend/src/components/BackendCrashNotice.test.jsx b/electron/src/shared/components/BackendCrashNotice.test.jsx similarity index 100% rename from frontend/src/components/BackendCrashNotice.test.jsx rename to electron/src/shared/components/BackendCrashNotice.test.jsx diff --git a/frontend/src/components/BackendRestartBanner.jsx b/electron/src/shared/components/BackendRestartBanner.jsx similarity index 100% rename from frontend/src/components/BackendRestartBanner.jsx rename to electron/src/shared/components/BackendRestartBanner.jsx diff --git a/frontend/src/components/BackendStartFailureNotice.jsx b/electron/src/shared/components/BackendStartFailureNotice.jsx similarity index 100% rename from frontend/src/components/BackendStartFailureNotice.jsx rename to electron/src/shared/components/BackendStartFailureNotice.jsx diff --git a/frontend/src/components/BackendStartFailureNotice.test.jsx b/electron/src/shared/components/BackendStartFailureNotice.test.jsx similarity index 100% rename from frontend/src/components/BackendStartFailureNotice.test.jsx rename to electron/src/shared/components/BackendStartFailureNotice.test.jsx diff --git a/frontend/src/components/BatchAddDialog.jsx b/electron/src/shared/components/BatchAddDialog.jsx similarity index 100% rename from frontend/src/components/BatchAddDialog.jsx rename to electron/src/shared/components/BatchAddDialog.jsx diff --git a/frontend/src/components/BootstrapSplash.jsx b/electron/src/shared/components/BootstrapSplash.jsx similarity index 100% rename from frontend/src/components/BootstrapSplash.jsx rename to electron/src/shared/components/BootstrapSplash.jsx diff --git a/frontend/src/components/CaptureWidget.jsx b/electron/src/shared/components/CaptureWidget.jsx similarity index 100% rename from frontend/src/components/CaptureWidget.jsx rename to electron/src/shared/components/CaptureWidget.jsx diff --git a/frontend/src/components/CaptureWidget.test.jsx b/electron/src/shared/components/CaptureWidget.test.jsx similarity index 100% rename from frontend/src/components/CaptureWidget.test.jsx rename to electron/src/shared/components/CaptureWidget.test.jsx diff --git a/frontend/src/components/ChangelogViewer.jsx b/electron/src/shared/components/ChangelogViewer.jsx similarity index 100% rename from frontend/src/components/ChangelogViewer.jsx rename to electron/src/shared/components/ChangelogViewer.jsx diff --git a/frontend/src/components/ChangelogViewer.test.jsx b/electron/src/shared/components/ChangelogViewer.test.jsx similarity index 100% rename from frontend/src/components/ChangelogViewer.test.jsx rename to electron/src/shared/components/ChangelogViewer.test.jsx diff --git a/frontend/src/components/CheckpointBanner.jsx b/electron/src/shared/components/CheckpointBanner.jsx similarity index 100% rename from frontend/src/components/CheckpointBanner.jsx rename to electron/src/shared/components/CheckpointBanner.jsx diff --git a/frontend/src/components/CompareModal.jsx b/electron/src/shared/components/CompareModal.jsx similarity index 100% rename from frontend/src/components/CompareModal.jsx rename to electron/src/shared/components/CompareModal.jsx diff --git a/frontend/src/components/ComputeQuickSettings.jsx b/electron/src/shared/components/ComputeQuickSettings.jsx similarity index 100% rename from frontend/src/components/ComputeQuickSettings.jsx rename to electron/src/shared/components/ComputeQuickSettings.jsx diff --git a/frontend/src/components/ComputeQuickSettings.test.jsx b/electron/src/shared/components/ComputeQuickSettings.test.jsx similarity index 100% rename from frontend/src/components/ComputeQuickSettings.test.jsx rename to electron/src/shared/components/ComputeQuickSettings.test.jsx diff --git a/frontend/src/components/DemoPresetGrid.jsx b/electron/src/shared/components/DemoPresetGrid.jsx similarity index 100% rename from frontend/src/components/DemoPresetGrid.jsx rename to electron/src/shared/components/DemoPresetGrid.jsx diff --git a/frontend/src/components/DesktopCaptureShortcutBridge.jsx b/electron/src/shared/components/DesktopCaptureShortcutBridge.jsx similarity index 100% rename from frontend/src/components/DesktopCaptureShortcutBridge.jsx rename to electron/src/shared/components/DesktopCaptureShortcutBridge.jsx diff --git a/frontend/src/components/DesktopCaptureShortcutBridge.test.jsx b/electron/src/shared/components/DesktopCaptureShortcutBridge.test.jsx similarity index 100% rename from frontend/src/components/DesktopCaptureShortcutBridge.test.jsx rename to electron/src/shared/components/DesktopCaptureShortcutBridge.test.jsx diff --git a/frontend/src/components/DictationDemo.jsx b/electron/src/shared/components/DictationDemo.jsx similarity index 100% rename from frontend/src/components/DictationDemo.jsx rename to electron/src/shared/components/DictationDemo.jsx diff --git a/frontend/src/components/DictationModelPicker.jsx b/electron/src/shared/components/DictationModelPicker.jsx similarity index 100% rename from frontend/src/components/DictationModelPicker.jsx rename to electron/src/shared/components/DictationModelPicker.jsx diff --git a/frontend/src/components/DictationModelPicker.test.jsx b/electron/src/shared/components/DictationModelPicker.test.jsx similarity index 100% rename from frontend/src/components/DictationModelPicker.test.jsx rename to electron/src/shared/components/DictationModelPicker.test.jsx diff --git a/frontend/src/components/DirectionDialog.jsx b/electron/src/shared/components/DirectionDialog.jsx similarity index 100% rename from frontend/src/components/DirectionDialog.jsx rename to electron/src/shared/components/DirectionDialog.jsx diff --git a/frontend/src/components/DonateMomentPopover.jsx b/electron/src/shared/components/DonateMomentPopover.jsx similarity index 100% rename from frontend/src/components/DonateMomentPopover.jsx rename to electron/src/shared/components/DonateMomentPopover.jsx diff --git a/frontend/src/components/DubSegmentRow.jsx b/electron/src/shared/components/DubSegmentRow.jsx similarity index 100% rename from frontend/src/components/DubSegmentRow.jsx rename to electron/src/shared/components/DubSegmentRow.jsx diff --git a/frontend/src/components/DubSegmentTable.jsx b/electron/src/shared/components/DubSegmentTable.jsx similarity index 100% rename from frontend/src/components/DubSegmentTable.jsx rename to electron/src/shared/components/DubSegmentTable.jsx diff --git a/frontend/src/components/DubWorkspaceSidebar.jsx b/electron/src/shared/components/DubWorkspaceSidebar.jsx similarity index 100% rename from frontend/src/components/DubWorkspaceSidebar.jsx rename to electron/src/shared/components/DubWorkspaceSidebar.jsx diff --git a/frontend/src/components/DubWorkspaceSidebar.test.jsx b/electron/src/shared/components/DubWorkspaceSidebar.test.jsx similarity index 100% rename from frontend/src/components/DubWorkspaceSidebar.test.jsx rename to electron/src/shared/components/DubWorkspaceSidebar.test.jsx diff --git a/frontend/src/components/DubbingDemo.jsx b/electron/src/shared/components/DubbingDemo.jsx similarity index 100% rename from frontend/src/components/DubbingDemo.jsx rename to electron/src/shared/components/DubbingDemo.jsx diff --git a/frontend/src/components/EngineCompatibilityMatrix.jsx b/electron/src/shared/components/EngineCompatibilityMatrix.jsx similarity index 100% rename from frontend/src/components/EngineCompatibilityMatrix.jsx rename to electron/src/shared/components/EngineCompatibilityMatrix.jsx diff --git a/frontend/src/components/EngineMark.jsx b/electron/src/shared/components/EngineMark.jsx similarity index 100% rename from frontend/src/components/EngineMark.jsx rename to electron/src/shared/components/EngineMark.jsx diff --git a/frontend/src/components/EngineQuickSwitch.jsx b/electron/src/shared/components/EngineQuickSwitch.jsx similarity index 100% rename from frontend/src/components/EngineQuickSwitch.jsx rename to electron/src/shared/components/EngineQuickSwitch.jsx diff --git a/frontend/src/components/EngineQuickSwitch.test.jsx b/electron/src/shared/components/EngineQuickSwitch.test.jsx similarity index 100% rename from frontend/src/components/EngineQuickSwitch.test.jsx rename to electron/src/shared/components/EngineQuickSwitch.test.jsx diff --git a/frontend/src/components/ErrorBoundary.jsx b/electron/src/shared/components/ErrorBoundary.jsx similarity index 100% rename from frontend/src/components/ErrorBoundary.jsx rename to electron/src/shared/components/ErrorBoundary.jsx diff --git a/frontend/src/components/ErrorBoundary.test.jsx b/electron/src/shared/components/ErrorBoundary.test.jsx similarity index 100% rename from frontend/src/components/ErrorBoundary.test.jsx rename to electron/src/shared/components/ErrorBoundary.test.jsx diff --git a/frontend/src/components/ExportModal.css b/electron/src/shared/components/ExportModal.css similarity index 100% rename from frontend/src/components/ExportModal.css rename to electron/src/shared/components/ExportModal.css diff --git a/frontend/src/components/ExportModal.jsx b/electron/src/shared/components/ExportModal.jsx similarity index 100% rename from frontend/src/components/ExportModal.jsx rename to electron/src/shared/components/ExportModal.jsx diff --git a/frontend/src/components/ExportModal.test.jsx b/electron/src/shared/components/ExportModal.test.jsx similarity index 100% rename from frontend/src/components/ExportModal.test.jsx rename to electron/src/shared/components/ExportModal.test.jsx diff --git a/frontend/src/components/FirstRunSetup.jsx b/electron/src/shared/components/FirstRunSetup.jsx similarity index 100% rename from frontend/src/components/FirstRunSetup.jsx rename to electron/src/shared/components/FirstRunSetup.jsx diff --git a/frontend/src/components/FloatingPill.jsx b/electron/src/shared/components/FloatingPill.jsx similarity index 100% rename from frontend/src/components/FloatingPill.jsx rename to electron/src/shared/components/FloatingPill.jsx diff --git a/frontend/src/components/GlobalAudioPlayer.jsx b/electron/src/shared/components/GlobalAudioPlayer.jsx similarity index 100% rename from frontend/src/components/GlobalAudioPlayer.jsx rename to electron/src/shared/components/GlobalAudioPlayer.jsx diff --git a/frontend/src/components/GlossaryPanel.css b/electron/src/shared/components/GlossaryPanel.css similarity index 100% rename from frontend/src/components/GlossaryPanel.css rename to electron/src/shared/components/GlossaryPanel.css diff --git a/frontend/src/components/GlossaryPanel.jsx b/electron/src/shared/components/GlossaryPanel.jsx similarity index 100% rename from frontend/src/components/GlossaryPanel.jsx rename to electron/src/shared/components/GlossaryPanel.jsx diff --git a/frontend/src/components/GlossaryPanel.test.jsx b/electron/src/shared/components/GlossaryPanel.test.jsx similarity index 100% rename from frontend/src/components/GlossaryPanel.test.jsx rename to electron/src/shared/components/GlossaryPanel.test.jsx diff --git a/frontend/src/components/GpuTarget.jsx b/electron/src/shared/components/GpuTarget.jsx similarity index 100% rename from frontend/src/components/GpuTarget.jsx rename to electron/src/shared/components/GpuTarget.jsx diff --git a/frontend/src/components/GpuTarget.test.jsx b/electron/src/shared/components/GpuTarget.test.jsx similarity index 100% rename from frontend/src/components/GpuTarget.test.jsx rename to electron/src/shared/components/GpuTarget.test.jsx diff --git a/frontend/src/components/Header.jsx b/electron/src/shared/components/Header.jsx similarity index 100% rename from frontend/src/components/Header.jsx rename to electron/src/shared/components/Header.jsx diff --git a/frontend/src/components/HfTokenCard.jsx b/electron/src/shared/components/HfTokenCard.jsx similarity index 100% rename from frontend/src/components/HfTokenCard.jsx rename to electron/src/shared/components/HfTokenCard.jsx diff --git a/frontend/src/components/HfTokenCard.test.jsx b/electron/src/shared/components/HfTokenCard.test.jsx similarity index 100% rename from frontend/src/components/HfTokenCard.test.jsx rename to electron/src/shared/components/HfTokenCard.test.jsx diff --git a/frontend/src/components/KeyboardCheatsheet.jsx b/electron/src/shared/components/KeyboardCheatsheet.jsx similarity index 100% rename from frontend/src/components/KeyboardCheatsheet.jsx rename to electron/src/shared/components/KeyboardCheatsheet.jsx diff --git a/frontend/src/components/LanguageFlag.jsx b/electron/src/shared/components/LanguageFlag.jsx similarity index 100% rename from frontend/src/components/LanguageFlag.jsx rename to electron/src/shared/components/LanguageFlag.jsx diff --git a/frontend/src/components/LanguageSwitchPrompt.jsx b/electron/src/shared/components/LanguageSwitchPrompt.jsx similarity index 100% rename from frontend/src/components/LanguageSwitchPrompt.jsx rename to electron/src/shared/components/LanguageSwitchPrompt.jsx diff --git a/frontend/src/components/LaunchpadDeck.jsx b/electron/src/shared/components/LaunchpadDeck.jsx similarity index 100% rename from frontend/src/components/LaunchpadDeck.jsx rename to electron/src/shared/components/LaunchpadDeck.jsx diff --git a/frontend/src/components/LogsFooter.jsx b/electron/src/shared/components/LogsFooter.jsx similarity index 100% rename from frontend/src/components/LogsFooter.jsx rename to electron/src/shared/components/LogsFooter.jsx diff --git a/frontend/src/components/LongformPersistenceGate.jsx b/electron/src/shared/components/LongformPersistenceGate.jsx similarity index 100% rename from frontend/src/components/LongformPersistenceGate.jsx rename to electron/src/shared/components/LongformPersistenceGate.jsx diff --git a/frontend/src/components/LongformPersistenceGate.test.jsx b/electron/src/shared/components/LongformPersistenceGate.test.jsx similarity index 100% rename from frontend/src/components/LongformPersistenceGate.test.jsx rename to electron/src/shared/components/LongformPersistenceGate.test.jsx diff --git a/frontend/src/components/MarkdownLite.jsx b/electron/src/shared/components/MarkdownLite.jsx similarity index 100% rename from frontend/src/components/MarkdownLite.jsx rename to electron/src/shared/components/MarkdownLite.jsx diff --git a/frontend/src/components/MediaEngineCard.jsx b/electron/src/shared/components/MediaEngineCard.jsx similarity index 100% rename from frontend/src/components/MediaEngineCard.jsx rename to electron/src/shared/components/MediaEngineCard.jsx diff --git a/frontend/src/components/MediaEngineCard.test.jsx b/electron/src/shared/components/MediaEngineCard.test.jsx similarity index 100% rename from frontend/src/components/MediaEngineCard.test.jsx rename to electron/src/shared/components/MediaEngineCard.test.jsx diff --git a/frontend/src/components/MirrorRescue.jsx b/electron/src/shared/components/MirrorRescue.jsx similarity index 100% rename from frontend/src/components/MirrorRescue.jsx rename to electron/src/shared/components/MirrorRescue.jsx diff --git a/frontend/src/components/ModeLifecycleBoundary.jsx b/electron/src/shared/components/ModeLifecycleBoundary.jsx similarity index 100% rename from frontend/src/components/ModeLifecycleBoundary.jsx rename to electron/src/shared/components/ModeLifecycleBoundary.jsx diff --git a/frontend/src/components/ModeLifecycleBoundary.test.jsx b/electron/src/shared/components/ModeLifecycleBoundary.test.jsx similarity index 100% rename from frontend/src/components/ModeLifecycleBoundary.test.jsx rename to electron/src/shared/components/ModeLifecycleBoundary.test.jsx diff --git a/frontend/src/components/MultiLangPicker.jsx b/electron/src/shared/components/MultiLangPicker.jsx similarity index 100% rename from frontend/src/components/MultiLangPicker.jsx rename to electron/src/shared/components/MultiLangPicker.jsx diff --git a/frontend/src/components/MultiLangPicker.test.jsx b/electron/src/shared/components/MultiLangPicker.test.jsx similarity index 100% rename from frontend/src/components/MultiLangPicker.test.jsx rename to electron/src/shared/components/MultiLangPicker.test.jsx diff --git a/frontend/src/components/NavRail.css b/electron/src/shared/components/NavRail.css similarity index 100% rename from frontend/src/components/NavRail.css rename to electron/src/shared/components/NavRail.css diff --git a/frontend/src/components/NavRail.jsx b/electron/src/shared/components/NavRail.jsx similarity index 100% rename from frontend/src/components/NavRail.jsx rename to electron/src/shared/components/NavRail.jsx diff --git a/frontend/src/components/NavRail.test.jsx b/electron/src/shared/components/NavRail.test.jsx similarity index 100% rename from frontend/src/components/NavRail.test.jsx rename to electron/src/shared/components/NavRail.test.jsx diff --git a/frontend/src/components/NetworkToggle.jsx b/electron/src/shared/components/NetworkToggle.jsx similarity index 99% rename from frontend/src/components/NetworkToggle.jsx rename to electron/src/shared/components/NetworkToggle.jsx index a08264ff5..f5cd86580 100644 --- a/frontend/src/components/NetworkToggle.jsx +++ b/electron/src/shared/components/NetworkToggle.jsx @@ -1,4 +1,4 @@ -// frontend/src/components/NetworkToggle.jsx +// electron/src/shared/components/NetworkToggle.jsx import { useEffect, useState, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { copyText } from '../utils/copyText'; diff --git a/frontend/src/components/NetworkToggle.test.jsx b/electron/src/shared/components/NetworkToggle.test.jsx similarity index 96% rename from frontend/src/components/NetworkToggle.test.jsx rename to electron/src/shared/components/NetworkToggle.test.jsx index 6f2219027..c61edb4ae 100644 --- a/frontend/src/components/NetworkToggle.test.jsx +++ b/electron/src/shared/components/NetworkToggle.test.jsx @@ -1,4 +1,4 @@ -// frontend/src/components/NetworkToggle.test.jsx +// electron/src/shared/components/NetworkToggle.test.jsx import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { render, screen, waitFor, fireEvent } from '@testing-library/react'; import NetworkToggle from './NetworkToggle'; diff --git a/frontend/src/components/NotificationPanel.jsx b/electron/src/shared/components/NotificationPanel.jsx similarity index 100% rename from frontend/src/components/NotificationPanel.jsx rename to electron/src/shared/components/NotificationPanel.jsx diff --git a/frontend/src/components/NotificationPanel.test.jsx b/electron/src/shared/components/NotificationPanel.test.jsx similarity index 100% rename from frontend/src/components/NotificationPanel.test.jsx rename to electron/src/shared/components/NotificationPanel.test.jsx diff --git a/frontend/src/components/OneTimeSecret.jsx b/electron/src/shared/components/OneTimeSecret.jsx similarity index 100% rename from frontend/src/components/OneTimeSecret.jsx rename to electron/src/shared/components/OneTimeSecret.jsx diff --git a/frontend/src/components/OneTimeSecret.test.jsx b/electron/src/shared/components/OneTimeSecret.test.jsx similarity index 100% rename from frontend/src/components/OneTimeSecret.test.jsx rename to electron/src/shared/components/OneTimeSecret.test.jsx diff --git a/frontend/src/components/PermissionChecks.jsx b/electron/src/shared/components/PermissionChecks.jsx similarity index 100% rename from frontend/src/components/PermissionChecks.jsx rename to electron/src/shared/components/PermissionChecks.jsx diff --git a/frontend/src/components/PocketTTSLicenseDialog.jsx b/electron/src/shared/components/PocketTTSLicenseDialog.jsx similarity index 100% rename from frontend/src/components/PocketTTSLicenseDialog.jsx rename to electron/src/shared/components/PocketTTSLicenseDialog.jsx diff --git a/frontend/src/components/ReadinessChecklist.jsx b/electron/src/shared/components/ReadinessChecklist.jsx similarity index 100% rename from frontend/src/components/ReadinessChecklist.jsx rename to electron/src/shared/components/ReadinessChecklist.jsx diff --git a/frontend/src/components/RemoteAuthGate.jsx b/electron/src/shared/components/RemoteAuthGate.jsx similarity index 100% rename from frontend/src/components/RemoteAuthGate.jsx rename to electron/src/shared/components/RemoteAuthGate.jsx diff --git a/frontend/src/components/RemoteAuthGate.test.jsx b/electron/src/shared/components/RemoteAuthGate.test.jsx similarity index 100% rename from frontend/src/components/RemoteAuthGate.test.jsx rename to electron/src/shared/components/RemoteAuthGate.test.jsx diff --git a/frontend/src/components/RemoteBackendRecovery.jsx b/electron/src/shared/components/RemoteBackendRecovery.jsx similarity index 100% rename from frontend/src/components/RemoteBackendRecovery.jsx rename to electron/src/shared/components/RemoteBackendRecovery.jsx diff --git a/frontend/src/components/RemoteBackendRecovery.test.jsx b/electron/src/shared/components/RemoteBackendRecovery.test.jsx similarity index 100% rename from frontend/src/components/RemoteBackendRecovery.test.jsx rename to electron/src/shared/components/RemoteBackendRecovery.test.jsx diff --git a/frontend/src/components/ReportBugButton.jsx b/electron/src/shared/components/ReportBugButton.jsx similarity index 100% rename from frontend/src/components/ReportBugButton.jsx rename to electron/src/shared/components/ReportBugButton.jsx diff --git a/frontend/src/components/SearchableSelect.jsx b/electron/src/shared/components/SearchableSelect.jsx similarity index 100% rename from frontend/src/components/SearchableSelect.jsx rename to electron/src/shared/components/SearchableSelect.jsx diff --git a/frontend/src/components/SearchableSelect.test.jsx b/electron/src/shared/components/SearchableSelect.test.jsx similarity index 100% rename from frontend/src/components/SearchableSelect.test.jsx rename to electron/src/shared/components/SearchableSelect.test.jsx diff --git a/frontend/src/components/SegmentTrack.jsx b/electron/src/shared/components/SegmentTrack.jsx similarity index 100% rename from frontend/src/components/SegmentTrack.jsx rename to electron/src/shared/components/SegmentTrack.jsx diff --git a/frontend/src/components/SegmentTrack.test.jsx b/electron/src/shared/components/SegmentTrack.test.jsx similarity index 100% rename from frontend/src/components/SegmentTrack.test.jsx rename to electron/src/shared/components/SegmentTrack.test.jsx diff --git a/frontend/src/components/Sidebar.jsx b/electron/src/shared/components/Sidebar.jsx similarity index 100% rename from frontend/src/components/Sidebar.jsx rename to electron/src/shared/components/Sidebar.jsx diff --git a/frontend/src/components/SidebarProjectRename.test.jsx b/electron/src/shared/components/SidebarProjectRename.test.jsx similarity index 100% rename from frontend/src/components/SidebarProjectRename.test.jsx rename to electron/src/shared/components/SidebarProjectRename.test.jsx diff --git a/frontend/src/components/StoriesEditor.jsx b/electron/src/shared/components/StoriesEditor.jsx similarity index 100% rename from frontend/src/components/StoriesEditor.jsx rename to electron/src/shared/components/StoriesEditor.jsx diff --git a/frontend/src/components/SupertonicLicenseDialog.jsx b/electron/src/shared/components/SupertonicLicenseDialog.jsx similarity index 100% rename from frontend/src/components/SupertonicLicenseDialog.jsx rename to electron/src/shared/components/SupertonicLicenseDialog.jsx diff --git a/frontend/src/components/TitleTabs.jsx b/electron/src/shared/components/TitleTabs.jsx similarity index 100% rename from frontend/src/components/TitleTabs.jsx rename to electron/src/shared/components/TitleTabs.jsx diff --git a/frontend/src/components/TranscriptionPicker.jsx b/electron/src/shared/components/TranscriptionPicker.jsx similarity index 100% rename from frontend/src/components/TranscriptionPicker.jsx rename to electron/src/shared/components/TranscriptionPicker.jsx diff --git a/frontend/src/components/UiScaleControl.jsx b/electron/src/shared/components/UiScaleControl.jsx similarity index 100% rename from frontend/src/components/UiScaleControl.jsx rename to electron/src/shared/components/UiScaleControl.jsx diff --git a/frontend/src/components/UiScaleControl.test.jsx b/electron/src/shared/components/UiScaleControl.test.jsx similarity index 100% rename from frontend/src/components/UiScaleControl.test.jsx rename to electron/src/shared/components/UiScaleControl.test.jsx diff --git a/frontend/src/components/UiScaleSetup.jsx b/electron/src/shared/components/UiScaleSetup.jsx similarity index 100% rename from frontend/src/components/UiScaleSetup.jsx rename to electron/src/shared/components/UiScaleSetup.jsx diff --git a/frontend/src/components/UiScaleSetup.test.jsx b/electron/src/shared/components/UiScaleSetup.test.jsx similarity index 100% rename from frontend/src/components/UiScaleSetup.test.jsx rename to electron/src/shared/components/UiScaleSetup.test.jsx diff --git a/frontend/src/components/UpdateToast.jsx b/electron/src/shared/components/UpdateToast.jsx similarity index 100% rename from frontend/src/components/UpdateToast.jsx rename to electron/src/shared/components/UpdateToast.jsx diff --git a/frontend/src/components/UpdatesPanel.jsx b/electron/src/shared/components/UpdatesPanel.jsx similarity index 99% rename from frontend/src/components/UpdatesPanel.jsx rename to electron/src/shared/components/UpdatesPanel.jsx index 1e3a34f2f..72d04730b 100644 --- a/frontend/src/components/UpdatesPanel.jsx +++ b/electron/src/shared/components/UpdatesPanel.jsx @@ -1,4 +1,4 @@ -// frontend/src/components/UpdatesPanel.jsx +// electron/src/shared/components/UpdatesPanel.jsx // Update management panel — lives under Settings → Updates. Shows live update // status (with the available build's actual release notes), channel switcher, // the data-safety line (pre-update DB backups), the app's own "What's new" diff --git a/frontend/src/components/UpdatesPanel.test.jsx b/electron/src/shared/components/UpdatesPanel.test.jsx similarity index 100% rename from frontend/src/components/UpdatesPanel.test.jsx rename to electron/src/shared/components/UpdatesPanel.test.jsx diff --git a/frontend/src/components/VoicePreview.jsx b/electron/src/shared/components/VoicePreview.jsx similarity index 100% rename from frontend/src/components/VoicePreview.jsx rename to electron/src/shared/components/VoicePreview.jsx diff --git a/frontend/src/components/VoiceSelector.jsx b/electron/src/shared/components/VoiceSelector.jsx similarity index 100% rename from frontend/src/components/VoiceSelector.jsx rename to electron/src/shared/components/VoiceSelector.jsx diff --git a/frontend/src/components/WatchFolderBar.jsx b/electron/src/shared/components/WatchFolderBar.jsx similarity index 100% rename from frontend/src/components/WatchFolderBar.jsx rename to electron/src/shared/components/WatchFolderBar.jsx diff --git a/frontend/src/components/WatchFolderBar.test.jsx b/electron/src/shared/components/WatchFolderBar.test.jsx similarity index 100% rename from frontend/src/components/WatchFolderBar.test.jsx rename to electron/src/shared/components/WatchFolderBar.test.jsx diff --git a/frontend/src/components/WaveformPlayer.jsx b/electron/src/shared/components/WaveformPlayer.jsx similarity index 100% rename from frontend/src/components/WaveformPlayer.jsx rename to electron/src/shared/components/WaveformPlayer.jsx diff --git a/frontend/src/components/WaveformTimeline.jsx b/electron/src/shared/components/WaveformTimeline.jsx similarity index 100% rename from frontend/src/components/WaveformTimeline.jsx rename to electron/src/shared/components/WaveformTimeline.jsx diff --git a/frontend/src/components/WaveformTimeline.readyFallback.test.js b/electron/src/shared/components/WaveformTimeline.readyFallback.test.js similarity index 100% rename from frontend/src/components/WaveformTimeline.readyFallback.test.js rename to electron/src/shared/components/WaveformTimeline.readyFallback.test.js diff --git a/frontend/src/components/WaveformTimeline.unlock.test.js b/electron/src/shared/components/WaveformTimeline.unlock.test.js similarity index 100% rename from frontend/src/components/WaveformTimeline.unlock.test.js rename to electron/src/shared/components/WaveformTimeline.unlock.test.js diff --git a/frontend/src/components/WizardLibrary.jsx b/electron/src/shared/components/WizardLibrary.jsx similarity index 100% rename from frontend/src/components/WizardLibrary.jsx rename to electron/src/shared/components/WizardLibrary.jsx diff --git a/frontend/src/components/WorkspaceHistory.jsx b/electron/src/shared/components/WorkspaceHistory.jsx similarity index 100% rename from frontend/src/components/WorkspaceHistory.jsx rename to electron/src/shared/components/WorkspaceHistory.jsx diff --git a/frontend/src/components/WorkspaceHistory.test.jsx b/electron/src/shared/components/WorkspaceHistory.test.jsx similarity index 100% rename from frontend/src/components/WorkspaceHistory.test.jsx rename to electron/src/shared/components/WorkspaceHistory.test.jsx diff --git a/frontend/src/components/WorkspaceVoices.jsx b/electron/src/shared/components/WorkspaceVoices.jsx similarity index 100% rename from frontend/src/components/WorkspaceVoices.jsx rename to electron/src/shared/components/WorkspaceVoices.jsx diff --git a/frontend/src/components/WorkspaceVoices.test.jsx b/electron/src/shared/components/WorkspaceVoices.test.jsx similarity index 100% rename from frontend/src/components/WorkspaceVoices.test.jsx rename to electron/src/shared/components/WorkspaceVoices.test.jsx diff --git a/frontend/src/components/audiobook/AudiobookBookPanel.jsx b/electron/src/shared/components/audiobook/AudiobookBookPanel.jsx similarity index 100% rename from frontend/src/components/audiobook/AudiobookBookPanel.jsx rename to electron/src/shared/components/audiobook/AudiobookBookPanel.jsx diff --git a/frontend/src/components/audiobook/AudiobookHero.jsx b/electron/src/shared/components/audiobook/AudiobookHero.jsx similarity index 100% rename from frontend/src/components/audiobook/AudiobookHero.jsx rename to electron/src/shared/components/audiobook/AudiobookHero.jsx diff --git a/frontend/src/components/audiobook/AudiobookOverrides.jsx b/electron/src/shared/components/audiobook/AudiobookOverrides.jsx similarity index 100% rename from frontend/src/components/audiobook/AudiobookOverrides.jsx rename to electron/src/shared/components/audiobook/AudiobookOverrides.jsx diff --git a/frontend/src/components/audiobook/AudiobookRecovery.jsx b/electron/src/shared/components/audiobook/AudiobookRecovery.jsx similarity index 100% rename from frontend/src/components/audiobook/AudiobookRecovery.jsx rename to electron/src/shared/components/audiobook/AudiobookRecovery.jsx diff --git a/frontend/src/components/audiobook/AudiobookResult.jsx b/electron/src/shared/components/audiobook/AudiobookResult.jsx similarity index 100% rename from frontend/src/components/audiobook/AudiobookResult.jsx rename to electron/src/shared/components/audiobook/AudiobookResult.jsx diff --git a/frontend/src/components/audiobook/AudiobookScriptPanel.jsx b/electron/src/shared/components/audiobook/AudiobookScriptPanel.jsx similarity index 100% rename from frontend/src/components/audiobook/AudiobookScriptPanel.jsx rename to electron/src/shared/components/audiobook/AudiobookScriptPanel.jsx diff --git a/frontend/src/components/audiobook/AudiobookVoicesPanel.jsx b/electron/src/shared/components/audiobook/AudiobookVoicesPanel.jsx similarity index 100% rename from frontend/src/components/audiobook/AudiobookVoicesPanel.jsx rename to electron/src/shared/components/audiobook/AudiobookVoicesPanel.jsx diff --git a/frontend/src/components/audiobook/BookDetails.jsx b/electron/src/shared/components/audiobook/BookDetails.jsx similarity index 100% rename from frontend/src/components/audiobook/BookDetails.jsx rename to electron/src/shared/components/audiobook/BookDetails.jsx diff --git a/frontend/src/components/audiobook/CastPanel.jsx b/electron/src/shared/components/audiobook/CastPanel.jsx similarity index 100% rename from frontend/src/components/audiobook/CastPanel.jsx rename to electron/src/shared/components/audiobook/CastPanel.jsx diff --git a/frontend/src/components/audiobook/GenerationProgress.jsx b/electron/src/shared/components/audiobook/GenerationProgress.jsx similarity index 100% rename from frontend/src/components/audiobook/GenerationProgress.jsx rename to electron/src/shared/components/audiobook/GenerationProgress.jsx diff --git a/frontend/src/components/audiobook/GenerationProgress.test.jsx b/electron/src/shared/components/audiobook/GenerationProgress.test.jsx similarity index 100% rename from frontend/src/components/audiobook/GenerationProgress.test.jsx rename to electron/src/shared/components/audiobook/GenerationProgress.test.jsx diff --git a/frontend/src/components/audiobook/LexiconEditor.jsx b/electron/src/shared/components/audiobook/LexiconEditor.jsx similarity index 100% rename from frontend/src/components/audiobook/LexiconEditor.jsx rename to electron/src/shared/components/audiobook/LexiconEditor.jsx diff --git a/frontend/src/components/audiobook/MarkupToolbar.jsx b/electron/src/shared/components/audiobook/MarkupToolbar.jsx similarity index 100% rename from frontend/src/components/audiobook/MarkupToolbar.jsx rename to electron/src/shared/components/audiobook/MarkupToolbar.jsx diff --git a/frontend/src/components/audiobook/PlanList.jsx b/electron/src/shared/components/audiobook/PlanList.jsx similarity index 100% rename from frontend/src/components/audiobook/PlanList.jsx rename to electron/src/shared/components/audiobook/PlanList.jsx diff --git a/frontend/src/components/audiobook/Section.jsx b/electron/src/shared/components/audiobook/Section.jsx similarity index 100% rename from frontend/src/components/audiobook/Section.jsx rename to electron/src/shared/components/audiobook/Section.jsx diff --git a/frontend/src/components/audiobook/StatsBar.jsx b/electron/src/shared/components/audiobook/StatsBar.jsx similarity index 100% rename from frontend/src/components/audiobook/StatsBar.jsx rename to electron/src/shared/components/audiobook/StatsBar.jsx diff --git a/frontend/src/components/audiobook/SyncedLyricsPlayer.jsx b/electron/src/shared/components/audiobook/SyncedLyricsPlayer.jsx similarity index 100% rename from frontend/src/components/audiobook/SyncedLyricsPlayer.jsx rename to electron/src/shared/components/audiobook/SyncedLyricsPlayer.jsx diff --git a/frontend/src/components/audiobook/SyncedLyricsPlayer.test.jsx b/electron/src/shared/components/audiobook/SyncedLyricsPlayer.test.jsx similarity index 100% rename from frontend/src/components/audiobook/SyncedLyricsPlayer.test.jsx rename to electron/src/shared/components/audiobook/SyncedLyricsPlayer.test.jsx diff --git a/frontend/src/components/audiobook/ValidationWarnings.jsx b/electron/src/shared/components/audiobook/ValidationWarnings.jsx similarity index 100% rename from frontend/src/components/audiobook/ValidationWarnings.jsx rename to electron/src/shared/components/audiobook/ValidationWarnings.jsx diff --git a/frontend/src/components/brand/VoiceStudioMark.jsx b/electron/src/shared/components/brand/VoiceStudioMark.jsx similarity index 100% rename from frontend/src/components/brand/VoiceStudioMark.jsx rename to electron/src/shared/components/brand/VoiceStudioMark.jsx diff --git a/frontend/src/components/captureWaveform.js b/electron/src/shared/components/captureWaveform.js similarity index 100% rename from frontend/src/components/captureWaveform.js rename to electron/src/shared/components/captureWaveform.js diff --git a/frontend/src/components/catalogue/SetupSummary.jsx b/electron/src/shared/components/catalogue/SetupSummary.jsx similarity index 100% rename from frontend/src/components/catalogue/SetupSummary.jsx rename to electron/src/shared/components/catalogue/SetupSummary.jsx diff --git a/frontend/src/components/catalogue/SetupSummary.test.jsx b/electron/src/shared/components/catalogue/SetupSummary.test.jsx similarity index 100% rename from frontend/src/components/catalogue/SetupSummary.test.jsx rename to electron/src/shared/components/catalogue/SetupSummary.test.jsx diff --git a/frontend/src/components/clone/ActionBar.jsx b/electron/src/shared/components/clone/ActionBar.jsx similarity index 100% rename from frontend/src/components/clone/ActionBar.jsx rename to electron/src/shared/components/clone/ActionBar.jsx diff --git a/frontend/src/components/clone/ActionBar.test.jsx b/electron/src/shared/components/clone/ActionBar.test.jsx similarity index 100% rename from frontend/src/components/clone/ActionBar.test.jsx rename to electron/src/shared/components/clone/ActionBar.test.jsx diff --git a/frontend/src/components/clone/AudioMethodPanel.jsx b/electron/src/shared/components/clone/AudioMethodPanel.jsx similarity index 100% rename from frontend/src/components/clone/AudioMethodPanel.jsx rename to electron/src/shared/components/clone/AudioMethodPanel.jsx diff --git a/frontend/src/components/clone/AudioMethodPanel.test.jsx b/electron/src/shared/components/clone/AudioMethodPanel.test.jsx similarity index 100% rename from frontend/src/components/clone/AudioMethodPanel.test.jsx rename to electron/src/shared/components/clone/AudioMethodPanel.test.jsx diff --git a/frontend/src/components/clone/ConvertMethodPanel.jsx b/electron/src/shared/components/clone/ConvertMethodPanel.jsx similarity index 100% rename from frontend/src/components/clone/ConvertMethodPanel.jsx rename to electron/src/shared/components/clone/ConvertMethodPanel.jsx diff --git a/frontend/src/components/clone/ConvertMethodPanel.test.jsx b/electron/src/shared/components/clone/ConvertMethodPanel.test.jsx similarity index 100% rename from frontend/src/components/clone/ConvertMethodPanel.test.jsx rename to electron/src/shared/components/clone/ConvertMethodPanel.test.jsx diff --git a/frontend/src/components/clone/DesignMethodPanel.jsx b/electron/src/shared/components/clone/DesignMethodPanel.jsx similarity index 100% rename from frontend/src/components/clone/DesignMethodPanel.jsx rename to electron/src/shared/components/clone/DesignMethodPanel.jsx diff --git a/frontend/src/components/clone/DesignMethodPanel.test.jsx b/electron/src/shared/components/clone/DesignMethodPanel.test.jsx similarity index 100% rename from frontend/src/components/clone/DesignMethodPanel.test.jsx rename to electron/src/shared/components/clone/DesignMethodPanel.test.jsx diff --git a/frontend/src/components/clone/MicButton.jsx b/electron/src/shared/components/clone/MicButton.jsx similarity index 100% rename from frontend/src/components/clone/MicButton.jsx rename to electron/src/shared/components/clone/MicButton.jsx diff --git a/frontend/src/components/clone/ScriptPanel.jsx b/electron/src/shared/components/clone/ScriptPanel.jsx similarity index 100% rename from frontend/src/components/clone/ScriptPanel.jsx rename to electron/src/shared/components/clone/ScriptPanel.jsx diff --git a/frontend/src/components/clone/ScriptPanel.test.jsx b/electron/src/shared/components/clone/ScriptPanel.test.jsx similarity index 100% rename from frontend/src/components/clone/ScriptPanel.test.jsx rename to electron/src/shared/components/clone/ScriptPanel.test.jsx diff --git a/frontend/src/components/clone/VoiceModeIcon.css b/electron/src/shared/components/clone/VoiceModeIcon.css similarity index 100% rename from frontend/src/components/clone/VoiceModeIcon.css rename to electron/src/shared/components/clone/VoiceModeIcon.css diff --git a/frontend/src/components/clone/VoiceModeIcon.jsx b/electron/src/shared/components/clone/VoiceModeIcon.jsx similarity index 100% rename from frontend/src/components/clone/VoiceModeIcon.jsx rename to electron/src/shared/components/clone/VoiceModeIcon.jsx diff --git a/frontend/src/components/clone/VoiceSelect.jsx b/electron/src/shared/components/clone/VoiceSelect.jsx similarity index 100% rename from frontend/src/components/clone/VoiceSelect.jsx rename to electron/src/shared/components/clone/VoiceSelect.jsx diff --git a/frontend/src/components/computeTarget.jsx b/electron/src/shared/components/computeTarget.jsx similarity index 100% rename from frontend/src/components/computeTarget.jsx rename to electron/src/shared/components/computeTarget.jsx diff --git a/frontend/src/components/donate/GoalBar.jsx b/electron/src/shared/components/donate/GoalBar.jsx similarity index 100% rename from frontend/src/components/donate/GoalBar.jsx rename to electron/src/shared/components/donate/GoalBar.jsx diff --git a/frontend/src/components/donate/Pip.jsx b/electron/src/shared/components/donate/Pip.jsx similarity index 100% rename from frontend/src/components/donate/Pip.jsx rename to electron/src/shared/components/donate/Pip.jsx diff --git a/frontend/src/components/dub/CastingBoard.jsx b/electron/src/shared/components/dub/CastingBoard.jsx similarity index 100% rename from frontend/src/components/dub/CastingBoard.jsx rename to electron/src/shared/components/dub/CastingBoard.jsx diff --git a/frontend/src/components/dub/CastingBoard.test.jsx b/electron/src/shared/components/dub/CastingBoard.test.jsx similarity index 100% rename from frontend/src/components/dub/CastingBoard.test.jsx rename to electron/src/shared/components/dub/CastingBoard.test.jsx diff --git a/frontend/src/components/dub/DubFailureNotice.jsx b/electron/src/shared/components/dub/DubFailureNotice.jsx similarity index 100% rename from frontend/src/components/dub/DubFailureNotice.jsx rename to electron/src/shared/components/dub/DubFailureNotice.jsx diff --git a/frontend/src/components/dub/DubFooter.jsx b/electron/src/shared/components/dub/DubFooter.jsx similarity index 100% rename from frontend/src/components/dub/DubFooter.jsx rename to electron/src/shared/components/dub/DubFooter.jsx diff --git a/frontend/src/components/dub/DubFooter.test.jsx b/electron/src/shared/components/dub/DubFooter.test.jsx similarity index 100% rename from frontend/src/components/dub/DubFooter.test.jsx rename to electron/src/shared/components/dub/DubFooter.test.jsx diff --git a/frontend/src/components/dub/DubHeader.jsx b/electron/src/shared/components/dub/DubHeader.jsx similarity index 100% rename from frontend/src/components/dub/DubHeader.jsx rename to electron/src/shared/components/dub/DubHeader.jsx diff --git a/frontend/src/components/dub/DubHeader.test.jsx b/electron/src/shared/components/dub/DubHeader.test.jsx similarity index 100% rename from frontend/src/components/dub/DubHeader.test.jsx rename to electron/src/shared/components/dub/DubHeader.test.jsx diff --git a/frontend/src/components/dub/DubLeftColumn.css b/electron/src/shared/components/dub/DubLeftColumn.css similarity index 100% rename from frontend/src/components/dub/DubLeftColumn.css rename to electron/src/shared/components/dub/DubLeftColumn.css diff --git a/frontend/src/components/dub/DubLeftColumn.jsx b/electron/src/shared/components/dub/DubLeftColumn.jsx similarity index 100% rename from frontend/src/components/dub/DubLeftColumn.jsx rename to electron/src/shared/components/dub/DubLeftColumn.jsx diff --git a/frontend/src/components/dub/DubPasteTranslationDialog.jsx b/electron/src/shared/components/dub/DubPasteTranslationDialog.jsx similarity index 100% rename from frontend/src/components/dub/DubPasteTranslationDialog.jsx rename to electron/src/shared/components/dub/DubPasteTranslationDialog.jsx diff --git a/frontend/src/components/dub/DubPipelineStepper.jsx b/electron/src/shared/components/dub/DubPipelineStepper.jsx similarity index 100% rename from frontend/src/components/dub/DubPipelineStepper.jsx rename to electron/src/shared/components/dub/DubPipelineStepper.jsx diff --git a/frontend/src/components/dub/DubPipelineStepper.test.jsx b/electron/src/shared/components/dub/DubPipelineStepper.test.jsx similarity index 100% rename from frontend/src/components/dub/DubPipelineStepper.test.jsx rename to electron/src/shared/components/dub/DubPipelineStepper.test.jsx diff --git a/frontend/src/components/dub/DubResizableColumns.jsx b/electron/src/shared/components/dub/DubResizableColumns.jsx similarity index 100% rename from frontend/src/components/dub/DubResizableColumns.jsx rename to electron/src/shared/components/dub/DubResizableColumns.jsx diff --git a/frontend/src/components/dub/DubResizableColumns.test.jsx b/electron/src/shared/components/dub/DubResizableColumns.test.jsx similarity index 100% rename from frontend/src/components/dub/DubResizableColumns.test.jsx rename to electron/src/shared/components/dub/DubResizableColumns.test.jsx diff --git a/frontend/src/components/dub/DubRightColumn.css b/electron/src/shared/components/dub/DubRightColumn.css similarity index 100% rename from frontend/src/components/dub/DubRightColumn.css rename to electron/src/shared/components/dub/DubRightColumn.css diff --git a/frontend/src/components/dub/DubRightColumn.jsx b/electron/src/shared/components/dub/DubRightColumn.jsx similarity index 100% rename from frontend/src/components/dub/DubRightColumn.jsx rename to electron/src/shared/components/dub/DubRightColumn.jsx diff --git a/frontend/src/components/dub/DubRightColumn.test.jsx b/electron/src/shared/components/dub/DubRightColumn.test.jsx similarity index 100% rename from frontend/src/components/dub/DubRightColumn.test.jsx rename to electron/src/shared/components/dub/DubRightColumn.test.jsx diff --git a/frontend/src/components/dub/DubSelectionToolbar.css b/electron/src/shared/components/dub/DubSelectionToolbar.css similarity index 100% rename from frontend/src/components/dub/DubSelectionToolbar.css rename to electron/src/shared/components/dub/DubSelectionToolbar.css diff --git a/frontend/src/components/dub/DubSelectionToolbar.jsx b/electron/src/shared/components/dub/DubSelectionToolbar.jsx similarity index 100% rename from frontend/src/components/dub/DubSelectionToolbar.jsx rename to electron/src/shared/components/dub/DubSelectionToolbar.jsx diff --git a/frontend/src/components/dub/DubToggle.jsx b/electron/src/shared/components/dub/DubToggle.jsx similarity index 100% rename from frontend/src/components/dub/DubToggle.jsx rename to electron/src/shared/components/dub/DubToggle.jsx diff --git a/frontend/src/components/dub/DubToggle.test.jsx b/electron/src/shared/components/dub/DubToggle.test.jsx similarity index 100% rename from frontend/src/components/dub/DubToggle.test.jsx rename to electron/src/shared/components/dub/DubToggle.test.jsx diff --git a/frontend/src/components/dub/DubTrackSummary.jsx b/electron/src/shared/components/dub/DubTrackSummary.jsx similarity index 100% rename from frontend/src/components/dub/DubTrackSummary.jsx rename to electron/src/shared/components/dub/DubTrackSummary.jsx diff --git a/frontend/src/components/dub/DubTrackSummary.test.jsx b/electron/src/shared/components/dub/DubTrackSummary.test.jsx similarity index 100% rename from frontend/src/components/dub/DubTrackSummary.test.jsx rename to electron/src/shared/components/dub/DubTrackSummary.test.jsx diff --git a/frontend/src/components/dub/FooterBtn.jsx b/electron/src/shared/components/dub/FooterBtn.jsx similarity index 100% rename from frontend/src/components/dub/FooterBtn.jsx rename to electron/src/shared/components/dub/FooterBtn.jsx diff --git a/frontend/src/components/dub/IdleSkeleton.jsx b/electron/src/shared/components/dub/IdleSkeleton.jsx similarity index 100% rename from frontend/src/components/dub/IdleSkeleton.jsx rename to electron/src/shared/components/dub/IdleSkeleton.jsx diff --git a/frontend/src/components/dub/PrepOverlay.jsx b/electron/src/shared/components/dub/PrepOverlay.jsx similarity index 100% rename from frontend/src/components/dub/PrepOverlay.jsx rename to electron/src/shared/components/dub/PrepOverlay.jsx diff --git a/frontend/src/components/dub/TrackManager.jsx b/electron/src/shared/components/dub/TrackManager.jsx similarity index 100% rename from frontend/src/components/dub/TrackManager.jsx rename to electron/src/shared/components/dub/TrackManager.jsx diff --git a/frontend/src/components/dub/TrackManager.test.jsx b/electron/src/shared/components/dub/TrackManager.test.jsx similarity index 100% rename from frontend/src/components/dub/TrackManager.test.jsx rename to electron/src/shared/components/dub/TrackManager.test.jsx diff --git a/frontend/src/components/dub/TranscribeOverlay.jsx b/electron/src/shared/components/dub/TranscribeOverlay.jsx similarity index 100% rename from frontend/src/components/dub/TranscribeOverlay.jsx rename to electron/src/shared/components/dub/TranscribeOverlay.jsx diff --git a/frontend/src/components/engines/EngineDetail.jsx b/electron/src/shared/components/engines/EngineDetail.jsx similarity index 100% rename from frontend/src/components/engines/EngineDetail.jsx rename to electron/src/shared/components/engines/EngineDetail.jsx diff --git a/frontend/src/components/engines/EngineWeights.jsx b/electron/src/shared/components/engines/EngineWeights.jsx similarity index 100% rename from frontend/src/components/engines/EngineWeights.jsx rename to electron/src/shared/components/engines/EngineWeights.jsx diff --git a/frontend/src/components/engines/EngineWeights.test.jsx b/electron/src/shared/components/engines/EngineWeights.test.jsx similarity index 100% rename from frontend/src/components/engines/EngineWeights.test.jsx rename to electron/src/shared/components/engines/EngineWeights.test.jsx diff --git a/frontend/src/components/engines/engineDisplay.js b/electron/src/shared/components/engines/engineDisplay.js similarity index 100% rename from frontend/src/components/engines/engineDisplay.js rename to electron/src/shared/components/engines/engineDisplay.js diff --git a/frontend/src/components/engines/useEngineInventory.js b/electron/src/shared/components/engines/useEngineInventory.js similarity index 100% rename from frontend/src/components/engines/useEngineInventory.js rename to electron/src/shared/components/engines/useEngineInventory.js diff --git a/frontend/src/components/gallery/ArchetypeCard.jsx b/electron/src/shared/components/gallery/ArchetypeCard.jsx similarity index 100% rename from frontend/src/components/gallery/ArchetypeCard.jsx rename to electron/src/shared/components/gallery/ArchetypeCard.jsx diff --git a/frontend/src/components/gallery/ArchetypesZone.jsx b/electron/src/shared/components/gallery/ArchetypesZone.jsx similarity index 100% rename from frontend/src/components/gallery/ArchetypesZone.jsx rename to electron/src/shared/components/gallery/ArchetypesZone.jsx diff --git a/frontend/src/components/gallery/ArchetypesZone.test.jsx b/electron/src/shared/components/gallery/ArchetypesZone.test.jsx similarity index 100% rename from frontend/src/components/gallery/ArchetypesZone.test.jsx rename to electron/src/shared/components/gallery/ArchetypesZone.test.jsx diff --git a/frontend/src/components/gallery/CommunityZone.jsx b/electron/src/shared/components/gallery/CommunityZone.jsx similarity index 100% rename from frontend/src/components/gallery/CommunityZone.jsx rename to electron/src/shared/components/gallery/CommunityZone.jsx diff --git a/frontend/src/components/gallery/CommunityZone.test.jsx b/electron/src/shared/components/gallery/CommunityZone.test.jsx similarity index 100% rename from frontend/src/components/gallery/CommunityZone.test.jsx rename to electron/src/shared/components/gallery/CommunityZone.test.jsx diff --git a/frontend/src/components/gallery/GalleryPolish.test.jsx b/electron/src/shared/components/gallery/GalleryPolish.test.jsx similarity index 100% rename from frontend/src/components/gallery/GalleryPolish.test.jsx rename to electron/src/shared/components/gallery/GalleryPolish.test.jsx diff --git a/frontend/src/components/gallery/GallerySectionHeader.jsx b/electron/src/shared/components/gallery/GallerySectionHeader.jsx similarity index 100% rename from frontend/src/components/gallery/GallerySectionHeader.jsx rename to electron/src/shared/components/gallery/GallerySectionHeader.jsx diff --git a/frontend/src/components/gallery/ImportsZone.jsx b/electron/src/shared/components/gallery/ImportsZone.jsx similarity index 100% rename from frontend/src/components/gallery/ImportsZone.jsx rename to electron/src/shared/components/gallery/ImportsZone.jsx diff --git a/frontend/src/components/gallery/ImportsZone.test.jsx b/electron/src/shared/components/gallery/ImportsZone.test.jsx similarity index 100% rename from frontend/src/components/gallery/ImportsZone.test.jsx rename to electron/src/shared/components/gallery/ImportsZone.test.jsx diff --git a/frontend/src/components/gallery/constants.js b/electron/src/shared/components/gallery/constants.js similarity index 100% rename from frontend/src/components/gallery/constants.js rename to electron/src/shared/components/gallery/constants.js diff --git a/frontend/src/components/gallery/facets.d.ts b/electron/src/shared/components/gallery/facets.d.ts similarity index 100% rename from frontend/src/components/gallery/facets.d.ts rename to electron/src/shared/components/gallery/facets.d.ts diff --git a/frontend/src/components/gallery/facets.js b/electron/src/shared/components/gallery/facets.js similarity index 100% rename from frontend/src/components/gallery/facets.js rename to electron/src/shared/components/gallery/facets.js diff --git a/frontend/src/components/navItems.js b/electron/src/shared/components/navItems.js similarity index 100% rename from frontend/src/components/navItems.js rename to electron/src/shared/components/navItems.js diff --git a/frontend/src/components/profile/ProfileActivity.jsx b/electron/src/shared/components/profile/ProfileActivity.jsx similarity index 100% rename from frontend/src/components/profile/ProfileActivity.jsx rename to electron/src/shared/components/profile/ProfileActivity.jsx diff --git a/frontend/src/components/profile/ProfileDetails.jsx b/electron/src/shared/components/profile/ProfileDetails.jsx similarity index 100% rename from frontend/src/components/profile/ProfileDetails.jsx rename to electron/src/shared/components/profile/ProfileDetails.jsx diff --git a/frontend/src/components/profile/ProfileHeader.jsx b/electron/src/shared/components/profile/ProfileHeader.jsx similarity index 100% rename from frontend/src/components/profile/ProfileHeader.jsx rename to electron/src/shared/components/profile/ProfileHeader.jsx diff --git a/frontend/src/components/profile/ProfileInspector.test.jsx b/electron/src/shared/components/profile/ProfileInspector.test.jsx similarity index 100% rename from frontend/src/components/profile/ProfileInspector.test.jsx rename to electron/src/shared/components/profile/ProfileInspector.test.jsx diff --git a/frontend/src/components/settings/AboutTab.jsx b/electron/src/shared/components/settings/AboutTab.jsx similarity index 100% rename from frontend/src/components/settings/AboutTab.jsx rename to electron/src/shared/components/settings/AboutTab.jsx diff --git a/frontend/src/components/settings/AboutTab.test.jsx b/electron/src/shared/components/settings/AboutTab.test.jsx similarity index 100% rename from frontend/src/components/settings/AboutTab.test.jsx rename to electron/src/shared/components/settings/AboutTab.test.jsx diff --git a/frontend/src/components/settings/AecPanel.jsx b/electron/src/shared/components/settings/AecPanel.jsx similarity index 100% rename from frontend/src/components/settings/AecPanel.jsx rename to electron/src/shared/components/settings/AecPanel.jsx diff --git a/frontend/src/components/settings/AnalyticsOptIn.jsx b/electron/src/shared/components/settings/AnalyticsOptIn.jsx similarity index 100% rename from frontend/src/components/settings/AnalyticsOptIn.jsx rename to electron/src/shared/components/settings/AnalyticsOptIn.jsx diff --git a/frontend/src/components/settings/ApiKeysPanel.jsx b/electron/src/shared/components/settings/ApiKeysPanel.jsx similarity index 100% rename from frontend/src/components/settings/ApiKeysPanel.jsx rename to electron/src/shared/components/settings/ApiKeysPanel.jsx diff --git a/frontend/src/components/settings/ApiKeysPanel.test.jsx b/electron/src/shared/components/settings/ApiKeysPanel.test.jsx similarity index 100% rename from frontend/src/components/settings/ApiKeysPanel.test.jsx rename to electron/src/shared/components/settings/ApiKeysPanel.test.jsx diff --git a/frontend/src/components/settings/AppearancePanel.jsx b/electron/src/shared/components/settings/AppearancePanel.jsx similarity index 100% rename from frontend/src/components/settings/AppearancePanel.jsx rename to electron/src/shared/components/settings/AppearancePanel.jsx diff --git a/frontend/src/components/settings/AppearancePanel.test.jsx b/electron/src/shared/components/settings/AppearancePanel.test.jsx similarity index 100% rename from frontend/src/components/settings/AppearancePanel.test.jsx rename to electron/src/shared/components/settings/AppearancePanel.test.jsx diff --git a/frontend/src/components/settings/AsrOpenAICompatPanel.jsx b/electron/src/shared/components/settings/AsrOpenAICompatPanel.jsx similarity index 100% rename from frontend/src/components/settings/AsrOpenAICompatPanel.jsx rename to electron/src/shared/components/settings/AsrOpenAICompatPanel.jsx diff --git a/frontend/src/components/settings/AudioToolsPanel.jsx b/electron/src/shared/components/settings/AudioToolsPanel.jsx similarity index 100% rename from frontend/src/components/settings/AudioToolsPanel.jsx rename to electron/src/shared/components/settings/AudioToolsPanel.jsx diff --git a/frontend/src/components/settings/AudioToolsPanel.test.jsx b/electron/src/shared/components/settings/AudioToolsPanel.test.jsx similarity index 100% rename from frontend/src/components/settings/AudioToolsPanel.test.jsx rename to electron/src/shared/components/settings/AudioToolsPanel.test.jsx diff --git a/frontend/src/components/settings/ComputeDevicePanel.jsx b/electron/src/shared/components/settings/ComputeDevicePanel.jsx similarity index 100% rename from frontend/src/components/settings/ComputeDevicePanel.jsx rename to electron/src/shared/components/settings/ComputeDevicePanel.jsx diff --git a/frontend/src/components/settings/ComputeDevicePanel.test.jsx b/electron/src/shared/components/settings/ComputeDevicePanel.test.jsx similarity index 100% rename from frontend/src/components/settings/ComputeDevicePanel.test.jsx rename to electron/src/shared/components/settings/ComputeDevicePanel.test.jsx diff --git a/frontend/src/components/settings/EnginesTab.jsx b/electron/src/shared/components/settings/EnginesTab.jsx similarity index 100% rename from frontend/src/components/settings/EnginesTab.jsx rename to electron/src/shared/components/settings/EnginesTab.jsx diff --git a/frontend/src/components/settings/EnginesTab.test.jsx b/electron/src/shared/components/settings/EnginesTab.test.jsx similarity index 100% rename from frontend/src/components/settings/EnginesTab.test.jsx rename to electron/src/shared/components/settings/EnginesTab.test.jsx diff --git a/frontend/src/components/settings/GeneralTab.jsx b/electron/src/shared/components/settings/GeneralTab.jsx similarity index 100% rename from frontend/src/components/settings/GeneralTab.jsx rename to electron/src/shared/components/settings/GeneralTab.jsx diff --git a/frontend/src/components/settings/GenerateBudgetPanel.jsx b/electron/src/shared/components/settings/GenerateBudgetPanel.jsx similarity index 100% rename from frontend/src/components/settings/GenerateBudgetPanel.jsx rename to electron/src/shared/components/settings/GenerateBudgetPanel.jsx diff --git a/frontend/src/components/settings/GenerateBudgetPanel.test.jsx b/electron/src/shared/components/settings/GenerateBudgetPanel.test.jsx similarity index 100% rename from frontend/src/components/settings/GenerateBudgetPanel.test.jsx rename to electron/src/shared/components/settings/GenerateBudgetPanel.test.jsx diff --git a/frontend/src/components/settings/HFMirrorPanel.jsx b/electron/src/shared/components/settings/HFMirrorPanel.jsx similarity index 100% rename from frontend/src/components/settings/HFMirrorPanel.jsx rename to electron/src/shared/components/settings/HFMirrorPanel.jsx diff --git a/frontend/src/components/settings/HFMirrorPanel.test.jsx b/electron/src/shared/components/settings/HFMirrorPanel.test.jsx similarity index 100% rename from frontend/src/components/settings/HFMirrorPanel.test.jsx rename to electron/src/shared/components/settings/HFMirrorPanel.test.jsx diff --git a/frontend/src/components/settings/HistoryRetentionPanel.jsx b/electron/src/shared/components/settings/HistoryRetentionPanel.jsx similarity index 100% rename from frontend/src/components/settings/HistoryRetentionPanel.jsx rename to electron/src/shared/components/settings/HistoryRetentionPanel.jsx diff --git a/frontend/src/components/settings/HistoryRetentionPanel.test.jsx b/electron/src/shared/components/settings/HistoryRetentionPanel.test.jsx similarity index 100% rename from frontend/src/components/settings/HistoryRetentionPanel.test.jsx rename to electron/src/shared/components/settings/HistoryRetentionPanel.test.jsx diff --git a/frontend/src/components/settings/HotkeyTab.jsx b/electron/src/shared/components/settings/HotkeyTab.jsx similarity index 100% rename from frontend/src/components/settings/HotkeyTab.jsx rename to electron/src/shared/components/settings/HotkeyTab.jsx diff --git a/frontend/src/components/settings/HotkeyTab.test.jsx b/electron/src/shared/components/settings/HotkeyTab.test.jsx similarity index 100% rename from frontend/src/components/settings/HotkeyTab.test.jsx rename to electron/src/shared/components/settings/HotkeyTab.test.jsx diff --git a/frontend/src/components/settings/InboundNodePanel.jsx b/electron/src/shared/components/settings/InboundNodePanel.jsx similarity index 100% rename from frontend/src/components/settings/InboundNodePanel.jsx rename to electron/src/shared/components/settings/InboundNodePanel.jsx diff --git a/frontend/src/components/settings/InboundNodePanel.test.jsx b/electron/src/shared/components/settings/InboundNodePanel.test.jsx similarity index 100% rename from frontend/src/components/settings/InboundNodePanel.test.jsx rename to electron/src/shared/components/settings/InboundNodePanel.test.jsx diff --git a/frontend/src/components/settings/JoinWorkerPanel.jsx b/electron/src/shared/components/settings/JoinWorkerPanel.jsx similarity index 100% rename from frontend/src/components/settings/JoinWorkerPanel.jsx rename to electron/src/shared/components/settings/JoinWorkerPanel.jsx diff --git a/frontend/src/components/settings/JoinWorkerPanel.test.jsx b/electron/src/shared/components/settings/JoinWorkerPanel.test.jsx similarity index 100% rename from frontend/src/components/settings/JoinWorkerPanel.test.jsx rename to electron/src/shared/components/settings/JoinWorkerPanel.test.jsx diff --git a/frontend/src/components/settings/LLMProvidersPanel.jsx b/electron/src/shared/components/settings/LLMProvidersPanel.jsx similarity index 100% rename from frontend/src/components/settings/LLMProvidersPanel.jsx rename to electron/src/shared/components/settings/LLMProvidersPanel.jsx diff --git a/frontend/src/components/settings/LLMProvidersPanel.test.jsx b/electron/src/shared/components/settings/LLMProvidersPanel.test.jsx similarity index 100% rename from frontend/src/components/settings/LLMProvidersPanel.test.jsx rename to electron/src/shared/components/settings/LLMProvidersPanel.test.jsx diff --git a/frontend/src/components/settings/LLMSkillsPanel.jsx b/electron/src/shared/components/settings/LLMSkillsPanel.jsx similarity index 100% rename from frontend/src/components/settings/LLMSkillsPanel.jsx rename to electron/src/shared/components/settings/LLMSkillsPanel.jsx diff --git a/frontend/src/components/settings/LLMSkillsPanel.test.jsx b/electron/src/shared/components/settings/LLMSkillsPanel.test.jsx similarity index 100% rename from frontend/src/components/settings/LLMSkillsPanel.test.jsx rename to electron/src/shared/components/settings/LLMSkillsPanel.test.jsx diff --git a/frontend/src/components/settings/LogsTab.jsx b/electron/src/shared/components/settings/LogsTab.jsx similarity index 100% rename from frontend/src/components/settings/LogsTab.jsx rename to electron/src/shared/components/settings/LogsTab.jsx diff --git a/frontend/src/components/settings/LogsTab.test.jsx b/electron/src/shared/components/settings/LogsTab.test.jsx similarity index 100% rename from frontend/src/components/settings/LogsTab.test.jsx rename to electron/src/shared/components/settings/LogsTab.test.jsx diff --git a/frontend/src/components/settings/MCPBindingsPanel.jsx b/electron/src/shared/components/settings/MCPBindingsPanel.jsx similarity index 100% rename from frontend/src/components/settings/MCPBindingsPanel.jsx rename to electron/src/shared/components/settings/MCPBindingsPanel.jsx diff --git a/frontend/src/components/settings/MCPBindingsPanel.test.jsx b/electron/src/shared/components/settings/MCPBindingsPanel.test.jsx similarity index 100% rename from frontend/src/components/settings/MCPBindingsPanel.test.jsx rename to electron/src/shared/components/settings/MCPBindingsPanel.test.jsx diff --git a/frontend/src/components/settings/ModelStoreTab.jsx b/electron/src/shared/components/settings/ModelStoreTab.jsx similarity index 100% rename from frontend/src/components/settings/ModelStoreTab.jsx rename to electron/src/shared/components/settings/ModelStoreTab.jsx diff --git a/frontend/src/components/settings/NetworkTab.jsx b/electron/src/shared/components/settings/NetworkTab.jsx similarity index 100% rename from frontend/src/components/settings/NetworkTab.jsx rename to electron/src/shared/components/settings/NetworkTab.jsx diff --git a/frontend/src/components/settings/NetworkTab.test.jsx b/electron/src/shared/components/settings/NetworkTab.test.jsx similarity index 100% rename from frontend/src/components/settings/NetworkTab.test.jsx rename to electron/src/shared/components/settings/NetworkTab.test.jsx diff --git a/frontend/src/components/settings/OpenApiPanel.jsx b/electron/src/shared/components/settings/OpenApiPanel.jsx similarity index 100% rename from frontend/src/components/settings/OpenApiPanel.jsx rename to electron/src/shared/components/settings/OpenApiPanel.jsx diff --git a/frontend/src/components/settings/OpenApiPanel.test.jsx b/electron/src/shared/components/settings/OpenApiPanel.test.jsx similarity index 100% rename from frontend/src/components/settings/OpenApiPanel.test.jsx rename to electron/src/shared/components/settings/OpenApiPanel.test.jsx diff --git a/frontend/src/components/settings/PerformanceDeviceTab.jsx b/electron/src/shared/components/settings/PerformanceDeviceTab.jsx similarity index 100% rename from frontend/src/components/settings/PerformanceDeviceTab.jsx rename to electron/src/shared/components/settings/PerformanceDeviceTab.jsx diff --git a/frontend/src/components/settings/PerformancePanel.jsx b/electron/src/shared/components/settings/PerformancePanel.jsx similarity index 100% rename from frontend/src/components/settings/PerformancePanel.jsx rename to electron/src/shared/components/settings/PerformancePanel.jsx diff --git a/frontend/src/components/settings/PerformancePanel.test.jsx b/electron/src/shared/components/settings/PerformancePanel.test.jsx similarity index 100% rename from frontend/src/components/settings/PerformancePanel.test.jsx rename to electron/src/shared/components/settings/PerformancePanel.test.jsx diff --git a/frontend/src/components/settings/PermissionsPanel.jsx b/electron/src/shared/components/settings/PermissionsPanel.jsx similarity index 100% rename from frontend/src/components/settings/PermissionsPanel.jsx rename to electron/src/shared/components/settings/PermissionsPanel.jsx diff --git a/frontend/src/components/settings/PrivacyTab.jsx b/electron/src/shared/components/settings/PrivacyTab.jsx similarity index 100% rename from frontend/src/components/settings/PrivacyTab.jsx rename to electron/src/shared/components/settings/PrivacyTab.jsx diff --git a/frontend/src/components/settings/PrivacyTab.test.jsx b/electron/src/shared/components/settings/PrivacyTab.test.jsx similarity index 100% rename from frontend/src/components/settings/PrivacyTab.test.jsx rename to electron/src/shared/components/settings/PrivacyTab.test.jsx diff --git a/frontend/src/components/settings/PronunciationPanel.jsx b/electron/src/shared/components/settings/PronunciationPanel.jsx similarity index 100% rename from frontend/src/components/settings/PronunciationPanel.jsx rename to electron/src/shared/components/settings/PronunciationPanel.jsx diff --git a/frontend/src/components/settings/RefinementPanel.jsx b/electron/src/shared/components/settings/RefinementPanel.jsx similarity index 100% rename from frontend/src/components/settings/RefinementPanel.jsx rename to electron/src/shared/components/settings/RefinementPanel.jsx diff --git a/frontend/src/components/settings/RemoteBackendPanel.jsx b/electron/src/shared/components/settings/RemoteBackendPanel.jsx similarity index 100% rename from frontend/src/components/settings/RemoteBackendPanel.jsx rename to electron/src/shared/components/settings/RemoteBackendPanel.jsx diff --git a/frontend/src/components/settings/RemoteBackendPanel.test.jsx b/electron/src/shared/components/settings/RemoteBackendPanel.test.jsx similarity index 100% rename from frontend/src/components/settings/RemoteBackendPanel.test.jsx rename to electron/src/shared/components/settings/RemoteBackendPanel.test.jsx diff --git a/frontend/src/components/settings/ResetPanel.jsx b/electron/src/shared/components/settings/ResetPanel.jsx similarity index 100% rename from frontend/src/components/settings/ResetPanel.jsx rename to electron/src/shared/components/settings/ResetPanel.jsx diff --git a/frontend/src/components/settings/ResetPanel.test.jsx b/electron/src/shared/components/settings/ResetPanel.test.jsx similarity index 100% rename from frontend/src/components/settings/ResetPanel.test.jsx rename to electron/src/shared/components/settings/ResetPanel.test.jsx diff --git a/frontend/src/components/settings/RestartBadge.jsx b/electron/src/shared/components/settings/RestartBadge.jsx similarity index 100% rename from frontend/src/components/settings/RestartBadge.jsx rename to electron/src/shared/components/settings/RestartBadge.jsx diff --git a/frontend/src/components/settings/Row.jsx b/electron/src/shared/components/settings/Row.jsx similarity index 100% rename from frontend/src/components/settings/Row.jsx rename to electron/src/shared/components/settings/Row.jsx diff --git a/frontend/src/components/settings/ScalarApiReference.jsx b/electron/src/shared/components/settings/ScalarApiReference.jsx similarity index 100% rename from frontend/src/components/settings/ScalarApiReference.jsx rename to electron/src/shared/components/settings/ScalarApiReference.jsx diff --git a/frontend/src/components/settings/SettingsSearch.jsx b/electron/src/shared/components/settings/SettingsSearch.jsx similarity index 100% rename from frontend/src/components/settings/SettingsSearch.jsx rename to electron/src/shared/components/settings/SettingsSearch.jsx diff --git a/frontend/src/components/settings/SettingsSidebar.jsx b/electron/src/shared/components/settings/SettingsSidebar.jsx similarity index 100% rename from frontend/src/components/settings/SettingsSidebar.jsx rename to electron/src/shared/components/settings/SettingsSidebar.jsx diff --git a/frontend/src/components/settings/SettingsSidebar.test.jsx b/electron/src/shared/components/settings/SettingsSidebar.test.jsx similarity index 100% rename from frontend/src/components/settings/SettingsSidebar.test.jsx rename to electron/src/shared/components/settings/SettingsSidebar.test.jsx diff --git a/frontend/src/components/settings/SharingPanel.jsx b/electron/src/shared/components/settings/SharingPanel.jsx similarity index 100% rename from frontend/src/components/settings/SharingPanel.jsx rename to electron/src/shared/components/settings/SharingPanel.jsx diff --git a/frontend/src/components/settings/SharingPanel.test.jsx b/electron/src/shared/components/settings/SharingPanel.test.jsx similarity index 100% rename from frontend/src/components/settings/SharingPanel.test.jsx rename to electron/src/shared/components/settings/SharingPanel.test.jsx diff --git a/frontend/src/components/settings/StoragePanel.jsx b/electron/src/shared/components/settings/StoragePanel.jsx similarity index 100% rename from frontend/src/components/settings/StoragePanel.jsx rename to electron/src/shared/components/settings/StoragePanel.jsx diff --git a/frontend/src/components/settings/StoragePanel.test.jsx b/electron/src/shared/components/settings/StoragePanel.test.jsx similarity index 100% rename from frontend/src/components/settings/StoragePanel.test.jsx rename to electron/src/shared/components/settings/StoragePanel.test.jsx diff --git a/frontend/src/components/settings/StorageTab.jsx b/electron/src/shared/components/settings/StorageTab.jsx similarity index 100% rename from frontend/src/components/settings/StorageTab.jsx rename to electron/src/shared/components/settings/StorageTab.jsx diff --git a/frontend/src/components/settings/StorageTab.test.jsx b/electron/src/shared/components/settings/StorageTab.test.jsx similarity index 100% rename from frontend/src/components/settings/StorageTab.test.jsx rename to electron/src/shared/components/settings/StorageTab.test.jsx diff --git a/frontend/src/components/settings/StorageTargetRow.jsx b/electron/src/shared/components/settings/StorageTargetRow.jsx similarity index 100% rename from frontend/src/components/settings/StorageTargetRow.jsx rename to electron/src/shared/components/settings/StorageTargetRow.jsx diff --git a/frontend/src/components/settings/StorageUsagePanel.jsx b/electron/src/shared/components/settings/StorageUsagePanel.jsx similarity index 100% rename from frontend/src/components/settings/StorageUsagePanel.jsx rename to electron/src/shared/components/settings/StorageUsagePanel.jsx diff --git a/frontend/src/components/settings/StorageUsagePanel.test.jsx b/electron/src/shared/components/settings/StorageUsagePanel.test.jsx similarity index 100% rename from frontend/src/components/settings/StorageUsagePanel.test.jsx rename to electron/src/shared/components/settings/StorageUsagePanel.test.jsx diff --git a/frontend/src/components/settings/TranslationTab.jsx b/electron/src/shared/components/settings/TranslationTab.jsx similarity index 100% rename from frontend/src/components/settings/TranslationTab.jsx rename to electron/src/shared/components/settings/TranslationTab.jsx diff --git a/frontend/src/components/settings/TranslationTab.test.jsx b/electron/src/shared/components/settings/TranslationTab.test.jsx similarity index 100% rename from frontend/src/components/settings/TranslationTab.test.jsx rename to electron/src/shared/components/settings/TranslationTab.test.jsx diff --git a/frontend/src/components/settings/UninstallPanel.jsx b/electron/src/shared/components/settings/UninstallPanel.jsx similarity index 100% rename from frontend/src/components/settings/UninstallPanel.jsx rename to electron/src/shared/components/settings/UninstallPanel.jsx diff --git a/frontend/src/components/settings/UninstallPanel.test.jsx b/electron/src/shared/components/settings/UninstallPanel.test.jsx similarity index 100% rename from frontend/src/components/settings/UninstallPanel.test.jsx rename to electron/src/shared/components/settings/UninstallPanel.test.jsx diff --git a/frontend/src/components/settings/UsageTab.jsx b/electron/src/shared/components/settings/UsageTab.jsx similarity index 100% rename from frontend/src/components/settings/UsageTab.jsx rename to electron/src/shared/components/settings/UsageTab.jsx diff --git a/frontend/src/components/settings/VoicePanel.jsx b/electron/src/shared/components/settings/VoicePanel.jsx similarity index 100% rename from frontend/src/components/settings/VoicePanel.jsx rename to electron/src/shared/components/settings/VoicePanel.jsx diff --git a/frontend/src/components/settings/VoicePreviewsPanel.jsx b/electron/src/shared/components/settings/VoicePreviewsPanel.jsx similarity index 100% rename from frontend/src/components/settings/VoicePreviewsPanel.jsx rename to electron/src/shared/components/settings/VoicePreviewsPanel.jsx diff --git a/frontend/src/components/settings/VoicePreviewsPanel.test.jsx b/electron/src/shared/components/settings/VoicePreviewsPanel.test.jsx similarity index 100% rename from frontend/src/components/settings/VoicePreviewsPanel.test.jsx rename to electron/src/shared/components/settings/VoicePreviewsPanel.test.jsx diff --git a/frontend/src/components/settings/WatermarkControl.jsx b/electron/src/shared/components/settings/WatermarkControl.jsx similarity index 100% rename from frontend/src/components/settings/WatermarkControl.jsx rename to electron/src/shared/components/settings/WatermarkControl.jsx diff --git a/frontend/src/components/settings/WorkersPanel.jsx b/electron/src/shared/components/settings/WorkersPanel.jsx similarity index 100% rename from frontend/src/components/settings/WorkersPanel.jsx rename to electron/src/shared/components/settings/WorkersPanel.jsx diff --git a/frontend/src/components/settings/WorkersPanel.test.jsx b/electron/src/shared/components/settings/WorkersPanel.test.jsx similarity index 100% rename from frontend/src/components/settings/WorkersPanel.test.jsx rename to electron/src/shared/components/settings/WorkersPanel.test.jsx diff --git a/frontend/src/components/settings/bytes.js b/electron/src/shared/components/settings/bytes.js similarity index 100% rename from frontend/src/components/settings/bytes.js rename to electron/src/shared/components/settings/bytes.js diff --git a/frontend/src/components/settings/models/ModelSection.jsx b/electron/src/shared/components/settings/models/ModelSection.jsx similarity index 100% rename from frontend/src/components/settings/models/ModelSection.jsx rename to electron/src/shared/components/settings/models/ModelSection.jsx diff --git a/frontend/src/components/settings/models/ModelsTable.jsx b/electron/src/shared/components/settings/models/ModelsTable.jsx similarity index 100% rename from frontend/src/components/settings/models/ModelsTable.jsx rename to electron/src/shared/components/settings/models/ModelsTable.jsx diff --git a/frontend/src/components/settings/models/columns.jsx b/electron/src/shared/components/settings/models/columns.jsx similarity index 100% rename from frontend/src/components/settings/models/columns.jsx rename to electron/src/shared/components/settings/models/columns.jsx diff --git a/frontend/src/components/settings/models/downloadReducer.js b/electron/src/shared/components/settings/models/downloadReducer.js similarity index 100% rename from frontend/src/components/settings/models/downloadReducer.js rename to electron/src/shared/components/settings/models/downloadReducer.js diff --git a/frontend/src/components/settings/models/format.d.ts b/electron/src/shared/components/settings/models/format.d.ts similarity index 100% rename from frontend/src/components/settings/models/format.d.ts rename to electron/src/shared/components/settings/models/format.d.ts diff --git a/frontend/src/components/settings/models/format.js b/electron/src/shared/components/settings/models/format.js similarity index 100% rename from frontend/src/components/settings/models/format.js rename to electron/src/shared/components/settings/models/format.js diff --git a/frontend/src/components/settings/models/installResults.js b/electron/src/shared/components/settings/models/installResults.js similarity index 100% rename from frontend/src/components/settings/models/installResults.js rename to electron/src/shared/components/settings/models/installResults.js diff --git a/frontend/src/components/settings/models/installResults.test.js b/electron/src/shared/components/settings/models/installResults.test.js similarity index 100% rename from frontend/src/components/settings/models/installResults.test.js rename to electron/src/shared/components/settings/models/installResults.test.js diff --git a/frontend/src/components/settings/models/progressText.js b/electron/src/shared/components/settings/models/progressText.js similarity index 100% rename from frontend/src/components/settings/models/progressText.js rename to electron/src/shared/components/settings/models/progressText.js diff --git a/frontend/src/components/settings/models/runtime.js b/electron/src/shared/components/settings/models/runtime.js similarity index 100% rename from frontend/src/components/settings/models/runtime.js rename to electron/src/shared/components/settings/models/runtime.js diff --git a/frontend/src/components/settings/models/sections.js b/electron/src/shared/components/settings/models/sections.js similarity index 100% rename from frontend/src/components/settings/models/sections.js rename to electron/src/shared/components/settings/models/sections.js diff --git a/frontend/src/components/settings/models/useModelDownloads.js b/electron/src/shared/components/settings/models/useModelDownloads.js similarity index 100% rename from frontend/src/components/settings/models/useModelDownloads.js rename to electron/src/shared/components/settings/models/useModelDownloads.js diff --git a/frontend/src/components/settings/native.js b/electron/src/shared/components/settings/native.js similarity index 100% rename from frontend/src/components/settings/native.js rename to electron/src/shared/components/settings/native.js diff --git a/frontend/src/components/settings/primitives/Collapsible.jsx b/electron/src/shared/components/settings/primitives/Collapsible.jsx similarity index 100% rename from frontend/src/components/settings/primitives/Collapsible.jsx rename to electron/src/shared/components/settings/primitives/Collapsible.jsx diff --git a/frontend/src/components/settings/primitives/InfoHint.jsx b/electron/src/shared/components/settings/primitives/InfoHint.jsx similarity index 100% rename from frontend/src/components/settings/primitives/InfoHint.jsx rename to electron/src/shared/components/settings/primitives/InfoHint.jsx diff --git a/frontend/src/components/settings/primitives/SettingRow.jsx b/electron/src/shared/components/settings/primitives/SettingRow.jsx similarity index 100% rename from frontend/src/components/settings/primitives/SettingRow.jsx rename to electron/src/shared/components/settings/primitives/SettingRow.jsx diff --git a/frontend/src/components/settings/primitives/SettingsInput.jsx b/electron/src/shared/components/settings/primitives/SettingsInput.jsx similarity index 100% rename from frontend/src/components/settings/primitives/SettingsInput.jsx rename to electron/src/shared/components/settings/primitives/SettingsInput.jsx diff --git a/frontend/src/components/settings/primitives/SettingsPrimitives.test.jsx b/electron/src/shared/components/settings/primitives/SettingsPrimitives.test.jsx similarity index 100% rename from frontend/src/components/settings/primitives/SettingsPrimitives.test.jsx rename to electron/src/shared/components/settings/primitives/SettingsPrimitives.test.jsx diff --git a/frontend/src/components/settings/primitives/SettingsSection.jsx b/electron/src/shared/components/settings/primitives/SettingsSection.jsx similarity index 100% rename from frontend/src/components/settings/primitives/SettingsSection.jsx rename to electron/src/shared/components/settings/primitives/SettingsSection.jsx diff --git a/frontend/src/components/settings/primitives/SettingsToggle.jsx b/electron/src/shared/components/settings/primitives/SettingsToggle.jsx similarity index 100% rename from frontend/src/components/settings/primitives/SettingsToggle.jsx rename to electron/src/shared/components/settings/primitives/SettingsToggle.jsx diff --git a/frontend/src/components/settings/primitives/index.js b/electron/src/shared/components/settings/primitives/index.js similarity index 100% rename from frontend/src/components/settings/primitives/index.js rename to electron/src/shared/components/settings/primitives/index.js diff --git a/frontend/src/components/settings/refineStatus.d.ts b/electron/src/shared/components/settings/refineStatus.d.ts similarity index 100% rename from frontend/src/components/settings/refineStatus.d.ts rename to electron/src/shared/components/settings/refineStatus.d.ts diff --git a/frontend/src/components/settings/refineStatus.js b/electron/src/shared/components/settings/refineStatus.js similarity index 100% rename from frontend/src/components/settings/refineStatus.js rename to electron/src/shared/components/settings/refineStatus.js diff --git a/frontend/src/components/settings/settingsCategories.jsx b/electron/src/shared/components/settings/settingsCategories.jsx similarity index 100% rename from frontend/src/components/settings/settingsCategories.jsx rename to electron/src/shared/components/settings/settingsCategories.jsx diff --git a/frontend/src/components/settings/settingsCategories.test.jsx b/electron/src/shared/components/settings/settingsCategories.test.jsx similarity index 100% rename from frontend/src/components/settings/settingsCategories.test.jsx rename to electron/src/shared/components/settings/settingsCategories.test.jsx diff --git a/frontend/src/components/ui/badge.tsx b/electron/src/shared/components/ui/badge.tsx similarity index 100% rename from frontend/src/components/ui/badge.tsx rename to electron/src/shared/components/ui/badge.tsx diff --git a/frontend/src/components/ui/button.tsx b/electron/src/shared/components/ui/button.tsx similarity index 100% rename from frontend/src/components/ui/button.tsx rename to electron/src/shared/components/ui/button.tsx diff --git a/frontend/src/components/ui/card.tsx b/electron/src/shared/components/ui/card.tsx similarity index 100% rename from frontend/src/components/ui/card.tsx rename to electron/src/shared/components/ui/card.tsx diff --git a/frontend/src/components/ui/dialog.tsx b/electron/src/shared/components/ui/dialog.tsx similarity index 100% rename from frontend/src/components/ui/dialog.tsx rename to electron/src/shared/components/ui/dialog.tsx diff --git a/frontend/src/components/ui/dropdown-menu.tsx b/electron/src/shared/components/ui/dropdown-menu.tsx similarity index 100% rename from frontend/src/components/ui/dropdown-menu.tsx rename to electron/src/shared/components/ui/dropdown-menu.tsx diff --git a/frontend/src/components/ui/input.tsx b/electron/src/shared/components/ui/input.tsx similarity index 100% rename from frontend/src/components/ui/input.tsx rename to electron/src/shared/components/ui/input.tsx diff --git a/frontend/src/components/ui/progress.tsx b/electron/src/shared/components/ui/progress.tsx similarity index 100% rename from frontend/src/components/ui/progress.tsx rename to electron/src/shared/components/ui/progress.tsx diff --git a/frontend/src/components/ui/select.tsx b/electron/src/shared/components/ui/select.tsx similarity index 100% rename from frontend/src/components/ui/select.tsx rename to electron/src/shared/components/ui/select.tsx diff --git a/frontend/src/components/ui/slider.tsx b/electron/src/shared/components/ui/slider.tsx similarity index 100% rename from frontend/src/components/ui/slider.tsx rename to electron/src/shared/components/ui/slider.tsx diff --git a/frontend/src/components/ui/table.tsx b/electron/src/shared/components/ui/table.tsx similarity index 100% rename from frontend/src/components/ui/table.tsx rename to electron/src/shared/components/ui/table.tsx diff --git a/frontend/src/components/ui/tabs.tsx b/electron/src/shared/components/ui/tabs.tsx similarity index 100% rename from frontend/src/components/ui/tabs.tsx rename to electron/src/shared/components/ui/tabs.tsx diff --git a/frontend/src/components/ui/textarea.tsx b/electron/src/shared/components/ui/textarea.tsx similarity index 100% rename from frontend/src/components/ui/textarea.tsx rename to electron/src/shared/components/ui/textarea.tsx diff --git a/frontend/src/components/ui/toggle-group.tsx b/electron/src/shared/components/ui/toggle-group.tsx similarity index 100% rename from frontend/src/components/ui/toggle-group.tsx rename to electron/src/shared/components/ui/toggle-group.tsx diff --git a/frontend/src/components/ui/toggle.tsx b/electron/src/shared/components/ui/toggle.tsx similarity index 100% rename from frontend/src/components/ui/toggle.tsx rename to electron/src/shared/components/ui/toggle.tsx diff --git a/frontend/src/components/ui/tooltip.tsx b/electron/src/shared/components/ui/tooltip.tsx similarity index 100% rename from frontend/src/components/ui/tooltip.tsx rename to electron/src/shared/components/ui/tooltip.tsx diff --git a/frontend/src/config/integration-catalog.d.ts b/electron/src/shared/config/integration-catalog.d.ts similarity index 100% rename from frontend/src/config/integration-catalog.d.ts rename to electron/src/shared/config/integration-catalog.d.ts diff --git a/frontend/src/config/integration-catalog.js b/electron/src/shared/config/integration-catalog.js similarity index 100% rename from frontend/src/config/integration-catalog.js rename to electron/src/shared/config/integration-catalog.js diff --git a/frontend/src/config/sponsors.d.ts b/electron/src/shared/config/sponsors.d.ts similarity index 100% rename from frontend/src/config/sponsors.d.ts rename to electron/src/shared/config/sponsors.d.ts diff --git a/frontend/src/config/sponsors.js b/electron/src/shared/config/sponsors.js similarity index 100% rename from frontend/src/config/sponsors.js rename to electron/src/shared/config/sponsors.js diff --git a/frontend/src/config/voice-ai-directory.d.ts b/electron/src/shared/config/voice-ai-directory.d.ts similarity index 100% rename from frontend/src/config/voice-ai-directory.d.ts rename to electron/src/shared/config/voice-ai-directory.d.ts diff --git a/frontend/src/config/voice-ai-directory.js b/electron/src/shared/config/voice-ai-directory.js similarity index 100% rename from frontend/src/config/voice-ai-directory.js rename to electron/src/shared/config/voice-ai-directory.js diff --git a/frontend/src/data/sampleAudiobook.d.ts b/electron/src/shared/data/sampleAudiobook.d.ts similarity index 100% rename from frontend/src/data/sampleAudiobook.d.ts rename to electron/src/shared/data/sampleAudiobook.d.ts diff --git a/frontend/src/data/sampleAudiobook.js b/electron/src/shared/data/sampleAudiobook.js similarity index 100% rename from frontend/src/data/sampleAudiobook.js rename to electron/src/shared/data/sampleAudiobook.js diff --git a/frontend/src/data/sampleStory.d.ts b/electron/src/shared/data/sampleStory.d.ts similarity index 100% rename from frontend/src/data/sampleStory.d.ts rename to electron/src/shared/data/sampleStory.d.ts diff --git a/frontend/src/data/sampleStory.js b/electron/src/shared/data/sampleStory.js similarity index 100% rename from frontend/src/data/sampleStory.js rename to electron/src/shared/data/sampleStory.js diff --git a/frontend/src/hooks/useAppData.js b/electron/src/shared/hooks/useAppData.js similarity index 100% rename from frontend/src/hooks/useAppData.js rename to electron/src/shared/hooks/useAppData.js diff --git a/frontend/src/hooks/useAppData.persistence.test.jsx b/electron/src/shared/hooks/useAppData.persistence.test.jsx similarity index 100% rename from frontend/src/hooks/useAppData.persistence.test.jsx rename to electron/src/shared/hooks/useAppData.persistence.test.jsx diff --git a/frontend/src/hooks/useAudiobookLexicon.js b/electron/src/shared/hooks/useAudiobookLexicon.js similarity index 100% rename from frontend/src/hooks/useAudiobookLexicon.js rename to electron/src/shared/hooks/useAudiobookLexicon.js diff --git a/frontend/src/hooks/useDictationReadiness.js b/electron/src/shared/hooks/useDictationReadiness.js similarity index 100% rename from frontend/src/hooks/useDictationReadiness.js rename to electron/src/shared/hooks/useDictationReadiness.js diff --git a/frontend/src/hooks/useDictationReadiness.test.jsx b/electron/src/shared/hooks/useDictationReadiness.test.jsx similarity index 100% rename from frontend/src/hooks/useDictationReadiness.test.jsx rename to electron/src/shared/hooks/useDictationReadiness.test.jsx diff --git a/frontend/src/hooks/useDubLivePreview.js b/electron/src/shared/hooks/useDubLivePreview.js similarity index 100% rename from frontend/src/hooks/useDubLivePreview.js rename to electron/src/shared/hooks/useDubLivePreview.js diff --git a/frontend/src/hooks/useDubWorkflow.js b/electron/src/shared/hooks/useDubWorkflow.js similarity index 100% rename from frontend/src/hooks/useDubWorkflow.js rename to electron/src/shared/hooks/useDubWorkflow.js diff --git a/frontend/src/hooks/useEffectiveDictationShortcut.js b/electron/src/shared/hooks/useEffectiveDictationShortcut.js similarity index 100% rename from frontend/src/hooks/useEffectiveDictationShortcut.js rename to electron/src/shared/hooks/useEffectiveDictationShortcut.js diff --git a/frontend/src/hooks/useOpenApiDeepLink.js b/electron/src/shared/hooks/useOpenApiDeepLink.js similarity index 100% rename from frontend/src/hooks/useOpenApiDeepLink.js rename to electron/src/shared/hooks/useOpenApiDeepLink.js diff --git a/frontend/src/hooks/useOpenApiDeepLink.test.js b/electron/src/shared/hooks/useOpenApiDeepLink.test.js similarity index 100% rename from frontend/src/hooks/useOpenApiDeepLink.test.js rename to electron/src/shared/hooks/useOpenApiDeepLink.test.js diff --git a/frontend/src/hooks/usePermissions.js b/electron/src/shared/hooks/usePermissions.js similarity index 100% rename from frontend/src/hooks/usePermissions.js rename to electron/src/shared/hooks/usePermissions.js diff --git a/frontend/src/hooks/useProfiles.js b/electron/src/shared/hooks/useProfiles.js similarity index 100% rename from frontend/src/hooks/useProfiles.js rename to electron/src/shared/hooks/useProfiles.js diff --git a/frontend/src/hooks/useProfiles.test.jsx b/electron/src/shared/hooks/useProfiles.test.jsx similarity index 100% rename from frontend/src/hooks/useProfiles.test.jsx rename to electron/src/shared/hooks/useProfiles.test.jsx diff --git a/frontend/src/hooks/useRealtimeEvents.js b/electron/src/shared/hooks/useRealtimeEvents.js similarity index 100% rename from frontend/src/hooks/useRealtimeEvents.js rename to electron/src/shared/hooks/useRealtimeEvents.js diff --git a/frontend/src/hooks/useRecording.js b/electron/src/shared/hooks/useRecording.js similarity index 100% rename from frontend/src/hooks/useRecording.js rename to electron/src/shared/hooks/useRecording.js diff --git a/frontend/src/hooks/useResponsiveShellSize.js b/electron/src/shared/hooks/useResponsiveShellSize.js similarity index 100% rename from frontend/src/hooks/useResponsiveShellSize.js rename to electron/src/shared/hooks/useResponsiveShellSize.js diff --git a/frontend/src/hooks/useResponsiveShellSize.test.jsx b/electron/src/shared/hooks/useResponsiveShellSize.test.jsx similarity index 100% rename from frontend/src/hooks/useResponsiveShellSize.test.jsx rename to electron/src/shared/hooks/useResponsiveShellSize.test.jsx diff --git a/frontend/src/hooks/useSegmentEditing.js b/electron/src/shared/hooks/useSegmentEditing.js similarity index 100% rename from frontend/src/hooks/useSegmentEditing.js rename to electron/src/shared/hooks/useSegmentEditing.js diff --git a/frontend/src/hooks/useShellNarrow.js b/electron/src/shared/hooks/useShellNarrow.js similarity index 100% rename from frontend/src/hooks/useShellNarrow.js rename to electron/src/shared/hooks/useShellNarrow.js diff --git a/frontend/src/hooks/useTTS.js b/electron/src/shared/hooks/useTTS.js similarity index 100% rename from frontend/src/hooks/useTTS.js rename to electron/src/shared/hooks/useTTS.js diff --git a/frontend/src/hooks/useTimelineOnsets.js b/electron/src/shared/hooks/useTimelineOnsets.js similarity index 100% rename from frontend/src/hooks/useTimelineOnsets.js rename to electron/src/shared/hooks/useTimelineOnsets.js diff --git a/frontend/src/i18n/index.ts b/electron/src/shared/i18n/index.ts similarity index 100% rename from frontend/src/i18n/index.ts rename to electron/src/shared/i18n/index.ts diff --git a/frontend/src/i18n/locales/ar.json b/electron/src/shared/i18n/locales/ar.json similarity index 100% rename from frontend/src/i18n/locales/ar.json rename to electron/src/shared/i18n/locales/ar.json diff --git a/frontend/src/i18n/locales/de.json b/electron/src/shared/i18n/locales/de.json similarity index 100% rename from frontend/src/i18n/locales/de.json rename to electron/src/shared/i18n/locales/de.json diff --git a/frontend/src/i18n/locales/en.json b/electron/src/shared/i18n/locales/en.json similarity index 100% rename from frontend/src/i18n/locales/en.json rename to electron/src/shared/i18n/locales/en.json diff --git a/frontend/src/i18n/locales/es.json b/electron/src/shared/i18n/locales/es.json similarity index 100% rename from frontend/src/i18n/locales/es.json rename to electron/src/shared/i18n/locales/es.json diff --git a/frontend/src/i18n/locales/fr.json b/electron/src/shared/i18n/locales/fr.json similarity index 100% rename from frontend/src/i18n/locales/fr.json rename to electron/src/shared/i18n/locales/fr.json diff --git a/frontend/src/i18n/locales/hi.json b/electron/src/shared/i18n/locales/hi.json similarity index 100% rename from frontend/src/i18n/locales/hi.json rename to electron/src/shared/i18n/locales/hi.json diff --git a/frontend/src/i18n/locales/id.json b/electron/src/shared/i18n/locales/id.json similarity index 100% rename from frontend/src/i18n/locales/id.json rename to electron/src/shared/i18n/locales/id.json diff --git a/frontend/src/i18n/locales/it.json b/electron/src/shared/i18n/locales/it.json similarity index 100% rename from frontend/src/i18n/locales/it.json rename to electron/src/shared/i18n/locales/it.json diff --git a/frontend/src/i18n/locales/ja.json b/electron/src/shared/i18n/locales/ja.json similarity index 100% rename from frontend/src/i18n/locales/ja.json rename to electron/src/shared/i18n/locales/ja.json diff --git a/frontend/src/i18n/locales/ko.json b/electron/src/shared/i18n/locales/ko.json similarity index 100% rename from frontend/src/i18n/locales/ko.json rename to electron/src/shared/i18n/locales/ko.json diff --git a/frontend/src/i18n/locales/nl.json b/electron/src/shared/i18n/locales/nl.json similarity index 100% rename from frontend/src/i18n/locales/nl.json rename to electron/src/shared/i18n/locales/nl.json diff --git a/frontend/src/i18n/locales/pl.json b/electron/src/shared/i18n/locales/pl.json similarity index 100% rename from frontend/src/i18n/locales/pl.json rename to electron/src/shared/i18n/locales/pl.json diff --git a/frontend/src/i18n/locales/pt.json b/electron/src/shared/i18n/locales/pt.json similarity index 100% rename from frontend/src/i18n/locales/pt.json rename to electron/src/shared/i18n/locales/pt.json diff --git a/frontend/src/i18n/locales/ru.json b/electron/src/shared/i18n/locales/ru.json similarity index 100% rename from frontend/src/i18n/locales/ru.json rename to electron/src/shared/i18n/locales/ru.json diff --git a/frontend/src/i18n/locales/sv.json b/electron/src/shared/i18n/locales/sv.json similarity index 100% rename from frontend/src/i18n/locales/sv.json rename to electron/src/shared/i18n/locales/sv.json diff --git a/frontend/src/i18n/locales/th.json b/electron/src/shared/i18n/locales/th.json similarity index 100% rename from frontend/src/i18n/locales/th.json rename to electron/src/shared/i18n/locales/th.json diff --git a/frontend/src/i18n/locales/tr.json b/electron/src/shared/i18n/locales/tr.json similarity index 100% rename from frontend/src/i18n/locales/tr.json rename to electron/src/shared/i18n/locales/tr.json diff --git a/frontend/src/i18n/locales/uk.json b/electron/src/shared/i18n/locales/uk.json similarity index 100% rename from frontend/src/i18n/locales/uk.json rename to electron/src/shared/i18n/locales/uk.json diff --git a/frontend/src/i18n/locales/vi.json b/electron/src/shared/i18n/locales/vi.json similarity index 100% rename from frontend/src/i18n/locales/vi.json rename to electron/src/shared/i18n/locales/vi.json diff --git a/frontend/src/i18n/locales/zh-CN.json b/electron/src/shared/i18n/locales/zh-CN.json similarity index 100% rename from frontend/src/i18n/locales/zh-CN.json rename to electron/src/shared/i18n/locales/zh-CN.json diff --git a/frontend/src/i18n/locales/zh-TW.json b/electron/src/shared/i18n/locales/zh-TW.json similarity index 100% rename from frontend/src/i18n/locales/zh-TW.json rename to electron/src/shared/i18n/locales/zh-TW.json diff --git a/frontend/src/languages.json b/electron/src/shared/languages.json similarity index 100% rename from frontend/src/languages.json rename to electron/src/shared/languages.json diff --git a/frontend/src/lib/utils.ts b/electron/src/shared/lib/utils.ts similarity index 100% rename from frontend/src/lib/utils.ts rename to electron/src/shared/lib/utils.ts diff --git a/frontend/src/pages/AudiobookTab.jsx b/electron/src/shared/pages/AudiobookTab.jsx similarity index 100% rename from frontend/src/pages/AudiobookTab.jsx rename to electron/src/shared/pages/AudiobookTab.jsx diff --git a/frontend/src/pages/BatchQueue.jsx b/electron/src/shared/pages/BatchQueue.jsx similarity index 100% rename from frontend/src/pages/BatchQueue.jsx rename to electron/src/shared/pages/BatchQueue.jsx diff --git a/frontend/src/pages/CloneDesignTab.jsx b/electron/src/shared/pages/CloneDesignTab.jsx similarity index 100% rename from frontend/src/pages/CloneDesignTab.jsx rename to electron/src/shared/pages/CloneDesignTab.jsx diff --git a/frontend/src/pages/CloneDesignTab.test.jsx b/electron/src/shared/pages/CloneDesignTab.test.jsx similarity index 100% rename from frontend/src/pages/CloneDesignTab.test.jsx rename to electron/src/shared/pages/CloneDesignTab.test.jsx diff --git a/frontend/src/pages/ContactPage.jsx b/electron/src/shared/pages/ContactPage.jsx similarity index 100% rename from frontend/src/pages/ContactPage.jsx rename to electron/src/shared/pages/ContactPage.jsx diff --git a/frontend/src/pages/DubTab.jsx b/electron/src/shared/pages/DubTab.jsx similarity index 100% rename from frontend/src/pages/DubTab.jsx rename to electron/src/shared/pages/DubTab.jsx diff --git a/frontend/src/pages/Launchpad.jsx b/electron/src/shared/pages/Launchpad.jsx similarity index 100% rename from frontend/src/pages/Launchpad.jsx rename to electron/src/shared/pages/Launchpad.jsx diff --git a/frontend/src/pages/ModelCatalogue.jsx b/electron/src/shared/pages/ModelCatalogue.jsx similarity index 100% rename from frontend/src/pages/ModelCatalogue.jsx rename to electron/src/shared/pages/ModelCatalogue.jsx diff --git a/frontend/src/pages/ModelCatalogue.test.jsx b/electron/src/shared/pages/ModelCatalogue.test.jsx similarity index 100% rename from frontend/src/pages/ModelCatalogue.test.jsx rename to electron/src/shared/pages/ModelCatalogue.test.jsx diff --git a/frontend/src/pages/Projects.jsx b/electron/src/shared/pages/Projects.jsx similarity index 100% rename from frontend/src/pages/Projects.jsx rename to electron/src/shared/pages/Projects.jsx diff --git a/frontend/src/pages/Settings.jsx b/electron/src/shared/pages/Settings.jsx similarity index 100% rename from frontend/src/pages/Settings.jsx rename to electron/src/shared/pages/Settings.jsx diff --git a/frontend/src/pages/SetupWizard.jsx b/electron/src/shared/pages/SetupWizard.jsx similarity index 100% rename from frontend/src/pages/SetupWizard.jsx rename to electron/src/shared/pages/SetupWizard.jsx diff --git a/frontend/src/pages/SupportPage.jsx b/electron/src/shared/pages/SupportPage.jsx similarity index 100% rename from frontend/src/pages/SupportPage.jsx rename to electron/src/shared/pages/SupportPage.jsx diff --git a/frontend/src/pages/ToolsPage.jsx b/electron/src/shared/pages/ToolsPage.jsx similarity index 100% rename from frontend/src/pages/ToolsPage.jsx rename to electron/src/shared/pages/ToolsPage.jsx diff --git a/frontend/src/pages/Transcriptions.jsx b/electron/src/shared/pages/Transcriptions.jsx similarity index 100% rename from frontend/src/pages/Transcriptions.jsx rename to electron/src/shared/pages/Transcriptions.jsx diff --git a/frontend/src/pages/Transcriptions.test.jsx b/electron/src/shared/pages/Transcriptions.test.jsx similarity index 100% rename from frontend/src/pages/Transcriptions.test.jsx rename to electron/src/shared/pages/Transcriptions.test.jsx diff --git a/frontend/src/pages/VoiceGallery.jsx b/electron/src/shared/pages/VoiceGallery.jsx similarity index 100% rename from frontend/src/pages/VoiceGallery.jsx rename to electron/src/shared/pages/VoiceGallery.jsx diff --git a/frontend/src/pages/VoiceProfile.jsx b/electron/src/shared/pages/VoiceProfile.jsx similarity index 100% rename from frontend/src/pages/VoiceProfile.jsx rename to electron/src/shared/pages/VoiceProfile.jsx diff --git a/frontend/src/store/dismissedNotifications.test.ts b/electron/src/shared/store/dismissedNotifications.test.ts similarity index 100% rename from frontend/src/store/dismissedNotifications.test.ts rename to electron/src/shared/store/dismissedNotifications.test.ts diff --git a/frontend/src/store/donationSlice.test.ts b/electron/src/shared/store/donationSlice.test.ts similarity index 100% rename from frontend/src/store/donationSlice.test.ts rename to electron/src/shared/store/donationSlice.test.ts diff --git a/frontend/src/store/donationSlice.ts b/electron/src/shared/store/donationSlice.ts similarity index 100% rename from frontend/src/store/donationSlice.ts rename to electron/src/shared/store/donationSlice.ts diff --git a/frontend/src/store/dubSlice.ts b/electron/src/shared/store/dubSlice.ts similarity index 100% rename from frontend/src/store/dubSlice.ts rename to electron/src/shared/store/dubSlice.ts diff --git a/frontend/src/store/gallerySlice.ts b/electron/src/shared/store/gallerySlice.ts similarity index 100% rename from frontend/src/store/gallerySlice.ts rename to electron/src/shared/store/gallerySlice.ts diff --git a/frontend/src/store/generateSlice.ts b/electron/src/shared/store/generateSlice.ts similarity index 100% rename from frontend/src/store/generateSlice.ts rename to electron/src/shared/store/generateSlice.ts diff --git a/frontend/src/store/glossarySlice.ts b/electron/src/shared/store/glossarySlice.ts similarity index 100% rename from frontend/src/store/glossarySlice.ts rename to electron/src/shared/store/glossarySlice.ts diff --git a/frontend/src/store/index.ts b/electron/src/shared/store/index.ts similarity index 100% rename from frontend/src/store/index.ts rename to electron/src/shared/store/index.ts diff --git a/frontend/src/store/longformMigration.test.ts b/electron/src/shared/store/longformMigration.test.ts similarity index 100% rename from frontend/src/store/longformMigration.test.ts rename to electron/src/shared/store/longformMigration.test.ts diff --git a/frontend/src/store/longformSlice.test.ts b/electron/src/shared/store/longformSlice.test.ts similarity index 100% rename from frontend/src/store/longformSlice.test.ts rename to electron/src/shared/store/longformSlice.test.ts diff --git a/frontend/src/store/longformSlice.ts b/electron/src/shared/store/longformSlice.ts similarity index 100% rename from frontend/src/store/longformSlice.ts rename to electron/src/shared/store/longformSlice.ts diff --git a/frontend/src/store/persistenceScheduling.test.ts b/electron/src/shared/store/persistenceScheduling.test.ts similarity index 100% rename from frontend/src/store/persistenceScheduling.test.ts rename to electron/src/shared/store/persistenceScheduling.test.ts diff --git a/frontend/src/store/pillSlice.ts b/electron/src/shared/store/pillSlice.ts similarity index 100% rename from frontend/src/store/pillSlice.ts rename to electron/src/shared/store/pillSlice.ts diff --git a/frontend/src/store/prefsSlice.ts b/electron/src/shared/store/prefsSlice.ts similarity index 100% rename from frontend/src/store/prefsSlice.ts rename to electron/src/shared/store/prefsSlice.ts diff --git a/frontend/src/store/releasesSlice.test.ts b/electron/src/shared/store/releasesSlice.test.ts similarity index 100% rename from frontend/src/store/releasesSlice.test.ts rename to electron/src/shared/store/releasesSlice.test.ts diff --git a/frontend/src/store/releasesSlice.ts b/electron/src/shared/store/releasesSlice.ts similarity index 100% rename from frontend/src/store/releasesSlice.ts rename to electron/src/shared/store/releasesSlice.ts diff --git a/frontend/src/store/store.test.js b/electron/src/shared/store/store.test.js similarity index 100% rename from frontend/src/store/store.test.js rename to electron/src/shared/store/store.test.js diff --git a/frontend/src/store/timingStrategyMigration.test.ts b/electron/src/shared/store/timingStrategyMigration.test.ts similarity index 100% rename from frontend/src/store/timingStrategyMigration.test.ts rename to electron/src/shared/store/timingStrategyMigration.test.ts diff --git a/frontend/src/store/uiScaleMigration.test.ts b/electron/src/shared/store/uiScaleMigration.test.ts similarity index 100% rename from frontend/src/store/uiScaleMigration.test.ts rename to electron/src/shared/store/uiScaleMigration.test.ts diff --git a/frontend/src/store/uiSlice.ts b/electron/src/shared/store/uiSlice.ts similarity index 100% rename from frontend/src/store/uiSlice.ts rename to electron/src/shared/store/uiSlice.ts diff --git a/frontend/src/store/updaterSlice.test.ts b/electron/src/shared/store/updaterSlice.test.ts similarity index 100% rename from frontend/src/store/updaterSlice.test.ts rename to electron/src/shared/store/updaterSlice.test.ts diff --git a/frontend/src/store/updaterSlice.ts b/electron/src/shared/store/updaterSlice.ts similarity index 100% rename from frontend/src/store/updaterSlice.ts rename to electron/src/shared/store/updaterSlice.ts diff --git a/frontend/src/test/AnalyticsConsentBanner.test.jsx b/electron/src/shared/test/AnalyticsConsentBanner.test.jsx similarity index 100% rename from frontend/src/test/AnalyticsConsentBanner.test.jsx rename to electron/src/shared/test/AnalyticsConsentBanner.test.jsx diff --git a/frontend/src/test/AppRemoteBackendGate.test.js b/electron/src/shared/test/AppRemoteBackendGate.test.js similarity index 100% rename from frontend/src/test/AppRemoteBackendGate.test.js rename to electron/src/shared/test/AppRemoteBackendGate.test.js diff --git a/frontend/src/test/AsrOpenAICompatPanel.test.jsx b/electron/src/shared/test/AsrOpenAICompatPanel.test.jsx similarity index 100% rename from frontend/src/test/AsrOpenAICompatPanel.test.jsx rename to electron/src/shared/test/AsrOpenAICompatPanel.test.jsx diff --git a/frontend/src/test/AudioTrimmerPreview.test.jsx b/electron/src/shared/test/AudioTrimmerPreview.test.jsx similarity index 100% rename from frontend/src/test/AudioTrimmerPreview.test.jsx rename to electron/src/shared/test/AudioTrimmerPreview.test.jsx diff --git a/frontend/src/test/AudiobookRecovery.test.jsx b/electron/src/shared/test/AudiobookRecovery.test.jsx similarity index 100% rename from frontend/src/test/AudiobookRecovery.test.jsx rename to electron/src/shared/test/AudiobookRecovery.test.jsx diff --git a/frontend/src/test/AudiobookStopCancel.test.jsx b/electron/src/shared/test/AudiobookStopCancel.test.jsx similarity index 100% rename from frontend/src/test/AudiobookStopCancel.test.jsx rename to electron/src/shared/test/AudiobookStopCancel.test.jsx diff --git a/frontend/src/test/AudiobookTabLayout.test.jsx b/electron/src/shared/test/AudiobookTabLayout.test.jsx similarity index 100% rename from frontend/src/test/AudiobookTabLayout.test.jsx rename to electron/src/shared/test/AudiobookTabLayout.test.jsx diff --git a/frontend/src/test/BackendCrashNotice.browser.test.jsx b/electron/src/shared/test/BackendCrashNotice.browser.test.jsx similarity index 100% rename from frontend/src/test/BackendCrashNotice.browser.test.jsx rename to electron/src/shared/test/BackendCrashNotice.browser.test.jsx diff --git a/frontend/src/test/BootstrapSplashAwaitingSetupStall.test.jsx b/electron/src/shared/test/BootstrapSplashAwaitingSetupStall.test.jsx similarity index 100% rename from frontend/src/test/BootstrapSplashAwaitingSetupStall.test.jsx rename to electron/src/shared/test/BootstrapSplashAwaitingSetupStall.test.jsx diff --git a/frontend/src/test/BootstrapSplashFailedRecovery.test.jsx b/electron/src/shared/test/BootstrapSplashFailedRecovery.test.jsx similarity index 100% rename from frontend/src/test/BootstrapSplashFailedRecovery.test.jsx rename to electron/src/shared/test/BootstrapSplashFailedRecovery.test.jsx diff --git a/frontend/src/test/BootstrapSplashFailedRender.test.jsx b/electron/src/shared/test/BootstrapSplashFailedRender.test.jsx similarity index 100% rename from frontend/src/test/BootstrapSplashFailedRender.test.jsx rename to electron/src/shared/test/BootstrapSplashFailedRender.test.jsx diff --git a/frontend/src/test/BootstrapSplashLogRetention.test.jsx b/electron/src/shared/test/BootstrapSplashLogRetention.test.jsx similarity index 100% rename from frontend/src/test/BootstrapSplashLogRetention.test.jsx rename to electron/src/shared/test/BootstrapSplashLogRetention.test.jsx diff --git a/frontend/src/test/BootstrapSplashObservedStages.test.jsx b/electron/src/shared/test/BootstrapSplashObservedStages.test.jsx similarity index 100% rename from frontend/src/test/BootstrapSplashObservedStages.test.jsx rename to electron/src/shared/test/BootstrapSplashObservedStages.test.jsx diff --git a/frontend/src/test/BootstrapSplashRecovery.test.jsx b/electron/src/shared/test/BootstrapSplashRecovery.test.jsx similarity index 100% rename from frontend/src/test/BootstrapSplashRecovery.test.jsx rename to electron/src/shared/test/BootstrapSplashRecovery.test.jsx diff --git a/frontend/src/test/BootstrapSplashSlowBackendStall.test.jsx b/electron/src/shared/test/BootstrapSplashSlowBackendStall.test.jsx similarity index 100% rename from frontend/src/test/BootstrapSplashSlowBackendStall.test.jsx rename to electron/src/shared/test/BootstrapSplashSlowBackendStall.test.jsx diff --git a/frontend/src/test/CaptureWidgetMicPreflight.test.jsx b/electron/src/shared/test/CaptureWidgetMicPreflight.test.jsx similarity index 100% rename from frontend/src/test/CaptureWidgetMicPreflight.test.jsx rename to electron/src/shared/test/CaptureWidgetMicPreflight.test.jsx diff --git a/frontend/src/test/CaptureWidgetPillVisible.test.jsx b/electron/src/shared/test/CaptureWidgetPillVisible.test.jsx similarity index 100% rename from frontend/src/test/CaptureWidgetPillVisible.test.jsx rename to electron/src/shared/test/CaptureWidgetPillVisible.test.jsx diff --git a/frontend/src/test/CaptureWidgetSetupRace.test.jsx b/electron/src/shared/test/CaptureWidgetSetupRace.test.jsx similarity index 100% rename from frontend/src/test/CaptureWidgetSetupRace.test.jsx rename to electron/src/shared/test/CaptureWidgetSetupRace.test.jsx diff --git a/frontend/src/test/CaptureWidgetStrandedPill.test.jsx b/electron/src/shared/test/CaptureWidgetStrandedPill.test.jsx similarity index 100% rename from frontend/src/test/CaptureWidgetStrandedPill.test.jsx rename to electron/src/shared/test/CaptureWidgetStrandedPill.test.jsx diff --git a/frontend/src/test/ContactPage.test.jsx b/electron/src/shared/test/ContactPage.test.jsx similarity index 100% rename from frontend/src/test/ContactPage.test.jsx rename to electron/src/shared/test/ContactPage.test.jsx diff --git a/frontend/src/test/DemoPresetGrid.test.jsx b/electron/src/shared/test/DemoPresetGrid.test.jsx similarity index 100% rename from frontend/src/test/DemoPresetGrid.test.jsx rename to electron/src/shared/test/DemoPresetGrid.test.jsx diff --git a/frontend/src/test/DictationDemo.test.jsx b/electron/src/shared/test/DictationDemo.test.jsx similarity index 100% rename from frontend/src/test/DictationDemo.test.jsx rename to electron/src/shared/test/DictationDemo.test.jsx diff --git a/frontend/src/test/DictationNoPillWindow.test.jsx b/electron/src/shared/test/DictationNoPillWindow.test.jsx similarity index 100% rename from frontend/src/test/DictationNoPillWindow.test.jsx rename to electron/src/shared/test/DictationNoPillWindow.test.jsx diff --git a/frontend/src/test/DubErrorBanner.test.jsx b/electron/src/shared/test/DubErrorBanner.test.jsx similarity index 100% rename from frontend/src/test/DubErrorBanner.test.jsx rename to electron/src/shared/test/DubErrorBanner.test.jsx diff --git a/frontend/src/test/DubHeaderActions.test.jsx b/electron/src/shared/test/DubHeaderActions.test.jsx similarity index 100% rename from frontend/src/test/DubHeaderActions.test.jsx rename to electron/src/shared/test/DubHeaderActions.test.jsx diff --git a/frontend/src/test/DubIdleSkeleton.test.jsx b/electron/src/shared/test/DubIdleSkeleton.test.jsx similarity index 100% rename from frontend/src/test/DubIdleSkeleton.test.jsx rename to electron/src/shared/test/DubIdleSkeleton.test.jsx diff --git a/frontend/src/test/DubSegmentRowPlanBadge.test.jsx b/electron/src/shared/test/DubSegmentRowPlanBadge.test.jsx similarity index 100% rename from frontend/src/test/DubSegmentRowPlanBadge.test.jsx rename to electron/src/shared/test/DubSegmentRowPlanBadge.test.jsx diff --git a/frontend/src/test/DubSegmentRowTiming.test.jsx b/electron/src/shared/test/DubSegmentRowTiming.test.jsx similarity index 100% rename from frontend/src/test/DubSegmentRowTiming.test.jsx rename to electron/src/shared/test/DubSegmentRowTiming.test.jsx diff --git a/frontend/src/test/DubSegmentRowVoicePicker.test.jsx b/electron/src/shared/test/DubSegmentRowVoicePicker.test.jsx similarity index 100% rename from frontend/src/test/DubSegmentRowVoicePicker.test.jsx rename to electron/src/shared/test/DubSegmentRowVoicePicker.test.jsx diff --git a/frontend/src/test/DubSegmentTableMerge.test.jsx b/electron/src/shared/test/DubSegmentTableMerge.test.jsx similarity index 100% rename from frontend/src/test/DubSegmentTableMerge.test.jsx rename to electron/src/shared/test/DubSegmentTableMerge.test.jsx diff --git a/frontend/src/test/DubTrackPillTooltip.test.jsx b/electron/src/shared/test/DubTrackPillTooltip.test.jsx similarity index 100% rename from frontend/src/test/DubTrackPillTooltip.test.jsx rename to electron/src/shared/test/DubTrackPillTooltip.test.jsx diff --git a/frontend/src/test/DubTrackTabsRestore.test.jsx b/electron/src/shared/test/DubTrackTabsRestore.test.jsx similarity index 100% rename from frontend/src/test/DubTrackTabsRestore.test.jsx rename to electron/src/shared/test/DubTrackTabsRestore.test.jsx diff --git a/frontend/src/test/DubTranslateEngineInstall.test.jsx b/electron/src/shared/test/DubTranslateEngineInstall.test.jsx similarity index 100% rename from frontend/src/test/DubTranslateEngineInstall.test.jsx rename to electron/src/shared/test/DubTranslateEngineInstall.test.jsx diff --git a/frontend/src/test/DubTranslationQualityToggles.test.jsx b/electron/src/shared/test/DubTranslationQualityToggles.test.jsx similarity index 100% rename from frontend/src/test/DubTranslationQualityToggles.test.jsx rename to electron/src/shared/test/DubTranslationQualityToggles.test.jsx diff --git a/frontend/src/test/DubbingDemo.test.jsx b/electron/src/shared/test/DubbingDemo.test.jsx similarity index 100% rename from frontend/src/test/DubbingDemo.test.jsx rename to electron/src/shared/test/DubbingDemo.test.jsx diff --git a/frontend/src/test/EngineCompatibilityMatrix.test.jsx b/electron/src/shared/test/EngineCompatibilityMatrix.test.jsx similarity index 100% rename from frontend/src/test/EngineCompatibilityMatrix.test.jsx rename to electron/src/shared/test/EngineCompatibilityMatrix.test.jsx diff --git a/frontend/src/test/EngineDocsLink.test.jsx b/electron/src/shared/test/EngineDocsLink.test.jsx similarity index 98% rename from frontend/src/test/EngineDocsLink.test.jsx rename to electron/src/shared/test/EngineDocsLink.test.jsx index 517d6a5cb..5e2948553 100644 --- a/frontend/src/test/EngineDocsLink.test.jsx +++ b/electron/src/shared/test/EngineDocsLink.test.jsx @@ -11,7 +11,7 @@ * * `docs/engines/.md` is what actually explains it — accurate, and in * cosyvoice's case CI-guarded against the installer registry — and nothing in - * `frontend/src` referenced `docs/engines` at all. The backend now carries a + * `electron/src/shared` referenced `docs/engines` at all. The backend now carries a * registry-authored `docs_url` that the scrub leaves alone, and the row renders * it with the same "Learn more →" affordance the MCP and Remote GPU panels use. */ diff --git a/frontend/src/test/FirstRunSetupPortableDir.test.jsx b/electron/src/shared/test/FirstRunSetupPortableDir.test.jsx similarity index 100% rename from frontend/src/test/FirstRunSetupPortableDir.test.jsx rename to electron/src/shared/test/FirstRunSetupPortableDir.test.jsx diff --git a/frontend/src/test/GlobalAudioPlayer.test.jsx b/electron/src/shared/test/GlobalAudioPlayer.test.jsx similarity index 100% rename from frontend/src/test/GlobalAudioPlayer.test.jsx rename to electron/src/shared/test/GlobalAudioPlayer.test.jsx diff --git a/frontend/src/test/GoalBar.test.jsx b/electron/src/shared/test/GoalBar.test.jsx similarity index 100% rename from frontend/src/test/GoalBar.test.jsx rename to electron/src/shared/test/GoalBar.test.jsx diff --git a/frontend/src/test/HeaderMacTrafficLightInset.test.jsx b/electron/src/shared/test/HeaderMacTrafficLightInset.test.jsx similarity index 100% rename from frontend/src/test/HeaderMacTrafficLightInset.test.jsx rename to electron/src/shared/test/HeaderMacTrafficLightInset.test.jsx diff --git a/frontend/src/test/HeaderNavStyle.test.jsx b/electron/src/shared/test/HeaderNavStyle.test.jsx similarity index 100% rename from frontend/src/test/HeaderNavStyle.test.jsx rename to electron/src/shared/test/HeaderNavStyle.test.jsx diff --git a/frontend/src/test/HeaderStatusDotReducedMotion.test.jsx b/electron/src/shared/test/HeaderStatusDotReducedMotion.test.jsx similarity index 100% rename from frontend/src/test/HeaderStatusDotReducedMotion.test.jsx rename to electron/src/shared/test/HeaderStatusDotReducedMotion.test.jsx diff --git a/frontend/src/test/HeaderWaveBars.test.jsx b/electron/src/shared/test/HeaderWaveBars.test.jsx similarity index 100% rename from frontend/src/test/HeaderWaveBars.test.jsx rename to electron/src/shared/test/HeaderWaveBars.test.jsx diff --git a/frontend/src/test/LanguageSwitchPrompt.test.jsx b/electron/src/shared/test/LanguageSwitchPrompt.test.jsx similarity index 100% rename from frontend/src/test/LanguageSwitchPrompt.test.jsx rename to electron/src/shared/test/LanguageSwitchPrompt.test.jsx diff --git a/frontend/src/test/LaunchpadDeck.test.jsx b/electron/src/shared/test/LaunchpadDeck.test.jsx similarity index 100% rename from frontend/src/test/LaunchpadDeck.test.jsx rename to electron/src/shared/test/LaunchpadDeck.test.jsx diff --git a/frontend/src/test/LaunchpadScrollShrink.test.jsx b/electron/src/shared/test/LaunchpadScrollShrink.test.jsx similarity index 100% rename from frontend/src/test/LaunchpadScrollShrink.test.jsx rename to electron/src/shared/test/LaunchpadScrollShrink.test.jsx diff --git a/frontend/src/test/LogsFooterAllClear.test.jsx b/electron/src/shared/test/LogsFooterAllClear.test.jsx similarity index 100% rename from frontend/src/test/LogsFooterAllClear.test.jsx rename to electron/src/shared/test/LogsFooterAllClear.test.jsx diff --git a/frontend/src/test/LogsFooterClearFailure.test.jsx b/electron/src/shared/test/LogsFooterClearFailure.test.jsx similarity index 100% rename from frontend/src/test/LogsFooterClearFailure.test.jsx rename to electron/src/shared/test/LogsFooterClearFailure.test.jsx diff --git a/frontend/src/test/LogsFooterDonatePopover.test.jsx b/electron/src/shared/test/LogsFooterDonatePopover.test.jsx similarity index 100% rename from frontend/src/test/LogsFooterDonatePopover.test.jsx rename to electron/src/shared/test/LogsFooterDonatePopover.test.jsx diff --git a/frontend/src/test/LogsFooterNotifications.test.jsx b/electron/src/shared/test/LogsFooterNotifications.test.jsx similarity index 100% rename from frontend/src/test/LogsFooterNotifications.test.jsx rename to electron/src/shared/test/LogsFooterNotifications.test.jsx diff --git a/frontend/src/test/NavStyleTitlebarTabs.test.jsx b/electron/src/shared/test/NavStyleTitlebarTabs.test.jsx similarity index 100% rename from frontend/src/test/NavStyleTitlebarTabs.test.jsx rename to electron/src/shared/test/NavStyleTitlebarTabs.test.jsx diff --git a/frontend/src/test/PermissionChecks.test.jsx b/electron/src/shared/test/PermissionChecks.test.jsx similarity index 100% rename from frontend/src/test/PermissionChecks.test.jsx rename to electron/src/shared/test/PermissionChecks.test.jsx diff --git a/frontend/src/test/PermissionsPanel.test.jsx b/electron/src/shared/test/PermissionsPanel.test.jsx similarity index 100% rename from frontend/src/test/PermissionsPanel.test.jsx rename to electron/src/shared/test/PermissionsPanel.test.jsx diff --git a/frontend/src/test/ProjectsAudiobookPlayback.test.jsx b/electron/src/shared/test/ProjectsAudiobookPlayback.test.jsx similarity index 100% rename from frontend/src/test/ProjectsAudiobookPlayback.test.jsx rename to electron/src/shared/test/ProjectsAudiobookPlayback.test.jsx diff --git a/frontend/src/test/ProjectsRelativeTime.test.jsx b/electron/src/shared/test/ProjectsRelativeTime.test.jsx similarity index 100% rename from frontend/src/test/ProjectsRelativeTime.test.jsx rename to electron/src/shared/test/ProjectsRelativeTime.test.jsx diff --git a/frontend/src/test/PronunciationPanel.test.jsx b/electron/src/shared/test/PronunciationPanel.test.jsx similarity index 100% rename from frontend/src/test/PronunciationPanel.test.jsx rename to electron/src/shared/test/PronunciationPanel.test.jsx diff --git a/frontend/src/test/ReadinessChecklist.test.jsx b/electron/src/shared/test/ReadinessChecklist.test.jsx similarity index 100% rename from frontend/src/test/ReadinessChecklist.test.jsx rename to electron/src/shared/test/ReadinessChecklist.test.jsx diff --git a/frontend/src/test/RefinementPanel.test.jsx b/electron/src/shared/test/RefinementPanel.test.jsx similarity index 100% rename from frontend/src/test/RefinementPanel.test.jsx rename to electron/src/shared/test/RefinementPanel.test.jsx diff --git a/frontend/src/test/SetupWizardChrome.test.jsx b/electron/src/shared/test/SetupWizardChrome.test.jsx similarity index 100% rename from frontend/src/test/SetupWizardChrome.test.jsx rename to electron/src/shared/test/SetupWizardChrome.test.jsx diff --git a/frontend/src/test/SetupWizardConsent.test.jsx b/electron/src/shared/test/SetupWizardConsent.test.jsx similarity index 100% rename from frontend/src/test/SetupWizardConsent.test.jsx rename to electron/src/shared/test/SetupWizardConsent.test.jsx diff --git a/frontend/src/test/SetupWizardDictation.test.jsx b/electron/src/shared/test/SetupWizardDictation.test.jsx similarity index 100% rename from frontend/src/test/SetupWizardDictation.test.jsx rename to electron/src/shared/test/SetupWizardDictation.test.jsx diff --git a/frontend/src/test/StoriesEditorClearScript.test.jsx b/electron/src/shared/test/StoriesEditorClearScript.test.jsx similarity index 100% rename from frontend/src/test/StoriesEditorClearScript.test.jsx rename to electron/src/shared/test/StoriesEditorClearScript.test.jsx diff --git a/frontend/src/test/StoriesEditorImportEncoding.test.jsx b/electron/src/shared/test/StoriesEditorImportEncoding.test.jsx similarity index 100% rename from frontend/src/test/StoriesEditorImportEncoding.test.jsx rename to electron/src/shared/test/StoriesEditorImportEncoding.test.jsx diff --git a/frontend/src/test/StoriesEditorVoicePicker.test.jsx b/electron/src/shared/test/StoriesEditorVoicePicker.test.jsx similarity index 100% rename from frontend/src/test/StoriesEditorVoicePicker.test.jsx rename to electron/src/shared/test/StoriesEditorVoicePicker.test.jsx diff --git a/frontend/src/test/SupportPageSections.test.jsx b/electron/src/shared/test/SupportPageSections.test.jsx similarity index 100% rename from frontend/src/test/SupportPageSections.test.jsx rename to electron/src/shared/test/SupportPageSections.test.jsx diff --git a/frontend/src/test/SupportPageSponsors.test.jsx b/electron/src/shared/test/SupportPageSponsors.test.jsx similarity index 100% rename from frontend/src/test/SupportPageSponsors.test.jsx rename to electron/src/shared/test/SupportPageSponsors.test.jsx diff --git a/frontend/src/test/TranscribeOverlayEta.test.jsx b/electron/src/shared/test/TranscribeOverlayEta.test.jsx similarity index 100% rename from frontend/src/test/TranscribeOverlayEta.test.jsx rename to electron/src/shared/test/TranscribeOverlayEta.test.jsx diff --git a/frontend/src/test/TranscriptionPicker.test.jsx b/electron/src/shared/test/TranscriptionPicker.test.jsx similarity index 100% rename from frontend/src/test/TranscriptionPicker.test.jsx rename to electron/src/shared/test/TranscriptionPicker.test.jsx diff --git a/frontend/src/test/UpdateToast.test.jsx b/electron/src/shared/test/UpdateToast.test.jsx similarity index 100% rename from frontend/src/test/UpdateToast.test.jsx rename to electron/src/shared/test/UpdateToast.test.jsx diff --git a/frontend/src/test/VoiceGalleryActions.test.jsx b/electron/src/shared/test/VoiceGalleryActions.test.jsx similarity index 100% rename from frontend/src/test/VoiceGalleryActions.test.jsx rename to electron/src/shared/test/VoiceGalleryActions.test.jsx diff --git a/frontend/src/test/VoiceGalleryPreviewFallback.test.jsx b/electron/src/shared/test/VoiceGalleryPreviewFallback.test.jsx similarity index 100% rename from frontend/src/test/VoiceGalleryPreviewFallback.test.jsx rename to electron/src/shared/test/VoiceGalleryPreviewFallback.test.jsx diff --git a/frontend/src/test/VoicePanel.test.jsx b/electron/src/shared/test/VoicePanel.test.jsx similarity index 100% rename from frontend/src/test/VoicePanel.test.jsx rename to electron/src/shared/test/VoicePanel.test.jsx diff --git a/frontend/src/test/VoiceSelector.test.jsx b/electron/src/shared/test/VoiceSelector.test.jsx similarity index 100% rename from frontend/src/test/VoiceSelector.test.jsx rename to electron/src/shared/test/VoiceSelector.test.jsx diff --git a/frontend/src/test/WorkspaceHistoryClear.test.jsx b/electron/src/shared/test/WorkspaceHistoryClear.test.jsx similarity index 100% rename from frontend/src/test/WorkspaceHistoryClear.test.jsx rename to electron/src/shared/test/WorkspaceHistoryClear.test.jsx diff --git a/frontend/src/test/aecFarEndBus.test.js b/electron/src/shared/test/aecFarEndBus.test.js similarity index 100% rename from frontend/src/test/aecFarEndBus.test.js rename to electron/src/shared/test/aecFarEndBus.test.js diff --git a/frontend/src/test/aecPcm.test.js b/electron/src/shared/test/aecPcm.test.js similarity index 100% rename from frontend/src/test/aecPcm.test.js rename to electron/src/shared/test/aecPcm.test.js diff --git a/frontend/src/test/analyticsConsentRace.test.ts b/electron/src/shared/test/analyticsConsentRace.test.ts similarity index 100% rename from frontend/src/test/analyticsConsentRace.test.ts rename to electron/src/shared/test/analyticsConsentRace.test.ts diff --git a/frontend/src/test/analyticsFrontend.test.ts b/electron/src/shared/test/analyticsFrontend.test.ts similarity index 100% rename from frontend/src/test/analyticsFrontend.test.ts rename to electron/src/shared/test/analyticsFrontend.test.ts diff --git a/frontend/src/test/apiErrorClass.test.js b/electron/src/shared/test/apiErrorClass.test.js similarity index 100% rename from frontend/src/test/apiErrorClass.test.js rename to electron/src/shared/test/apiErrorClass.test.js diff --git a/frontend/src/test/appBusy.test.js b/electron/src/shared/test/appBusy.test.js similarity index 100% rename from frontend/src/test/appBusy.test.js rename to electron/src/shared/test/appBusy.test.js diff --git a/frontend/src/test/appShellScale.test.js b/electron/src/shared/test/appShellScale.test.js similarity index 100% rename from frontend/src/test/appShellScale.test.js rename to electron/src/shared/test/appShellScale.test.js diff --git a/frontend/src/test/asrModelMissing.test.jsx b/electron/src/shared/test/asrModelMissing.test.jsx similarity index 100% rename from frontend/src/test/asrModelMissing.test.jsx rename to electron/src/shared/test/asrModelMissing.test.jsx diff --git a/frontend/src/test/audioTrimSelectionPlayhead.test.js b/electron/src/shared/test/audioTrimSelectionPlayhead.test.js similarity index 100% rename from frontend/src/test/audioTrimSelectionPlayhead.test.js rename to electron/src/shared/test/audioTrimSelectionPlayhead.test.js diff --git a/frontend/src/test/audiobookCastMarkup.test.jsx b/electron/src/shared/test/audiobookCastMarkup.test.jsx similarity index 100% rename from frontend/src/test/audiobookCastMarkup.test.jsx rename to electron/src/shared/test/audiobookCastMarkup.test.jsx diff --git a/frontend/src/test/audiobookHero.test.jsx b/electron/src/shared/test/audiobookHero.test.jsx similarity index 100% rename from frontend/src/test/audiobookHero.test.jsx rename to electron/src/shared/test/audiobookHero.test.jsx diff --git a/frontend/src/test/audiobookOverrides.test.jsx b/electron/src/shared/test/audiobookOverrides.test.jsx similarity index 100% rename from frontend/src/test/audiobookOverrides.test.jsx rename to electron/src/shared/test/audiobookOverrides.test.jsx diff --git a/frontend/src/test/audiobookScript.test.js b/electron/src/shared/test/audiobookScript.test.js similarity index 100% rename from frontend/src/test/audiobookScript.test.js rename to electron/src/shared/test/audiobookScript.test.js diff --git a/frontend/src/test/backendContact.test.ts b/electron/src/shared/test/backendContact.test.ts similarity index 100% rename from frontend/src/test/backendContact.test.ts rename to electron/src/shared/test/backendContact.test.ts diff --git a/frontend/src/test/backendCrash.http.test.ts b/electron/src/shared/test/backendCrash.http.test.ts similarity index 100% rename from frontend/src/test/backendCrash.http.test.ts rename to electron/src/shared/test/backendCrash.http.test.ts diff --git a/frontend/src/test/bidiStartTruncation.test.jsx b/electron/src/shared/test/bidiStartTruncation.test.jsx similarity index 100% rename from frontend/src/test/bidiStartTruncation.test.jsx rename to electron/src/shared/test/bidiStartTruncation.test.jsx diff --git a/frontend/src/test/captureSherpaFinal.test.js b/electron/src/shared/test/captureSherpaFinal.test.js similarity index 100% rename from frontend/src/test/captureSherpaFinal.test.js rename to electron/src/shared/test/captureSherpaFinal.test.js diff --git a/frontend/src/test/client.crash.test.ts b/electron/src/shared/test/client.crash.test.ts similarity index 100% rename from frontend/src/test/client.crash.test.ts rename to electron/src/shared/test/client.crash.test.ts diff --git a/frontend/src/test/client.crashRace.test.ts b/electron/src/shared/test/client.crashRace.test.ts similarity index 100% rename from frontend/src/test/client.crashRace.test.ts rename to electron/src/shared/test/client.crashRace.test.ts diff --git a/frontend/src/test/client.restart.test.ts b/electron/src/shared/test/client.restart.test.ts similarity index 100% rename from frontend/src/test/client.restart.test.ts rename to electron/src/shared/test/client.restart.test.ts diff --git a/frontend/src/test/client.retry.test.ts b/electron/src/shared/test/client.retry.test.ts similarity index 100% rename from frontend/src/test/client.retry.test.ts rename to electron/src/shared/test/client.retry.test.ts diff --git a/frontend/src/test/client.startFailure.test.ts b/electron/src/shared/test/client.startFailure.test.ts similarity index 100% rename from frontend/src/test/client.startFailure.test.ts rename to electron/src/shared/test/client.startFailure.test.ts diff --git a/frontend/src/test/client.unreachable.test.ts b/electron/src/shared/test/client.unreachable.test.ts similarity index 100% rename from frontend/src/test/client.unreachable.test.ts rename to electron/src/shared/test/client.unreachable.test.ts diff --git a/frontend/src/test/cssTokens.test.js b/electron/src/shared/test/cssTokens.test.js similarity index 100% rename from frontend/src/test/cssTokens.test.js rename to electron/src/shared/test/cssTokens.test.js diff --git a/frontend/src/test/desktopWindowConfig.test.js b/electron/src/shared/test/desktopWindowConfig.test.js similarity index 100% rename from frontend/src/test/desktopWindowConfig.test.js rename to electron/src/shared/test/desktopWindowConfig.test.js diff --git a/frontend/src/test/dialogAliasConfig.test.js b/electron/src/shared/test/dialogAliasConfig.test.js similarity index 100% rename from frontend/src/test/dialogAliasConfig.test.js rename to electron/src/shared/test/dialogAliasConfig.test.js diff --git a/frontend/src/test/dictationPrefs.test.ts b/electron/src/shared/test/dictationPrefs.test.ts similarity index 100% rename from frontend/src/test/dictationPrefs.test.ts rename to electron/src/shared/test/dictationPrefs.test.ts diff --git a/frontend/src/test/droppedChunkNotice.test.js b/electron/src/shared/test/droppedChunkNotice.test.js similarity index 100% rename from frontend/src/test/droppedChunkNotice.test.js rename to electron/src/shared/test/droppedChunkNotice.test.js diff --git a/frontend/src/test/dubAsrInstallRecovery.test.jsx b/electron/src/shared/test/dubAsrInstallRecovery.test.jsx similarity index 100% rename from frontend/src/test/dubAsrInstallRecovery.test.jsx rename to electron/src/shared/test/dubAsrInstallRecovery.test.jsx diff --git a/frontend/src/test/dubExpiredJobError.test.js b/electron/src/shared/test/dubExpiredJobError.test.js similarity index 100% rename from frontend/src/test/dubExpiredJobError.test.js rename to electron/src/shared/test/dubExpiredJobError.test.js diff --git a/frontend/src/test/dubLivePreview.test.jsx b/electron/src/shared/test/dubLivePreview.test.jsx similarity index 100% rename from frontend/src/test/dubLivePreview.test.jsx rename to electron/src/shared/test/dubLivePreview.test.jsx diff --git a/frontend/src/test/dubLocalePlural.test.js b/electron/src/shared/test/dubLocalePlural.test.js similarity index 100% rename from frontend/src/test/dubLocalePlural.test.js rename to electron/src/shared/test/dubLocalePlural.test.js diff --git a/frontend/src/test/dubMultiLangGenerate.test.jsx b/electron/src/shared/test/dubMultiLangGenerate.test.jsx similarity index 100% rename from frontend/src/test/dubMultiLangGenerate.test.jsx rename to electron/src/shared/test/dubMultiLangGenerate.test.jsx diff --git a/frontend/src/test/dubMultiLangPersist.test.js b/electron/src/shared/test/dubMultiLangPersist.test.js similarity index 100% rename from frontend/src/test/dubMultiLangPersist.test.js rename to electron/src/shared/test/dubMultiLangPersist.test.js diff --git a/frontend/src/test/dubMultiLangWorkflow.integration.test.jsx b/electron/src/shared/test/dubMultiLangWorkflow.integration.test.jsx similarity index 100% rename from frontend/src/test/dubMultiLangWorkflow.integration.test.jsx rename to electron/src/shared/test/dubMultiLangWorkflow.integration.test.jsx diff --git a/frontend/src/test/dubPasteTranslation.test.jsx b/electron/src/shared/test/dubPasteTranslation.test.jsx similarity index 100% rename from frontend/src/test/dubPasteTranslation.test.jsx rename to electron/src/shared/test/dubPasteTranslation.test.jsx diff --git a/frontend/src/test/dubPerLangTranslations.test.jsx b/electron/src/shared/test/dubPerLangTranslations.test.jsx similarity index 100% rename from frontend/src/test/dubPerLangTranslations.test.jsx rename to electron/src/shared/test/dubPerLangTranslations.test.jsx diff --git a/frontend/src/test/dubPreviewTabTranscriptSync.test.jsx b/electron/src/shared/test/dubPreviewTabTranscriptSync.test.jsx similarity index 100% rename from frontend/src/test/dubPreviewTabTranscriptSync.test.jsx rename to electron/src/shared/test/dubPreviewTabTranscriptSync.test.jsx diff --git a/frontend/src/test/dubQueuedSrtImport.test.js b/electron/src/shared/test/dubQueuedSrtImport.test.js similarity index 100% rename from frontend/src/test/dubQueuedSrtImport.test.js rename to electron/src/shared/test/dubQueuedSrtImport.test.js diff --git a/frontend/src/test/dubResponsiveLayout.test.js b/electron/src/shared/test/dubResponsiveLayout.test.js similarity index 100% rename from frontend/src/test/dubResponsiveLayout.test.js rename to electron/src/shared/test/dubResponsiveLayout.test.js diff --git a/frontend/src/test/dubSegmentAttribution.test.jsx b/electron/src/shared/test/dubSegmentAttribution.test.jsx similarity index 100% rename from frontend/src/test/dubSegmentAttribution.test.jsx rename to electron/src/shared/test/dubSegmentAttribution.test.jsx diff --git a/frontend/src/test/dubStepRestoreClamp.test.js b/electron/src/shared/test/dubStepRestoreClamp.test.js similarity index 100% rename from frontend/src/test/dubStepRestoreClamp.test.js rename to electron/src/shared/test/dubStepRestoreClamp.test.js diff --git a/frontend/src/test/dubTranslateAllOverride.test.jsx b/electron/src/shared/test/dubTranslateAllOverride.test.jsx similarity index 100% rename from frontend/src/test/dubTranslateAllOverride.test.jsx rename to electron/src/shared/test/dubTranslateAllOverride.test.jsx diff --git a/frontend/src/test/dubVoiceMatchRequest.test.jsx b/electron/src/shared/test/dubVoiceMatchRequest.test.jsx similarity index 100% rename from frontend/src/test/dubVoiceMatchRequest.test.jsx rename to electron/src/shared/test/dubVoiceMatchRequest.test.jsx diff --git a/frontend/src/test/encodedText.js b/electron/src/shared/test/encodedText.js similarity index 100% rename from frontend/src/test/encodedText.js rename to electron/src/shared/test/encodedText.js diff --git a/frontend/src/test/engineSelectToast.test.js b/electron/src/shared/test/engineSelectToast.test.js similarity index 100% rename from frontend/src/test/engineSelectToast.test.js rename to electron/src/shared/test/engineSelectToast.test.js diff --git a/frontend/src/test/errorToastUserFixable.test.jsx b/electron/src/shared/test/errorToastUserFixable.test.jsx similarity index 100% rename from frontend/src/test/errorToastUserFixable.test.jsx rename to electron/src/shared/test/errorToastUserFixable.test.jsx diff --git a/frontend/src/test/featureCoverage.test.js b/electron/src/shared/test/featureCoverage.test.js similarity index 98% rename from frontend/src/test/featureCoverage.test.js rename to electron/src/shared/test/featureCoverage.test.js index 1f67225e5..2cbd13b84 100644 --- a/frontend/src/test/featureCoverage.test.js +++ b/electron/src/shared/test/featureCoverage.test.js @@ -16,7 +16,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; const _dir = path.dirname(fileURLToPath(import.meta.url)); -const SRC = path.resolve(_dir, '..'); // frontend/src +const SRC = path.resolve(_dir, '..'); // electron/src/shared const read = (p) => fs.readFileSync(path.join(SRC, p), 'utf8'); // Legacy/alias modes intentionally kept in the union but routed elsewhere diff --git a/frontend/src/test/firstSoundInstruct.test.js b/electron/src/shared/test/firstSoundInstruct.test.js similarity index 100% rename from frontend/src/test/firstSoundInstruct.test.js rename to electron/src/shared/test/firstSoundInstruct.test.js diff --git a/frontend/src/test/galleryErrorMessages.test.js b/electron/src/shared/test/galleryErrorMessages.test.js similarity index 100% rename from frontend/src/test/galleryErrorMessages.test.js rename to electron/src/shared/test/galleryErrorMessages.test.js diff --git a/frontend/src/test/generatePreflight.test.js b/electron/src/shared/test/generatePreflight.test.js similarity index 100% rename from frontend/src/test/generatePreflight.test.js rename to electron/src/shared/test/generatePreflight.test.js diff --git a/frontend/src/test/i18nDirection.test.js b/electron/src/shared/test/i18nDirection.test.js similarity index 100% rename from frontend/src/test/i18nDirection.test.js rename to electron/src/shared/test/i18nDirection.test.js diff --git a/frontend/src/test/initialLoadRetry.test.js b/electron/src/shared/test/initialLoadRetry.test.js similarity index 100% rename from frontend/src/test/initialLoadRetry.test.js rename to electron/src/shared/test/initialLoadRetry.test.js diff --git a/frontend/src/test/logsFooterInFlow.test.js b/electron/src/shared/test/logsFooterInFlow.test.js similarity index 100% rename from frontend/src/test/logsFooterInFlow.test.js rename to electron/src/shared/test/logsFooterInFlow.test.js diff --git a/frontend/src/test/longformParser.test.js b/electron/src/shared/test/longformParser.test.js similarity index 100% rename from frontend/src/test/longformParser.test.js rename to electron/src/shared/test/longformParser.test.js diff --git a/frontend/src/test/longformStream.test.js b/electron/src/shared/test/longformStream.test.js similarity index 100% rename from frontend/src/test/longformStream.test.js rename to electron/src/shared/test/longformStream.test.js diff --git a/frontend/src/test/modelNotDownloaded.test.jsx b/electron/src/shared/test/modelNotDownloaded.test.jsx similarity index 100% rename from frontend/src/test/modelNotDownloaded.test.jsx rename to electron/src/shared/test/modelNotDownloaded.test.jsx diff --git a/frontend/src/test/modelStoreGrouping.test.jsx b/electron/src/shared/test/modelStoreGrouping.test.jsx similarity index 100% rename from frontend/src/test/modelStoreGrouping.test.jsx rename to electron/src/shared/test/modelStoreGrouping.test.jsx diff --git a/frontend/src/test/modelStoreIncomplete.test.jsx b/electron/src/shared/test/modelStoreIncomplete.test.jsx similarity index 100% rename from frontend/src/test/modelStoreIncomplete.test.jsx rename to electron/src/shared/test/modelStoreIncomplete.test.jsx diff --git a/frontend/src/test/modelStoreInstallError.test.jsx b/electron/src/shared/test/modelStoreInstallError.test.jsx similarity index 100% rename from frontend/src/test/modelStoreInstallError.test.jsx rename to electron/src/shared/test/modelStoreInstallError.test.jsx diff --git a/frontend/src/test/modelStoreResidency.test.jsx b/electron/src/shared/test/modelStoreResidency.test.jsx similarity index 100% rename from frontend/src/test/modelStoreResidency.test.jsx rename to electron/src/shared/test/modelStoreResidency.test.jsx diff --git a/frontend/src/test/modelsTableEmptyState.test.jsx b/electron/src/shared/test/modelsTableEmptyState.test.jsx similarity index 100% rename from frontend/src/test/modelsTableEmptyState.test.jsx rename to electron/src/shared/test/modelsTableEmptyState.test.jsx diff --git a/frontend/src/test/navTabsGridColumns.test.js b/electron/src/shared/test/navTabsGridColumns.test.js similarity index 100% rename from frontend/src/test/navTabsGridColumns.test.js rename to electron/src/shared/test/navTabsGridColumns.test.js diff --git a/frontend/src/test/omniUiSchema.test.js b/electron/src/shared/test/omniUiSchema.test.js similarity index 100% rename from frontend/src/test/omniUiSchema.test.js rename to electron/src/shared/test/omniUiSchema.test.js diff --git a/frontend/src/test/openSettingsTab.test.js b/electron/src/shared/test/openSettingsTab.test.js similarity index 100% rename from frontend/src/test/openSettingsTab.test.js rename to electron/src/shared/test/openSettingsTab.test.js diff --git a/frontend/src/test/playBlobAudioFallback.test.js b/electron/src/shared/test/playBlobAudioFallback.test.js similarity index 100% rename from frontend/src/test/playBlobAudioFallback.test.js rename to electron/src/shared/test/playBlobAudioFallback.test.js diff --git a/frontend/src/test/playBlobAudioTracked.test.js b/electron/src/shared/test/playBlobAudioTracked.test.js similarity index 100% rename from frontend/src/test/playBlobAudioTracked.test.js rename to electron/src/shared/test/playBlobAudioTracked.test.js diff --git a/frontend/src/test/portInUseHint.test.js b/electron/src/shared/test/portInUseHint.test.js similarity index 100% rename from frontend/src/test/portInUseHint.test.js rename to electron/src/shared/test/portInUseHint.test.js diff --git a/frontend/src/test/probeAudioDuration.test.js b/electron/src/shared/test/probeAudioDuration.test.js similarity index 100% rename from frontend/src/test/probeAudioDuration.test.js rename to electron/src/shared/test/probeAudioDuration.test.js diff --git a/frontend/src/test/reduceMotionToggle.test.jsx b/electron/src/shared/test/reduceMotionToggle.test.jsx similarity index 100% rename from frontend/src/test/reduceMotionToggle.test.jsx rename to electron/src/shared/test/reduceMotionToggle.test.jsx diff --git a/frontend/src/test/refinementFailureNote.test.js b/electron/src/shared/test/refinementFailureNote.test.js similarity index 100% rename from frontend/src/test/refinementFailureNote.test.js rename to electron/src/shared/test/refinementFailureNote.test.js diff --git a/frontend/src/test/scriptPanelInsertPopover.test.jsx b/electron/src/shared/test/scriptPanelInsertPopover.test.jsx similarity index 100% rename from frontend/src/test/scriptPanelInsertPopover.test.jsx rename to electron/src/shared/test/scriptPanelInsertPopover.test.jsx diff --git a/frontend/src/test/seed.test.js b/electron/src/shared/test/seed.test.js similarity index 100% rename from frontend/src/test/seed.test.js rename to electron/src/shared/test/seed.test.js diff --git a/frontend/src/test/segments.cueSource.test.js b/electron/src/shared/test/segments.cueSource.test.js similarity index 100% rename from frontend/src/test/segments.cueSource.test.js rename to electron/src/shared/test/segments.cueSource.test.js diff --git a/frontend/src/test/segments.speakerClone.test.js b/electron/src/shared/test/segments.speakerClone.test.js similarity index 100% rename from frontend/src/test/segments.speakerClone.test.js rename to electron/src/shared/test/segments.speakerClone.test.js diff --git a/frontend/src/test/setup.js b/electron/src/shared/test/setup.js similarity index 100% rename from frontend/src/test/setup.js rename to electron/src/shared/test/setup.js diff --git a/frontend/src/test/splashWatchdog.test.js b/electron/src/shared/test/splashWatchdog.test.js similarity index 100% rename from frontend/src/test/splashWatchdog.test.js rename to electron/src/shared/test/splashWatchdog.test.js diff --git a/frontend/src/test/splitStoryText.test.js b/electron/src/shared/test/splitStoryText.test.js similarity index 100% rename from frontend/src/test/splitStoryText.test.js rename to electron/src/shared/test/splitStoryText.test.js diff --git a/frontend/src/test/sseParse.test.js b/electron/src/shared/test/sseParse.test.js similarity index 100% rename from frontend/src/test/sseParse.test.js rename to electron/src/shared/test/sseParse.test.js diff --git a/frontend/src/test/ssmlLite.test.js b/electron/src/shared/test/ssmlLite.test.js similarity index 100% rename from frontend/src/test/ssmlLite.test.js rename to electron/src/shared/test/ssmlLite.test.js diff --git a/frontend/src/test/storyToSpans.test.js b/electron/src/shared/test/storyToSpans.test.js similarity index 100% rename from frontend/src/test/storyToSpans.test.js rename to electron/src/shared/test/storyToSpans.test.js diff --git a/frontend/src/test/streamDropError.test.ts b/electron/src/shared/test/streamDropError.test.ts similarity index 100% rename from frontend/src/test/streamDropError.test.ts rename to electron/src/shared/test/streamDropError.test.ts diff --git a/frontend/src/test/streamingPreflight.test.js b/electron/src/shared/test/streamingPreflight.test.js similarity index 100% rename from frontend/src/test/streamingPreflight.test.js rename to electron/src/shared/test/streamingPreflight.test.js diff --git a/frontend/src/test/streamingTts.test.js b/electron/src/shared/test/streamingTts.test.js similarity index 100% rename from frontend/src/test/streamingTts.test.js rename to electron/src/shared/test/streamingTts.test.js diff --git a/frontend/src/test/themeCascade.test.js b/electron/src/shared/test/themeCascade.test.js similarity index 100% rename from frontend/src/test/themeCascade.test.js rename to electron/src/shared/test/themeCascade.test.js diff --git a/frontend/src/test/tokenParity.test.js b/electron/src/shared/test/tokenParity.test.js similarity index 100% rename from frontend/src/test/tokenParity.test.js rename to electron/src/shared/test/tokenParity.test.js diff --git a/frontend/src/test/ttsInflight.test.js b/electron/src/shared/test/ttsInflight.test.js similarity index 100% rename from frontend/src/test/ttsInflight.test.js rename to electron/src/shared/test/ttsInflight.test.js diff --git a/frontend/src/test/uiScaleFirstRunOrder.test.js b/electron/src/shared/test/uiScaleFirstRunOrder.test.js similarity index 100% rename from frontend/src/test/uiScaleFirstRunOrder.test.js rename to electron/src/shared/test/uiScaleFirstRunOrder.test.js diff --git a/frontend/src/test/uninstallPanel.test.js b/electron/src/shared/test/uninstallPanel.test.js similarity index 100% rename from frontend/src/test/uninstallPanel.test.js rename to electron/src/shared/test/uninstallPanel.test.js diff --git a/frontend/src/test/updatesPanelBusy.test.jsx b/electron/src/shared/test/updatesPanelBusy.test.jsx similarity index 100% rename from frontend/src/test/updatesPanelBusy.test.jsx rename to electron/src/shared/test/updatesPanelBusy.test.jsx diff --git a/frontend/src/test/usageTab.test.js b/electron/src/shared/test/usageTab.test.js similarity index 100% rename from frontend/src/test/usageTab.test.js rename to electron/src/shared/test/usageTab.test.js diff --git a/frontend/src/test/useRealtimeEvents.test.jsx b/electron/src/shared/test/useRealtimeEvents.test.jsx similarity index 100% rename from frontend/src/test/useRealtimeEvents.test.jsx rename to electron/src/shared/test/useRealtimeEvents.test.jsx diff --git a/frontend/src/test/useRecordingMicPreflight.test.js b/electron/src/shared/test/useRecordingMicPreflight.test.js similarity index 100% rename from frontend/src/test/useRecordingMicPreflight.test.js rename to electron/src/shared/test/useRecordingMicPreflight.test.js diff --git a/frontend/src/test/useTTSAutoplayPref.test.jsx b/electron/src/shared/test/useTTSAutoplayPref.test.jsx similarity index 100% rename from frontend/src/test/useTTSAutoplayPref.test.jsx rename to electron/src/shared/test/useTTSAutoplayPref.test.jsx diff --git a/frontend/src/test/visual/DubWorkspaceFixture.jsx b/electron/src/shared/test/visual/DubWorkspaceFixture.jsx similarity index 100% rename from frontend/src/test/visual/DubWorkspaceFixture.jsx rename to electron/src/shared/test/visual/DubWorkspaceFixture.jsx diff --git a/frontend/src/test/visual/README.md b/electron/src/shared/test/visual/README.md similarity index 100% rename from frontend/src/test/visual/README.md rename to electron/src/shared/test/visual/README.md diff --git a/frontend/src/test/visual/__screenshots__/AppearancePanel-catppuccin.png b/electron/src/shared/test/visual/__screenshots__/AppearancePanel-catppuccin.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/AppearancePanel-catppuccin.png rename to electron/src/shared/test/visual/__screenshots__/AppearancePanel-catppuccin.png diff --git a/frontend/src/test/visual/__screenshots__/AppearancePanel-default.png b/electron/src/shared/test/visual/__screenshots__/AppearancePanel-default.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/AppearancePanel-default.png rename to electron/src/shared/test/visual/__screenshots__/AppearancePanel-default.png diff --git a/frontend/src/test/visual/__screenshots__/AppearancePanel-midnight.png b/electron/src/shared/test/visual/__screenshots__/AppearancePanel-midnight.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/AppearancePanel-midnight.png rename to electron/src/shared/test/visual/__screenshots__/AppearancePanel-midnight.png diff --git a/frontend/src/test/visual/__screenshots__/Badge-catppuccin.png b/electron/src/shared/test/visual/__screenshots__/Badge-catppuccin.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Badge-catppuccin.png rename to electron/src/shared/test/visual/__screenshots__/Badge-catppuccin.png diff --git a/frontend/src/test/visual/__screenshots__/Badge-default.png b/electron/src/shared/test/visual/__screenshots__/Badge-default.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Badge-default.png rename to electron/src/shared/test/visual/__screenshots__/Badge-default.png diff --git a/frontend/src/test/visual/__screenshots__/Badge-midnight.png b/electron/src/shared/test/visual/__screenshots__/Badge-midnight.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Badge-midnight.png rename to electron/src/shared/test/visual/__screenshots__/Badge-midnight.png diff --git a/frontend/src/test/visual/__screenshots__/Button-catppuccin.png b/electron/src/shared/test/visual/__screenshots__/Button-catppuccin.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Button-catppuccin.png rename to electron/src/shared/test/visual/__screenshots__/Button-catppuccin.png diff --git a/frontend/src/test/visual/__screenshots__/Button-default.png b/electron/src/shared/test/visual/__screenshots__/Button-default.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Button-default.png rename to electron/src/shared/test/visual/__screenshots__/Button-default.png diff --git a/frontend/src/test/visual/__screenshots__/Button-midnight.png b/electron/src/shared/test/visual/__screenshots__/Button-midnight.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Button-midnight.png rename to electron/src/shared/test/visual/__screenshots__/Button-midnight.png diff --git a/frontend/src/test/visual/__screenshots__/GeneralTab-catppuccin.png b/electron/src/shared/test/visual/__screenshots__/GeneralTab-catppuccin.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/GeneralTab-catppuccin.png rename to electron/src/shared/test/visual/__screenshots__/GeneralTab-catppuccin.png diff --git a/frontend/src/test/visual/__screenshots__/GeneralTab-default.png b/electron/src/shared/test/visual/__screenshots__/GeneralTab-default.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/GeneralTab-default.png rename to electron/src/shared/test/visual/__screenshots__/GeneralTab-default.png diff --git a/frontend/src/test/visual/__screenshots__/GeneralTab-midnight.png b/electron/src/shared/test/visual/__screenshots__/GeneralTab-midnight.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/GeneralTab-midnight.png rename to electron/src/shared/test/visual/__screenshots__/GeneralTab-midnight.png diff --git a/frontend/src/test/visual/__screenshots__/Input-catppuccin.png b/electron/src/shared/test/visual/__screenshots__/Input-catppuccin.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Input-catppuccin.png rename to electron/src/shared/test/visual/__screenshots__/Input-catppuccin.png diff --git a/frontend/src/test/visual/__screenshots__/Input-default.png b/electron/src/shared/test/visual/__screenshots__/Input-default.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Input-default.png rename to electron/src/shared/test/visual/__screenshots__/Input-default.png diff --git a/frontend/src/test/visual/__screenshots__/Input-midnight.png b/electron/src/shared/test/visual/__screenshots__/Input-midnight.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Input-midnight.png rename to electron/src/shared/test/visual/__screenshots__/Input-midnight.png diff --git a/frontend/src/test/visual/__screenshots__/Panel-catppuccin.png b/electron/src/shared/test/visual/__screenshots__/Panel-catppuccin.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Panel-catppuccin.png rename to electron/src/shared/test/visual/__screenshots__/Panel-catppuccin.png diff --git a/frontend/src/test/visual/__screenshots__/Panel-default.png b/electron/src/shared/test/visual/__screenshots__/Panel-default.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Panel-default.png rename to electron/src/shared/test/visual/__screenshots__/Panel-default.png diff --git a/frontend/src/test/visual/__screenshots__/Panel-midnight.png b/electron/src/shared/test/visual/__screenshots__/Panel-midnight.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Panel-midnight.png rename to electron/src/shared/test/visual/__screenshots__/Panel-midnight.png diff --git a/frontend/src/test/visual/__screenshots__/Progress-catppuccin.png b/electron/src/shared/test/visual/__screenshots__/Progress-catppuccin.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Progress-catppuccin.png rename to electron/src/shared/test/visual/__screenshots__/Progress-catppuccin.png diff --git a/frontend/src/test/visual/__screenshots__/Progress-default.png b/electron/src/shared/test/visual/__screenshots__/Progress-default.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Progress-default.png rename to electron/src/shared/test/visual/__screenshots__/Progress-default.png diff --git a/frontend/src/test/visual/__screenshots__/Progress-midnight.png b/electron/src/shared/test/visual/__screenshots__/Progress-midnight.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Progress-midnight.png rename to electron/src/shared/test/visual/__screenshots__/Progress-midnight.png diff --git a/frontend/src/test/visual/__screenshots__/ResetPanel-catppuccin.png b/electron/src/shared/test/visual/__screenshots__/ResetPanel-catppuccin.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/ResetPanel-catppuccin.png rename to electron/src/shared/test/visual/__screenshots__/ResetPanel-catppuccin.png diff --git a/frontend/src/test/visual/__screenshots__/ResetPanel-default.png b/electron/src/shared/test/visual/__screenshots__/ResetPanel-default.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/ResetPanel-default.png rename to electron/src/shared/test/visual/__screenshots__/ResetPanel-default.png diff --git a/frontend/src/test/visual/__screenshots__/ResetPanel-midnight.png b/electron/src/shared/test/visual/__screenshots__/ResetPanel-midnight.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/ResetPanel-midnight.png rename to electron/src/shared/test/visual/__screenshots__/ResetPanel-midnight.png diff --git a/frontend/src/test/visual/__screenshots__/Segmented-catppuccin.png b/electron/src/shared/test/visual/__screenshots__/Segmented-catppuccin.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Segmented-catppuccin.png rename to electron/src/shared/test/visual/__screenshots__/Segmented-catppuccin.png diff --git a/frontend/src/test/visual/__screenshots__/Segmented-default.png b/electron/src/shared/test/visual/__screenshots__/Segmented-default.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Segmented-default.png rename to electron/src/shared/test/visual/__screenshots__/Segmented-default.png diff --git a/frontend/src/test/visual/__screenshots__/Segmented-midnight.png b/electron/src/shared/test/visual/__screenshots__/Segmented-midnight.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Segmented-midnight.png rename to electron/src/shared/test/visual/__screenshots__/Segmented-midnight.png diff --git a/frontend/src/test/visual/__screenshots__/SettingRow-catppuccin.png b/electron/src/shared/test/visual/__screenshots__/SettingRow-catppuccin.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/SettingRow-catppuccin.png rename to electron/src/shared/test/visual/__screenshots__/SettingRow-catppuccin.png diff --git a/frontend/src/test/visual/__screenshots__/SettingRow-default.png b/electron/src/shared/test/visual/__screenshots__/SettingRow-default.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/SettingRow-default.png rename to electron/src/shared/test/visual/__screenshots__/SettingRow-default.png diff --git a/frontend/src/test/visual/__screenshots__/SettingRow-midnight.png b/electron/src/shared/test/visual/__screenshots__/SettingRow-midnight.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/SettingRow-midnight.png rename to electron/src/shared/test/visual/__screenshots__/SettingRow-midnight.png diff --git a/frontend/src/test/visual/__screenshots__/SettingsToggle-catppuccin.png b/electron/src/shared/test/visual/__screenshots__/SettingsToggle-catppuccin.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/SettingsToggle-catppuccin.png rename to electron/src/shared/test/visual/__screenshots__/SettingsToggle-catppuccin.png diff --git a/frontend/src/test/visual/__screenshots__/SettingsToggle-default.png b/electron/src/shared/test/visual/__screenshots__/SettingsToggle-default.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/SettingsToggle-default.png rename to electron/src/shared/test/visual/__screenshots__/SettingsToggle-default.png diff --git a/frontend/src/test/visual/__screenshots__/SettingsToggle-midnight.png b/electron/src/shared/test/visual/__screenshots__/SettingsToggle-midnight.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/SettingsToggle-midnight.png rename to electron/src/shared/test/visual/__screenshots__/SettingsToggle-midnight.png diff --git a/frontend/src/test/visual/__screenshots__/ShadcnButton-catppuccin.png b/electron/src/shared/test/visual/__screenshots__/ShadcnButton-catppuccin.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/ShadcnButton-catppuccin.png rename to electron/src/shared/test/visual/__screenshots__/ShadcnButton-catppuccin.png diff --git a/frontend/src/test/visual/__screenshots__/ShadcnButton-default.png b/electron/src/shared/test/visual/__screenshots__/ShadcnButton-default.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/ShadcnButton-default.png rename to electron/src/shared/test/visual/__screenshots__/ShadcnButton-default.png diff --git a/frontend/src/test/visual/__screenshots__/ShadcnButton-midnight.png b/electron/src/shared/test/visual/__screenshots__/ShadcnButton-midnight.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/ShadcnButton-midnight.png rename to electron/src/shared/test/visual/__screenshots__/ShadcnButton-midnight.png diff --git a/frontend/src/test/visual/__screenshots__/ShadcnInput-catppuccin.png b/electron/src/shared/test/visual/__screenshots__/ShadcnInput-catppuccin.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/ShadcnInput-catppuccin.png rename to electron/src/shared/test/visual/__screenshots__/ShadcnInput-catppuccin.png diff --git a/frontend/src/test/visual/__screenshots__/ShadcnInput-default.png b/electron/src/shared/test/visual/__screenshots__/ShadcnInput-default.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/ShadcnInput-default.png rename to electron/src/shared/test/visual/__screenshots__/ShadcnInput-default.png diff --git a/frontend/src/test/visual/__screenshots__/ShadcnInput-midnight.png b/electron/src/shared/test/visual/__screenshots__/ShadcnInput-midnight.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/ShadcnInput-midnight.png rename to electron/src/shared/test/visual/__screenshots__/ShadcnInput-midnight.png diff --git a/frontend/src/test/visual/__screenshots__/Slider-catppuccin.png b/electron/src/shared/test/visual/__screenshots__/Slider-catppuccin.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Slider-catppuccin.png rename to electron/src/shared/test/visual/__screenshots__/Slider-catppuccin.png diff --git a/frontend/src/test/visual/__screenshots__/Slider-default.png b/electron/src/shared/test/visual/__screenshots__/Slider-default.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Slider-default.png rename to electron/src/shared/test/visual/__screenshots__/Slider-default.png diff --git a/frontend/src/test/visual/__screenshots__/Slider-midnight.png b/electron/src/shared/test/visual/__screenshots__/Slider-midnight.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Slider-midnight.png rename to electron/src/shared/test/visual/__screenshots__/Slider-midnight.png diff --git a/frontend/src/test/visual/__screenshots__/StoragePanel-catppuccin.png b/electron/src/shared/test/visual/__screenshots__/StoragePanel-catppuccin.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/StoragePanel-catppuccin.png rename to electron/src/shared/test/visual/__screenshots__/StoragePanel-catppuccin.png diff --git a/frontend/src/test/visual/__screenshots__/StoragePanel-default.png b/electron/src/shared/test/visual/__screenshots__/StoragePanel-default.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/StoragePanel-default.png rename to electron/src/shared/test/visual/__screenshots__/StoragePanel-default.png diff --git a/frontend/src/test/visual/__screenshots__/StoragePanel-midnight.png b/electron/src/shared/test/visual/__screenshots__/StoragePanel-midnight.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/StoragePanel-midnight.png rename to electron/src/shared/test/visual/__screenshots__/StoragePanel-midnight.png diff --git a/frontend/src/test/visual/__screenshots__/Table-catppuccin.png b/electron/src/shared/test/visual/__screenshots__/Table-catppuccin.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Table-catppuccin.png rename to electron/src/shared/test/visual/__screenshots__/Table-catppuccin.png diff --git a/frontend/src/test/visual/__screenshots__/Table-default.png b/electron/src/shared/test/visual/__screenshots__/Table-default.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Table-default.png rename to electron/src/shared/test/visual/__screenshots__/Table-default.png diff --git a/frontend/src/test/visual/__screenshots__/Table-midnight.png b/electron/src/shared/test/visual/__screenshots__/Table-midnight.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Table-midnight.png rename to electron/src/shared/test/visual/__screenshots__/Table-midnight.png diff --git a/frontend/src/test/visual/__screenshots__/Tabs-catppuccin.png b/electron/src/shared/test/visual/__screenshots__/Tabs-catppuccin.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Tabs-catppuccin.png rename to electron/src/shared/test/visual/__screenshots__/Tabs-catppuccin.png diff --git a/frontend/src/test/visual/__screenshots__/Tabs-default.png b/electron/src/shared/test/visual/__screenshots__/Tabs-default.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Tabs-default.png rename to electron/src/shared/test/visual/__screenshots__/Tabs-default.png diff --git a/frontend/src/test/visual/__screenshots__/Tabs-midnight.png b/electron/src/shared/test/visual/__screenshots__/Tabs-midnight.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/Tabs-midnight.png rename to electron/src/shared/test/visual/__screenshots__/Tabs-midnight.png diff --git a/frontend/src/test/visual/__screenshots__/TitleTabs-catppuccin.png b/electron/src/shared/test/visual/__screenshots__/TitleTabs-catppuccin.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/TitleTabs-catppuccin.png rename to electron/src/shared/test/visual/__screenshots__/TitleTabs-catppuccin.png diff --git a/frontend/src/test/visual/__screenshots__/TitleTabs-default.png b/electron/src/shared/test/visual/__screenshots__/TitleTabs-default.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/TitleTabs-default.png rename to electron/src/shared/test/visual/__screenshots__/TitleTabs-default.png diff --git a/frontend/src/test/visual/__screenshots__/TitleTabs-midnight.png b/electron/src/shared/test/visual/__screenshots__/TitleTabs-midnight.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/TitleTabs-midnight.png rename to electron/src/shared/test/visual/__screenshots__/TitleTabs-midnight.png diff --git a/frontend/src/test/visual/__screenshots__/UninstallPanel-catppuccin.png b/electron/src/shared/test/visual/__screenshots__/UninstallPanel-catppuccin.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/UninstallPanel-catppuccin.png rename to electron/src/shared/test/visual/__screenshots__/UninstallPanel-catppuccin.png diff --git a/frontend/src/test/visual/__screenshots__/UninstallPanel-default.png b/electron/src/shared/test/visual/__screenshots__/UninstallPanel-default.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/UninstallPanel-default.png rename to electron/src/shared/test/visual/__screenshots__/UninstallPanel-default.png diff --git a/frontend/src/test/visual/__screenshots__/UninstallPanel-midnight.png b/electron/src/shared/test/visual/__screenshots__/UninstallPanel-midnight.png similarity index 100% rename from frontend/src/test/visual/__screenshots__/UninstallPanel-midnight.png rename to electron/src/shared/test/visual/__screenshots__/UninstallPanel-midnight.png diff --git a/frontend/src/test/visual/audiobook-layout.visual.spec.ts b/electron/src/shared/test/visual/audiobook-layout.visual.spec.ts similarity index 100% rename from frontend/src/test/visual/audiobook-layout.visual.spec.ts rename to electron/src/shared/test/visual/audiobook-layout.visual.spec.ts diff --git a/frontend/src/test/visual/baseline.visual.spec.ts b/electron/src/shared/test/visual/baseline.visual.spec.ts similarity index 100% rename from frontend/src/test/visual/baseline.visual.spec.ts rename to electron/src/shared/test/visual/baseline.visual.spec.ts diff --git a/frontend/src/test/visual/dub-idle-start.visual.spec.ts b/electron/src/shared/test/visual/dub-idle-start.visual.spec.ts similarity index 100% rename from frontend/src/test/visual/dub-idle-start.visual.spec.ts rename to electron/src/shared/test/visual/dub-idle-start.visual.spec.ts diff --git a/frontend/src/test/visual/dub-idle-workspace.visual.spec.ts b/electron/src/shared/test/visual/dub-idle-workspace.visual.spec.ts similarity index 100% rename from frontend/src/test/visual/dub-idle-workspace.visual.spec.ts rename to electron/src/shared/test/visual/dub-idle-workspace.visual.spec.ts diff --git a/frontend/src/test/visual/dub-segment-layout.visual.spec.ts b/electron/src/shared/test/visual/dub-segment-layout.visual.spec.ts similarity index 100% rename from frontend/src/test/visual/dub-segment-layout.visual.spec.ts rename to electron/src/shared/test/visual/dub-segment-layout.visual.spec.ts diff --git a/frontend/src/test/visual/dub-workspace.visual.spec.ts b/electron/src/shared/test/visual/dub-workspace.visual.spec.ts similarity index 100% rename from frontend/src/test/visual/dub-workspace.visual.spec.ts rename to electron/src/shared/test/visual/dub-workspace.visual.spec.ts diff --git a/frontend/src/test/visual/harness.css b/electron/src/shared/test/visual/harness.css similarity index 100% rename from frontend/src/test/visual/harness.css rename to electron/src/shared/test/visual/harness.css diff --git a/frontend/src/test/visual/harness.html b/electron/src/shared/test/visual/harness.html similarity index 100% rename from frontend/src/test/visual/harness.html rename to electron/src/shared/test/visual/harness.html diff --git a/frontend/src/test/visual/harness.jsx b/electron/src/shared/test/visual/harness.jsx similarity index 100% rename from frontend/src/test/visual/harness.jsx rename to electron/src/shared/test/visual/harness.jsx diff --git a/frontend/src/test/visual/header-motion.visual.spec.ts b/electron/src/shared/test/visual/header-motion.visual.spec.ts similarity index 100% rename from frontend/src/test/visual/header-motion.visual.spec.ts rename to electron/src/shared/test/visual/header-motion.visual.spec.ts diff --git a/frontend/src/test/visual/manifest.ts b/electron/src/shared/test/visual/manifest.ts similarity index 100% rename from frontend/src/test/visual/manifest.ts rename to electron/src/shared/test/visual/manifest.ts diff --git a/frontend/src/test/visual/providers.jsx b/electron/src/shared/test/visual/providers.jsx similarity index 100% rename from frontend/src/test/visual/providers.jsx rename to electron/src/shared/test/visual/providers.jsx diff --git a/frontend/src/test/visual/specs.jsx b/electron/src/shared/test/visual/specs.jsx similarity index 100% rename from frontend/src/test/visual/specs.jsx rename to electron/src/shared/test/visual/specs.jsx diff --git a/frontend/src/test/visual/stories-workspace.visual.spec.ts b/electron/src/shared/test/visual/stories-workspace.visual.spec.ts similarity index 100% rename from frontend/src/test/visual/stories-workspace.visual.spec.ts rename to electron/src/shared/test/visual/stories-workspace.visual.spec.ts diff --git a/frontend/src/test/visual/waveformFixture.js b/electron/src/shared/test/visual/waveformFixture.js similarity index 100% rename from frontend/src/test/visual/waveformFixture.js rename to electron/src/shared/test/visual/waveformFixture.js diff --git a/frontend/src/test/watermarkControl.test.jsx b/electron/src/shared/test/watermarkControl.test.jsx similarity index 100% rename from frontend/src/test/watermarkControl.test.jsx rename to electron/src/shared/test/watermarkControl.test.jsx diff --git a/frontend/src/test/webCompat.test.js b/electron/src/shared/test/webCompat.test.js similarity index 99% rename from frontend/src/test/webCompat.test.js rename to electron/src/shared/test/webCompat.test.js index 1a2cebda7..bc67afa7e 100644 --- a/frontend/src/test/webCompat.test.js +++ b/electron/src/shared/test/webCompat.test.js @@ -99,7 +99,7 @@ describe('AbortSignal.timeout polyfill', () => { * - **Syntax.** A post-floor *grammar* feature (RegExp lookbehind, Safari * 16.4) is a parse-time SyntaxError that kills its whole chunk before a * line runs, and no polyfill can help. Text patterns here cannot see that. - * - **Dependencies.** Only `frontend/src` is scanned. A bundled library using + * - **Dependencies.** Only `electron/src/shared` is scanned. A bundled library using * a post-floor API or grammar is invisible here and ships anyway. * - **CSS.** Tailwind v4's own floor is Safari 16.4, and `index.css` uses * `color-mix()` (16.2) throughout, so the *rendering* floor is already diff --git a/frontend/src/test/widgetPillShadowClip.test.jsx b/electron/src/shared/test/widgetPillShadowClip.test.jsx similarity index 100% rename from frontend/src/test/widgetPillShadowClip.test.jsx rename to electron/src/shared/test/widgetPillShadowClip.test.jsx diff --git a/frontend/src/test/widgetWindowTransparency.test.jsx b/electron/src/shared/test/widgetWindowTransparency.test.jsx similarity index 100% rename from frontend/src/test/widgetWindowTransparency.test.jsx rename to electron/src/shared/test/widgetWindowTransparency.test.jsx diff --git a/frontend/src/test/wizardLibraryAggregate.test.js b/electron/src/shared/test/wizardLibraryAggregate.test.js similarity index 100% rename from frontend/src/test/wizardLibraryAggregate.test.js rename to electron/src/shared/test/wizardLibraryAggregate.test.js diff --git a/frontend/src/test/wizardLibraryInstallError.test.js b/electron/src/shared/test/wizardLibraryInstallError.test.js similarity index 100% rename from frontend/src/test/wizardLibraryInstallError.test.js rename to electron/src/shared/test/wizardLibraryInstallError.test.js diff --git a/frontend/src/test/wizardLibraryPlatformPick.test.js b/electron/src/shared/test/wizardLibraryPlatformPick.test.js similarity index 100% rename from frontend/src/test/wizardLibraryPlatformPick.test.js rename to electron/src/shared/test/wizardLibraryPlatformPick.test.js diff --git a/frontend/src/test/workspaceHistoryReflow.test.js b/electron/src/shared/test/workspaceHistoryReflow.test.js similarity index 100% rename from frontend/src/test/workspaceHistoryReflow.test.js rename to electron/src/shared/test/workspaceHistoryReflow.test.js diff --git a/frontend/src/ui/Badge.jsx b/electron/src/shared/ui/Badge.jsx similarity index 100% rename from frontend/src/ui/Badge.jsx rename to electron/src/shared/ui/Badge.jsx diff --git a/frontend/src/ui/Button.jsx b/electron/src/shared/ui/Button.jsx similarity index 100% rename from frontend/src/ui/Button.jsx rename to electron/src/shared/ui/Button.jsx diff --git a/frontend/src/ui/Dialog.jsx b/electron/src/shared/ui/Dialog.jsx similarity index 100% rename from frontend/src/ui/Dialog.jsx rename to electron/src/shared/ui/Dialog.jsx diff --git a/frontend/src/ui/Input.jsx b/electron/src/shared/ui/Input.jsx similarity index 100% rename from frontend/src/ui/Input.jsx rename to electron/src/shared/ui/Input.jsx diff --git a/frontend/src/ui/Menu.jsx b/electron/src/shared/ui/Menu.jsx similarity index 100% rename from frontend/src/ui/Menu.jsx rename to electron/src/shared/ui/Menu.jsx diff --git a/frontend/src/ui/Panel.jsx b/electron/src/shared/ui/Panel.jsx similarity index 100% rename from frontend/src/ui/Panel.jsx rename to electron/src/shared/ui/Panel.jsx diff --git a/frontend/src/ui/Progress.jsx b/electron/src/shared/ui/Progress.jsx similarity index 100% rename from frontend/src/ui/Progress.jsx rename to electron/src/shared/ui/Progress.jsx diff --git a/frontend/src/ui/README.md b/electron/src/shared/ui/README.md similarity index 100% rename from frontend/src/ui/README.md rename to electron/src/shared/ui/README.md diff --git a/frontend/src/ui/Segmented.jsx b/electron/src/shared/ui/Segmented.jsx similarity index 100% rename from frontend/src/ui/Segmented.jsx rename to electron/src/shared/ui/Segmented.jsx diff --git a/frontend/src/ui/Slider.jsx b/electron/src/shared/ui/Slider.jsx similarity index 100% rename from frontend/src/ui/Slider.jsx rename to electron/src/shared/ui/Slider.jsx diff --git a/frontend/src/ui/Table.jsx b/electron/src/shared/ui/Table.jsx similarity index 100% rename from frontend/src/ui/Table.jsx rename to electron/src/shared/ui/Table.jsx diff --git a/frontend/src/ui/Tabs.jsx b/electron/src/shared/ui/Tabs.jsx similarity index 100% rename from frontend/src/ui/Tabs.jsx rename to electron/src/shared/ui/Tabs.jsx diff --git a/frontend/src/ui/Tabs.test.jsx b/electron/src/shared/ui/Tabs.test.jsx similarity index 100% rename from frontend/src/ui/Tabs.test.jsx rename to electron/src/shared/ui/Tabs.test.jsx diff --git a/frontend/src/ui/Tooltip.jsx b/electron/src/shared/ui/Tooltip.jsx similarity index 100% rename from frontend/src/ui/Tooltip.jsx rename to electron/src/shared/ui/Tooltip.jsx diff --git a/frontend/src/ui/index.js b/electron/src/shared/ui/index.js similarity index 100% rename from frontend/src/ui/index.js rename to electron/src/shared/ui/index.js diff --git a/frontend/src/utils/abortableDelay.ts b/electron/src/shared/utils/abortableDelay.ts similarity index 100% rename from frontend/src/utils/abortableDelay.ts rename to electron/src/shared/utils/abortableDelay.ts diff --git a/frontend/src/utils/aec/farEndBus.d.ts b/electron/src/shared/utils/aec/farEndBus.d.ts similarity index 100% rename from frontend/src/utils/aec/farEndBus.d.ts rename to electron/src/shared/utils/aec/farEndBus.d.ts diff --git a/frontend/src/utils/aec/farEndBus.js b/electron/src/shared/utils/aec/farEndBus.js similarity index 100% rename from frontend/src/utils/aec/farEndBus.js rename to electron/src/shared/utils/aec/farEndBus.js diff --git a/frontend/src/utils/aec/micCapture.d.ts b/electron/src/shared/utils/aec/micCapture.d.ts similarity index 100% rename from frontend/src/utils/aec/micCapture.d.ts rename to electron/src/shared/utils/aec/micCapture.d.ts diff --git a/frontend/src/utils/aec/micCapture.js b/electron/src/shared/utils/aec/micCapture.js similarity index 100% rename from frontend/src/utils/aec/micCapture.js rename to electron/src/shared/utils/aec/micCapture.js diff --git a/frontend/src/utils/aec/micCapture.test.js b/electron/src/shared/utils/aec/micCapture.test.js similarity index 100% rename from frontend/src/utils/aec/micCapture.test.js rename to electron/src/shared/utils/aec/micCapture.test.js diff --git a/frontend/src/utils/aec/pcm.d.ts b/electron/src/shared/utils/aec/pcm.d.ts similarity index 100% rename from frontend/src/utils/aec/pcm.d.ts rename to electron/src/shared/utils/aec/pcm.d.ts diff --git a/frontend/src/utils/aec/pcm.js b/electron/src/shared/utils/aec/pcm.js similarity index 100% rename from frontend/src/utils/aec/pcm.js rename to electron/src/shared/utils/aec/pcm.js diff --git a/frontend/src/utils/aec/playbackTap.d.ts b/electron/src/shared/utils/aec/playbackTap.d.ts similarity index 100% rename from frontend/src/utils/aec/playbackTap.d.ts rename to electron/src/shared/utils/aec/playbackTap.d.ts diff --git a/frontend/src/utils/aec/playbackTap.js b/electron/src/shared/utils/aec/playbackTap.js similarity index 100% rename from frontend/src/utils/aec/playbackTap.js rename to electron/src/shared/utils/aec/playbackTap.js diff --git a/frontend/src/utils/aec/playbackTap.test.js b/electron/src/shared/utils/aec/playbackTap.test.js similarity index 100% rename from frontend/src/utils/aec/playbackTap.test.js rename to electron/src/shared/utils/aec/playbackTap.test.js diff --git a/frontend/src/utils/analytics.ts b/electron/src/shared/utils/analytics.ts similarity index 100% rename from frontend/src/utils/analytics.ts rename to electron/src/shared/utils/analytics.ts diff --git a/frontend/src/utils/apiBase.test.ts b/electron/src/shared/utils/apiBase.test.ts similarity index 100% rename from frontend/src/utils/apiBase.test.ts rename to electron/src/shared/utils/apiBase.test.ts diff --git a/frontend/src/utils/apiBase.ts b/electron/src/shared/utils/apiBase.ts similarity index 100% rename from frontend/src/utils/apiBase.ts rename to electron/src/shared/utils/apiBase.ts diff --git a/frontend/src/utils/appBusy.js b/electron/src/shared/utils/appBusy.js similarity index 100% rename from frontend/src/utils/appBusy.js rename to electron/src/shared/utils/appBusy.js diff --git a/frontend/src/utils/appShellClasses.js b/electron/src/shared/utils/appShellClasses.js similarity index 100% rename from frontend/src/utils/appShellClasses.js rename to electron/src/shared/utils/appShellClasses.js diff --git a/frontend/src/utils/appVersion.js b/electron/src/shared/utils/appVersion.js similarity index 100% rename from frontend/src/utils/appVersion.js rename to electron/src/shared/utils/appVersion.js diff --git a/frontend/src/utils/appVersion.test.js b/electron/src/shared/utils/appVersion.test.js similarity index 100% rename from frontend/src/utils/appVersion.test.js rename to electron/src/shared/utils/appVersion.test.js diff --git a/frontend/src/utils/archetypeIcons.jsx b/electron/src/shared/utils/archetypeIcons.jsx similarity index 100% rename from frontend/src/utils/archetypeIcons.jsx rename to electron/src/shared/utils/archetypeIcons.jsx diff --git a/frontend/src/utils/asrModelMissing.jsx b/electron/src/shared/utils/asrModelMissing.jsx similarity index 100% rename from frontend/src/utils/asrModelMissing.jsx rename to electron/src/shared/utils/asrModelMissing.jsx diff --git a/frontend/src/utils/audioInput.js b/electron/src/shared/utils/audioInput.js similarity index 100% rename from frontend/src/utils/audioInput.js rename to electron/src/shared/utils/audioInput.js diff --git a/frontend/src/utils/audioInput.test.js b/electron/src/shared/utils/audioInput.test.js similarity index 100% rename from frontend/src/utils/audioInput.test.js rename to electron/src/shared/utils/audioInput.test.js diff --git a/frontend/src/utils/audioTrim.d.ts b/electron/src/shared/utils/audioTrim.d.ts similarity index 100% rename from frontend/src/utils/audioTrim.d.ts rename to electron/src/shared/utils/audioTrim.d.ts diff --git a/frontend/src/utils/audioTrim.js b/electron/src/shared/utils/audioTrim.js similarity index 100% rename from frontend/src/utils/audioTrim.js rename to electron/src/shared/utils/audioTrim.js diff --git a/frontend/src/utils/audioUnlock.js b/electron/src/shared/utils/audioUnlock.js similarity index 100% rename from frontend/src/utils/audioUnlock.js rename to electron/src/shared/utils/audioUnlock.js diff --git a/frontend/src/utils/audioUnlock.test.js b/electron/src/shared/utils/audioUnlock.test.js similarity index 100% rename from frontend/src/utils/audioUnlock.test.js rename to electron/src/shared/utils/audioUnlock.test.js diff --git a/frontend/src/utils/audiobookLyrics.d.ts b/electron/src/shared/utils/audiobookLyrics.d.ts similarity index 100% rename from frontend/src/utils/audiobookLyrics.d.ts rename to electron/src/shared/utils/audiobookLyrics.d.ts diff --git a/frontend/src/utils/audiobookLyrics.js b/electron/src/shared/utils/audiobookLyrics.js similarity index 100% rename from frontend/src/utils/audiobookLyrics.js rename to electron/src/shared/utils/audiobookLyrics.js diff --git a/frontend/src/utils/audiobookLyrics.test.js b/electron/src/shared/utils/audiobookLyrics.test.js similarity index 100% rename from frontend/src/utils/audiobookLyrics.test.js rename to electron/src/shared/utils/audiobookLyrics.test.js diff --git a/frontend/src/utils/audiobookScript.d.ts b/electron/src/shared/utils/audiobookScript.d.ts similarity index 100% rename from frontend/src/utils/audiobookScript.d.ts rename to electron/src/shared/utils/audiobookScript.d.ts diff --git a/frontend/src/utils/audiobookScript.js b/electron/src/shared/utils/audiobookScript.js similarity index 100% rename from frontend/src/utils/audiobookScript.js rename to electron/src/shared/utils/audiobookScript.js diff --git a/frontend/src/utils/autoCast.d.ts b/electron/src/shared/utils/autoCast.d.ts similarity index 100% rename from frontend/src/utils/autoCast.d.ts rename to electron/src/shared/utils/autoCast.d.ts diff --git a/frontend/src/utils/autoCast.js b/electron/src/shared/utils/autoCast.js similarity index 100% rename from frontend/src/utils/autoCast.js rename to electron/src/shared/utils/autoCast.js diff --git a/frontend/src/utils/backendContact.ts b/electron/src/shared/utils/backendContact.ts similarity index 100% rename from frontend/src/utils/backendContact.ts rename to electron/src/shared/utils/backendContact.ts diff --git a/frontend/src/utils/backendCrash.ts b/electron/src/shared/utils/backendCrash.ts similarity index 96% rename from frontend/src/utils/backendCrash.ts rename to electron/src/shared/utils/backendCrash.ts index 3e84f2db3..3836cb1fa 100644 --- a/frontend/src/utils/backendCrash.ts +++ b/electron/src/shared/utils/backendCrash.ts @@ -45,9 +45,8 @@ export interface BackendCrashMarker { acknowledged: boolean; } -function inTauri(): boolean { - const w = window as unknown as Record | undefined; - return typeof window !== 'undefined' && !!(w?.__TAURI__ || w?.__TAURI_INTERNALS__); +function inElectron(): boolean { + return typeof window !== 'undefined' && !!window.voicestudio; } // ── Browser/Docker fallback: the backend's run-sentinel record (#1164) ───── @@ -177,10 +176,20 @@ async function fetchLastRunCrash(): Promise { /** Newest crash marker: the shell's (desktop) or the backend run-sentinel's * (browser/dev/Docker), or null when nothing ever crashed / nothing answers. */ export async function getLastBackendCrash(): Promise { - if (!inTauri()) return fetchLastRunCrash(); + if (!inElectron()) return fetchLastRunCrash(); try { - const { invoke } = await import('@tauri-apps/api/core'); - return ((await invoke('get_last_backend_crash')) as BackendCrashMarker | null) ?? null; + const crash = (await window.voicestudio.backend.getStatus()).lastCrash; + if (!crash) return null; + return { + ts: Math.round(crash.timestamp / 1000), + exit_code: crash.exitCode, + signal: null, + exit_desc: crash.signal || (crash.exitCode == null ? 'process ended unexpectedly' : ''), + backend_version: crash.version, + uptime_s: Math.round(crash.uptimeMs / 1000), + last_stderr: crash.logTail.join('\n'), + acknowledged: crash.acknowledged, + }; } catch { return null; } @@ -235,7 +244,7 @@ export async function awaitBackendCrashMarker( } opts.signal?.throwIfAborted(); if (crash) return { crash, unavailable: false }; - if (!inTauri()) return { crash: null, unavailable: false }; + if (!inElectron()) return { crash: null, unavailable: false }; if (Date.now() >= deadline) return { crash: null, unavailable: false }; await sleep(intervalMs); } @@ -243,7 +252,7 @@ export async function awaitBackendCrashMarker( /** Mark the newest crash as seen (the marker itself is retained for reports). */ export async function acknowledgeBackendCrash(): Promise { - if (!inTauri()) { + if (!inElectron()) { // Browser/dev/Docker: watermark the backend's run-sentinel record. try { const { API, apiUrl } = await import('../api/client.ts'); @@ -258,8 +267,7 @@ export async function acknowledgeBackendCrash(): Promise { return; } try { - const { invoke } = await import('@tauri-apps/api/core'); - await invoke('acknowledge_backend_crash'); + await window.voicestudio.backend.acknowledgeCrash(); } catch { /* shell unavailable — nothing to acknowledge */ } diff --git a/frontend/src/utils/backendLifecycle.ts b/electron/src/shared/utils/backendLifecycle.ts similarity index 81% rename from frontend/src/utils/backendLifecycle.ts rename to electron/src/shared/utils/backendLifecycle.ts index bbc9d8731..aadb27665 100644 --- a/frontend/src/utils/backendLifecycle.ts +++ b/electron/src/shared/utils/backendLifecycle.ts @@ -38,11 +38,6 @@ export interface BackendLifecycle { message: string | null; } -function inTauri(): boolean { - const w = window as unknown as Record | undefined; - return typeof window !== 'undefined' && !!(w?.__TAURI__ || w?.__TAURI_INTERNALS__); -} - /** Map the shell's BootstrapStage tag to the coarse lifecycle answer the * transport layer needs. Pure + exported for unit tests. */ export function classifyBootstrapStage(stage: string | null | undefined): BackendLifecycleStage { @@ -75,22 +70,20 @@ export function _toLifecycle(res: { stage?: string; message?: unknown } | null): * (`last_bootstrap_failure`, #1177). A precise diagnosis outranks silence, * and the retained copy is the only place it still exists. */ export async function backendLifecycleStage(): Promise { - if (!inTauri()) return { stage: 'unknown', message: null }; + if (typeof window === 'undefined' || !window.voicestudio) { + return { stage: 'unknown', message: null }; + } try { - const { invoke } = await import('@tauri-apps/api/core'); - const res = (await invoke('bootstrap_status')) as { stage?: string; message?: unknown } | null; - const lifecycle = _toLifecycle(res); - if (lifecycle.stage === 'failed' && !lifecycle.message) { - try { - const retained = (await invoke('last_bootstrap_failure')) as string | null; - if (typeof retained === 'string' && retained.trim()) { - return { stage: 'failed', message: retained.trim() }; - } - } catch { - /* older shell / IPC gone — the stage alone still ends the retry loop */ - } + const status = await window.voicestudio.backend.getStatus(); + if (status.stage === 'ready') return { stage: 'ready', message: null }; + if (['failed', 'crashed', 'port_in_use'].includes(status.stage)) { + const detail = status.message?.trim() || status.logTail.at(-1)?.trim() || null; + return { stage: 'failed', message: detail }; } - return lifecycle; + if (['setup_required', 'installing', 'attaching', 'starting'].includes(status.stage)) { + return { stage: 'starting', message: null }; + } + return { stage: 'unknown', message: null }; } catch { return { stage: 'unknown', message: null }; } diff --git a/frontend/src/utils/breadcrumbs.d.ts b/electron/src/shared/utils/breadcrumbs.d.ts similarity index 100% rename from frontend/src/utils/breadcrumbs.d.ts rename to electron/src/shared/utils/breadcrumbs.d.ts diff --git a/frontend/src/utils/breadcrumbs.js b/electron/src/shared/utils/breadcrumbs.js similarity index 100% rename from frontend/src/utils/breadcrumbs.js rename to electron/src/shared/utils/breadcrumbs.js diff --git a/frontend/src/utils/breadcrumbs.test.js b/electron/src/shared/utils/breadcrumbs.test.js similarity index 100% rename from frontend/src/utils/breadcrumbs.test.js rename to electron/src/shared/utils/breadcrumbs.test.js diff --git a/frontend/src/utils/bugReport.js b/electron/src/shared/utils/bugReport.js similarity index 100% rename from frontend/src/utils/bugReport.js rename to electron/src/shared/utils/bugReport.js diff --git a/frontend/src/utils/bugReport.test.js b/electron/src/shared/utils/bugReport.test.js similarity index 100% rename from frontend/src/utils/bugReport.test.js rename to electron/src/shared/utils/bugReport.test.js diff --git a/frontend/src/utils/bugReportDocument.d.ts b/electron/src/shared/utils/bugReportDocument.d.ts similarity index 100% rename from frontend/src/utils/bugReportDocument.d.ts rename to electron/src/shared/utils/bugReportDocument.d.ts diff --git a/frontend/src/utils/bugReportDocument.js b/electron/src/shared/utils/bugReportDocument.js similarity index 100% rename from frontend/src/utils/bugReportDocument.js rename to electron/src/shared/utils/bugReportDocument.js diff --git a/frontend/src/utils/bugReportDocument.test.js b/electron/src/shared/utils/bugReportDocument.test.js similarity index 100% rename from frontend/src/utils/bugReportDocument.test.js rename to electron/src/shared/utils/bugReportDocument.test.js diff --git a/frontend/src/utils/bugReportGate.test.js b/electron/src/shared/utils/bugReportGate.test.js similarity index 100% rename from frontend/src/utils/bugReportGate.test.js rename to electron/src/shared/utils/bugReportGate.test.js diff --git a/frontend/src/utils/captureProtocol.d.ts b/electron/src/shared/utils/captureProtocol.d.ts similarity index 100% rename from frontend/src/utils/captureProtocol.d.ts rename to electron/src/shared/utils/captureProtocol.d.ts diff --git a/frontend/src/utils/captureProtocol.js b/electron/src/shared/utils/captureProtocol.js similarity index 100% rename from frontend/src/utils/captureProtocol.js rename to electron/src/shared/utils/captureProtocol.js diff --git a/frontend/src/utils/channelControl.js b/electron/src/shared/utils/channelControl.js similarity index 94% rename from frontend/src/utils/channelControl.js rename to electron/src/shared/utils/channelControl.js index 174d3e44a..fa6a9efa0 100644 --- a/frontend/src/utils/channelControl.js +++ b/electron/src/shared/utils/channelControl.js @@ -1,4 +1,4 @@ -// frontend/src/utils/channelControl.js +// electron/src/shared/utils/channelControl.js import { isTauri } from './updater'; import { normalizeChannel } from './updateChannel'; diff --git a/frontend/src/utils/coalescedJsonStorage.test.ts b/electron/src/shared/utils/coalescedJsonStorage.test.ts similarity index 100% rename from frontend/src/utils/coalescedJsonStorage.test.ts rename to electron/src/shared/utils/coalescedJsonStorage.test.ts diff --git a/frontend/src/utils/coalescedJsonStorage.ts b/electron/src/shared/utils/coalescedJsonStorage.ts similarity index 100% rename from frontend/src/utils/coalescedJsonStorage.ts rename to electron/src/shared/utils/coalescedJsonStorage.ts diff --git a/frontend/src/utils/consoleBuffer.d.ts b/electron/src/shared/utils/consoleBuffer.d.ts similarity index 100% rename from frontend/src/utils/consoleBuffer.d.ts rename to electron/src/shared/utils/consoleBuffer.d.ts diff --git a/frontend/src/utils/consoleBuffer.js b/electron/src/shared/utils/consoleBuffer.js similarity index 100% rename from frontend/src/utils/consoleBuffer.js rename to electron/src/shared/utils/consoleBuffer.js diff --git a/frontend/src/utils/consoleBuffer.test.js b/electron/src/shared/utils/consoleBuffer.test.js similarity index 100% rename from frontend/src/utils/consoleBuffer.test.js rename to electron/src/shared/utils/consoleBuffer.test.js diff --git a/frontend/src/utils/constants.d.ts b/electron/src/shared/utils/constants.d.ts similarity index 100% rename from frontend/src/utils/constants.d.ts rename to electron/src/shared/utils/constants.d.ts diff --git a/frontend/src/utils/constants.js b/electron/src/shared/utils/constants.js similarity index 100% rename from frontend/src/utils/constants.js rename to electron/src/shared/utils/constants.js diff --git a/frontend/src/utils/contactLinks.d.ts b/electron/src/shared/utils/contactLinks.d.ts similarity index 100% rename from frontend/src/utils/contactLinks.d.ts rename to electron/src/shared/utils/contactLinks.d.ts diff --git a/frontend/src/utils/contactLinks.js b/electron/src/shared/utils/contactLinks.js similarity index 100% rename from frontend/src/utils/contactLinks.js rename to electron/src/shared/utils/contactLinks.js diff --git a/frontend/src/utils/cookieExport.ts b/electron/src/shared/utils/cookieExport.ts similarity index 100% rename from frontend/src/utils/cookieExport.ts rename to electron/src/shared/utils/cookieExport.ts diff --git a/frontend/src/utils/copyText.js b/electron/src/shared/utils/copyText.js similarity index 100% rename from frontend/src/utils/copyText.js rename to electron/src/shared/utils/copyText.js diff --git a/frontend/src/utils/copyText.test.js b/electron/src/shared/utils/copyText.test.js similarity index 100% rename from frontend/src/utils/copyText.test.js rename to electron/src/shared/utils/copyText.test.js diff --git a/frontend/src/utils/crashReport.d.ts b/electron/src/shared/utils/crashReport.d.ts similarity index 100% rename from frontend/src/utils/crashReport.d.ts rename to electron/src/shared/utils/crashReport.d.ts diff --git a/frontend/src/utils/crashReport.js b/electron/src/shared/utils/crashReport.js similarity index 100% rename from frontend/src/utils/crashReport.js rename to electron/src/shared/utils/crashReport.js diff --git a/frontend/src/utils/deploymentMode.ts b/electron/src/shared/utils/deploymentMode.ts similarity index 100% rename from frontend/src/utils/deploymentMode.ts rename to electron/src/shared/utils/deploymentMode.ts diff --git a/frontend/src/utils/dialog.js b/electron/src/shared/utils/dialog.js similarity index 100% rename from frontend/src/utils/dialog.js rename to electron/src/shared/utils/dialog.js diff --git a/frontend/src/utils/dictationCapture.js b/electron/src/shared/utils/dictationCapture.js similarity index 100% rename from frontend/src/utils/dictationCapture.js rename to electron/src/shared/utils/dictationCapture.js diff --git a/frontend/src/utils/dictationCapture.test.js b/electron/src/shared/utils/dictationCapture.test.js similarity index 100% rename from frontend/src/utils/dictationCapture.test.js rename to electron/src/shared/utils/dictationCapture.test.js diff --git a/frontend/src/utils/dictationNotice.jsx b/electron/src/shared/utils/dictationNotice.jsx similarity index 100% rename from frontend/src/utils/dictationNotice.jsx rename to electron/src/shared/utils/dictationNotice.jsx diff --git a/frontend/src/utils/dictationNotice.test.jsx b/electron/src/shared/utils/dictationNotice.test.jsx similarity index 100% rename from frontend/src/utils/dictationNotice.test.jsx rename to electron/src/shared/utils/dictationNotice.test.jsx diff --git a/frontend/src/utils/dictationScripts.d.ts b/electron/src/shared/utils/dictationScripts.d.ts similarity index 100% rename from frontend/src/utils/dictationScripts.d.ts rename to electron/src/shared/utils/dictationScripts.d.ts diff --git a/frontend/src/utils/dictationScripts.js b/electron/src/shared/utils/dictationScripts.js similarity index 100% rename from frontend/src/utils/dictationScripts.js rename to electron/src/shared/utils/dictationScripts.js diff --git a/frontend/src/utils/dictationShortcut.d.ts b/electron/src/shared/utils/dictationShortcut.d.ts similarity index 100% rename from frontend/src/utils/dictationShortcut.d.ts rename to electron/src/shared/utils/dictationShortcut.d.ts diff --git a/frontend/src/utils/dictationShortcut.js b/electron/src/shared/utils/dictationShortcut.js similarity index 100% rename from frontend/src/utils/dictationShortcut.js rename to electron/src/shared/utils/dictationShortcut.js diff --git a/frontend/src/utils/dictationShortcut.test.js b/electron/src/shared/utils/dictationShortcut.test.js similarity index 100% rename from frontend/src/utils/dictationShortcut.test.js rename to electron/src/shared/utils/dictationShortcut.test.js diff --git a/frontend/src/utils/donateLinks.d.ts b/electron/src/shared/utils/donateLinks.d.ts similarity index 100% rename from frontend/src/utils/donateLinks.d.ts rename to electron/src/shared/utils/donateLinks.d.ts diff --git a/frontend/src/utils/donateLinks.js b/electron/src/shared/utils/donateLinks.js similarity index 100% rename from frontend/src/utils/donateLinks.js rename to electron/src/shared/utils/donateLinks.js diff --git a/frontend/src/utils/donationMoments.js b/electron/src/shared/utils/donationMoments.js similarity index 100% rename from frontend/src/utils/donationMoments.js rename to electron/src/shared/utils/donationMoments.js diff --git a/frontend/src/utils/donationMoments.test.js b/electron/src/shared/utils/donationMoments.test.js similarity index 100% rename from frontend/src/utils/donationMoments.test.js rename to electron/src/shared/utils/donationMoments.test.js diff --git a/frontend/src/utils/download.js b/electron/src/shared/utils/download.js similarity index 100% rename from frontend/src/utils/download.js rename to electron/src/shared/utils/download.js diff --git a/frontend/src/utils/download.test.js b/electron/src/shared/utils/download.test.js similarity index 100% rename from frontend/src/utils/download.test.js rename to electron/src/shared/utils/download.test.js diff --git a/frontend/src/utils/dubDefaultTrack.js b/electron/src/shared/utils/dubDefaultTrack.js similarity index 100% rename from frontend/src/utils/dubDefaultTrack.js rename to electron/src/shared/utils/dubDefaultTrack.js diff --git a/frontend/src/utils/dubToStory.d.ts b/electron/src/shared/utils/dubToStory.d.ts similarity index 100% rename from frontend/src/utils/dubToStory.d.ts rename to electron/src/shared/utils/dubToStory.d.ts diff --git a/frontend/src/utils/dubToStory.js b/electron/src/shared/utils/dubToStory.js similarity index 100% rename from frontend/src/utils/dubToStory.js rename to electron/src/shared/utils/dubToStory.js diff --git a/frontend/src/utils/dubToStory.test.js b/electron/src/shared/utils/dubToStory.test.js similarity index 100% rename from frontend/src/utils/dubToStory.test.js rename to electron/src/shared/utils/dubToStory.test.js diff --git a/frontend/src/utils/engineDisplayName.js b/electron/src/shared/utils/engineDisplayName.js similarity index 100% rename from frontend/src/utils/engineDisplayName.js rename to electron/src/shared/utils/engineDisplayName.js diff --git a/frontend/src/utils/engineDisplayName.test.js b/electron/src/shared/utils/engineDisplayName.test.js similarity index 100% rename from frontend/src/utils/engineDisplayName.test.js rename to electron/src/shared/utils/engineDisplayName.test.js diff --git a/frontend/src/utils/engineSelectToast.js b/electron/src/shared/utils/engineSelectToast.js similarity index 100% rename from frontend/src/utils/engineSelectToast.js rename to electron/src/shared/utils/engineSelectToast.js diff --git a/frontend/src/utils/errorDocsMap.test.ts b/electron/src/shared/utils/errorDocsMap.test.ts similarity index 100% rename from frontend/src/utils/errorDocsMap.test.ts rename to electron/src/shared/utils/errorDocsMap.test.ts diff --git a/frontend/src/utils/errorDocsMap.ts b/electron/src/shared/utils/errorDocsMap.ts similarity index 100% rename from frontend/src/utils/errorDocsMap.ts rename to electron/src/shared/utils/errorDocsMap.ts diff --git a/frontend/src/utils/errorToast.jsx b/electron/src/shared/utils/errorToast.jsx similarity index 100% rename from frontend/src/utils/errorToast.jsx rename to electron/src/shared/utils/errorToast.jsx diff --git a/frontend/src/utils/firstSound.js b/electron/src/shared/utils/firstSound.js similarity index 100% rename from frontend/src/utils/firstSound.js rename to electron/src/shared/utils/firstSound.js diff --git a/frontend/src/utils/firstSound.json b/electron/src/shared/utils/firstSound.json similarity index 100% rename from frontend/src/utils/firstSound.json rename to electron/src/shared/utils/firstSound.json diff --git a/frontend/src/utils/foreignErrors.d.ts b/electron/src/shared/utils/foreignErrors.d.ts similarity index 100% rename from frontend/src/utils/foreignErrors.d.ts rename to electron/src/shared/utils/foreignErrors.d.ts diff --git a/frontend/src/utils/foreignErrors.js b/electron/src/shared/utils/foreignErrors.js similarity index 100% rename from frontend/src/utils/foreignErrors.js rename to electron/src/shared/utils/foreignErrors.js diff --git a/frontend/src/utils/format.js b/electron/src/shared/utils/format.js similarity index 100% rename from frontend/src/utils/format.js rename to electron/src/shared/utils/format.js diff --git a/frontend/src/utils/generatePreflight.js b/electron/src/shared/utils/generatePreflight.js similarity index 100% rename from frontend/src/utils/generatePreflight.js rename to electron/src/shared/utils/generatePreflight.js diff --git a/frontend/src/utils/generationFailureMessage.test.ts b/electron/src/shared/utils/generationFailureMessage.test.ts similarity index 100% rename from frontend/src/utils/generationFailureMessage.test.ts rename to electron/src/shared/utils/generationFailureMessage.test.ts diff --git a/frontend/src/utils/generationFailureMessage.ts b/electron/src/shared/utils/generationFailureMessage.ts similarity index 100% rename from frontend/src/utils/generationFailureMessage.ts rename to electron/src/shared/utils/generationFailureMessage.ts diff --git a/frontend/src/utils/globalErrorHandlers.js b/electron/src/shared/utils/globalErrorHandlers.js similarity index 100% rename from frontend/src/utils/globalErrorHandlers.js rename to electron/src/shared/utils/globalErrorHandlers.js diff --git a/frontend/src/utils/globalErrorHandlers.test.js b/electron/src/shared/utils/globalErrorHandlers.test.js similarity index 100% rename from frontend/src/utils/globalErrorHandlers.test.js rename to electron/src/shared/utils/globalErrorHandlers.test.js diff --git a/frontend/src/utils/importStory.d.ts b/electron/src/shared/utils/importStory.d.ts similarity index 100% rename from frontend/src/utils/importStory.d.ts rename to electron/src/shared/utils/importStory.d.ts diff --git a/frontend/src/utils/importStory.js b/electron/src/shared/utils/importStory.js similarity index 100% rename from frontend/src/utils/importStory.js rename to electron/src/shared/utils/importStory.js diff --git a/frontend/src/utils/importStory.test.js b/electron/src/shared/utils/importStory.test.js similarity index 100% rename from frontend/src/utils/importStory.test.js rename to electron/src/shared/utils/importStory.test.js diff --git a/frontend/src/utils/indexedDbLongformStore.test.ts b/electron/src/shared/utils/indexedDbLongformStore.test.ts similarity index 100% rename from frontend/src/utils/indexedDbLongformStore.test.ts rename to electron/src/shared/utils/indexedDbLongformStore.test.ts diff --git a/frontend/src/utils/indexedDbLongformStore.ts b/electron/src/shared/utils/indexedDbLongformStore.ts similarity index 100% rename from frontend/src/utils/indexedDbLongformStore.ts rename to electron/src/shared/utils/indexedDbLongformStore.ts diff --git a/frontend/src/utils/initialLoadRetry.js b/electron/src/shared/utils/initialLoadRetry.js similarity index 100% rename from frontend/src/utils/initialLoadRetry.js rename to electron/src/shared/utils/initialLoadRetry.js diff --git a/frontend/src/utils/languageRejection.ts b/electron/src/shared/utils/languageRejection.ts similarity index 100% rename from frontend/src/utils/languageRejection.ts rename to electron/src/shared/utils/languageRejection.ts diff --git a/frontend/src/utils/languages.d.ts b/electron/src/shared/utils/languages.d.ts similarity index 100% rename from frontend/src/utils/languages.d.ts rename to electron/src/shared/utils/languages.d.ts diff --git a/frontend/src/utils/languages.js b/electron/src/shared/utils/languages.js similarity index 100% rename from frontend/src/utils/languages.js rename to electron/src/shared/utils/languages.js diff --git a/frontend/src/utils/logSafe.js b/electron/src/shared/utils/logSafe.js similarity index 100% rename from frontend/src/utils/logSafe.js rename to electron/src/shared/utils/logSafe.js diff --git a/frontend/src/utils/logSafe.test.js b/electron/src/shared/utils/logSafe.test.js similarity index 100% rename from frontend/src/utils/logSafe.test.js rename to electron/src/shared/utils/logSafe.test.js diff --git a/frontend/src/utils/longformOverrides.d.ts b/electron/src/shared/utils/longformOverrides.d.ts similarity index 100% rename from frontend/src/utils/longformOverrides.d.ts rename to electron/src/shared/utils/longformOverrides.d.ts diff --git a/frontend/src/utils/longformOverrides.js b/electron/src/shared/utils/longformOverrides.js similarity index 100% rename from frontend/src/utils/longformOverrides.js rename to electron/src/shared/utils/longformOverrides.js diff --git a/frontend/src/utils/longformParser.js b/electron/src/shared/utils/longformParser.js similarity index 98% rename from frontend/src/utils/longformParser.js rename to electron/src/shared/utils/longformParser.js index 9388bd1fb..20bcf4823 100644 --- a/frontend/src/utils/longformParser.js +++ b/electron/src/shared/utils/longformParser.js @@ -4,7 +4,7 @@ * * Byte-for-byte mirror of the Python parser, verified by the shared golden * corpus tests/fixtures/longform_parser_cases.json (asserted in both - * tests/test_longform_parser.py and frontend/src/test/longformParser.test.js). + * tests/test_longform_parser.py and electron/src/shared/test/longformParser.test.js). * Do not "improve" one side without the other — the corpus will fail. * * Grammar precedence (outer→inner): # chapter → [voice:] → [pause] → SSML-lite. diff --git a/frontend/src/utils/longformPersistence.test.ts b/electron/src/shared/utils/longformPersistence.test.ts similarity index 100% rename from frontend/src/utils/longformPersistence.test.ts rename to electron/src/shared/utils/longformPersistence.test.ts diff --git a/frontend/src/utils/longformPersistence.ts b/electron/src/shared/utils/longformPersistence.ts similarity index 100% rename from frontend/src/utils/longformPersistence.ts rename to electron/src/shared/utils/longformPersistence.ts diff --git a/frontend/src/utils/longformStream.d.ts b/electron/src/shared/utils/longformStream.d.ts similarity index 100% rename from frontend/src/utils/longformStream.d.ts rename to electron/src/shared/utils/longformStream.d.ts diff --git a/frontend/src/utils/longformStream.js b/electron/src/shared/utils/longformStream.js similarity index 100% rename from frontend/src/utils/longformStream.js rename to electron/src/shared/utils/longformStream.js diff --git a/frontend/src/utils/markdownLite.d.ts b/electron/src/shared/utils/markdownLite.d.ts similarity index 100% rename from frontend/src/utils/markdownLite.d.ts rename to electron/src/shared/utils/markdownLite.d.ts diff --git a/frontend/src/utils/markdownLite.js b/electron/src/shared/utils/markdownLite.js similarity index 100% rename from frontend/src/utils/markdownLite.js rename to electron/src/shared/utils/markdownLite.js diff --git a/frontend/src/utils/markdownLite.test.js b/electron/src/shared/utils/markdownLite.test.js similarity index 100% rename from frontend/src/utils/markdownLite.test.js rename to electron/src/shared/utils/markdownLite.test.js diff --git a/frontend/src/utils/media.js b/electron/src/shared/utils/media.js similarity index 100% rename from frontend/src/utils/media.js rename to electron/src/shared/utils/media.js diff --git a/frontend/src/utils/mediaDownload.js b/electron/src/shared/utils/mediaDownload.js similarity index 100% rename from frontend/src/utils/mediaDownload.js rename to electron/src/shared/utils/mediaDownload.js diff --git a/frontend/src/utils/mediaDownload.test.js b/electron/src/shared/utils/mediaDownload.test.js similarity index 100% rename from frontend/src/utils/mediaDownload.test.js rename to electron/src/shared/utils/mediaDownload.test.js diff --git a/frontend/src/utils/mediaRecorder.js b/electron/src/shared/utils/mediaRecorder.js similarity index 100% rename from frontend/src/utils/mediaRecorder.js rename to electron/src/shared/utils/mediaRecorder.js diff --git a/frontend/src/utils/mediaRecorder.test.js b/electron/src/shared/utils/mediaRecorder.test.js similarity index 100% rename from frontend/src/utils/mediaRecorder.test.js rename to electron/src/shared/utils/mediaRecorder.test.js diff --git a/frontend/src/utils/micDeniedToast.jsx b/electron/src/shared/utils/micDeniedToast.jsx similarity index 100% rename from frontend/src/utils/micDeniedToast.jsx rename to electron/src/shared/utils/micDeniedToast.jsx diff --git a/frontend/src/utils/micError.js b/electron/src/shared/utils/micError.js similarity index 100% rename from frontend/src/utils/micError.js rename to electron/src/shared/utils/micError.js diff --git a/frontend/src/utils/micError.test.js b/electron/src/shared/utils/micError.test.js similarity index 100% rename from frontend/src/utils/micError.test.js rename to electron/src/shared/utils/micError.test.js diff --git a/frontend/src/utils/modelNotDownloaded.jsx b/electron/src/shared/utils/modelNotDownloaded.jsx similarity index 100% rename from frontend/src/utils/modelNotDownloaded.jsx rename to electron/src/shared/utils/modelNotDownloaded.jsx diff --git a/frontend/src/utils/multiLang.d.ts b/electron/src/shared/utils/multiLang.d.ts similarity index 100% rename from frontend/src/utils/multiLang.d.ts rename to electron/src/shared/utils/multiLang.d.ts diff --git a/frontend/src/utils/multiLang.js b/electron/src/shared/utils/multiLang.js similarity index 100% rename from frontend/src/utils/multiLang.js rename to electron/src/shared/utils/multiLang.js diff --git a/frontend/src/utils/multiLang.test.js b/electron/src/shared/utils/multiLang.test.js similarity index 100% rename from frontend/src/utils/multiLang.test.js rename to electron/src/shared/utils/multiLang.test.js diff --git a/frontend/src/utils/nativeExit.test.ts b/electron/src/shared/utils/nativeExit.test.ts similarity index 100% rename from frontend/src/utils/nativeExit.test.ts rename to electron/src/shared/utils/nativeExit.test.ts diff --git a/frontend/src/utils/nativeExit.ts b/electron/src/shared/utils/nativeExit.ts similarity index 100% rename from frontend/src/utils/nativeExit.ts rename to electron/src/shared/utils/nativeExit.ts diff --git a/frontend/src/utils/networkPreferences.d.ts b/electron/src/shared/utils/networkPreferences.d.ts similarity index 100% rename from frontend/src/utils/networkPreferences.d.ts rename to electron/src/shared/utils/networkPreferences.d.ts diff --git a/frontend/src/utils/networkPreferences.js b/electron/src/shared/utils/networkPreferences.js similarity index 100% rename from frontend/src/utils/networkPreferences.js rename to electron/src/shared/utils/networkPreferences.js diff --git a/frontend/src/utils/omniUiSchema.js b/electron/src/shared/utils/omniUiSchema.js similarity index 100% rename from frontend/src/utils/omniUiSchema.js rename to electron/src/shared/utils/omniUiSchema.js diff --git a/frontend/src/utils/parseScript.js b/electron/src/shared/utils/parseScript.js similarity index 100% rename from frontend/src/utils/parseScript.js rename to electron/src/shared/utils/parseScript.js diff --git a/frontend/src/utils/parseScript.test.js b/electron/src/shared/utils/parseScript.test.js similarity index 100% rename from frontend/src/utils/parseScript.test.js rename to electron/src/shared/utils/parseScript.test.js diff --git a/frontend/src/utils/pasteTranslations.d.ts b/electron/src/shared/utils/pasteTranslations.d.ts similarity index 100% rename from frontend/src/utils/pasteTranslations.d.ts rename to electron/src/shared/utils/pasteTranslations.d.ts diff --git a/frontend/src/utils/pasteTranslations.js b/electron/src/shared/utils/pasteTranslations.js similarity index 100% rename from frontend/src/utils/pasteTranslations.js rename to electron/src/shared/utils/pasteTranslations.js diff --git a/frontend/src/utils/permissions.js b/electron/src/shared/utils/permissions.js similarity index 100% rename from frontend/src/utils/permissions.js rename to electron/src/shared/utils/permissions.js diff --git a/frontend/src/utils/permissions.test.js b/electron/src/shared/utils/permissions.test.js similarity index 100% rename from frontend/src/utils/permissions.test.js rename to electron/src/shared/utils/permissions.test.js diff --git a/frontend/src/utils/persistenceLifecycle.test.ts b/electron/src/shared/utils/persistenceLifecycle.test.ts similarity index 100% rename from frontend/src/utils/persistenceLifecycle.test.ts rename to electron/src/shared/utils/persistenceLifecycle.test.ts diff --git a/frontend/src/utils/persistenceLifecycle.ts b/electron/src/shared/utils/persistenceLifecycle.ts similarity index 91% rename from frontend/src/utils/persistenceLifecycle.ts rename to electron/src/shared/utils/persistenceLifecycle.ts index 6cb259ca9..437b7467f 100644 --- a/frontend/src/utils/persistenceLifecycle.ts +++ b/electron/src/shared/utils/persistenceLifecycle.ts @@ -110,26 +110,22 @@ export function reloadAfterApplicationPersistence( export async function installDesktopPersistenceExitHandshake( dependencies: DesktopExitHandshakeDependencies = {}, ): Promise { - const desktop = - dependencies.desktop ?? (typeof window !== 'undefined' && '__TAURI_INTERNALS__' in window); + const desktop = dependencies.desktop ?? (typeof window !== 'undefined' && !!window.voicestudio); if (!desktop) return () => {}; const warn = dependencies.warn ?? defaultWarn; - let listen = dependencies.listen; - if (!listen) { - try { - listen = (await import('@tauri-apps/api/event')).listen; - } catch (error) { - warn('[persistence] native exit listener could not load', error); - return () => {}; - } - } - const confirm = - dependencies.confirm ?? - (async () => { - const { invoke } = await import('@tauri-apps/api/core'); - await invoke(CONFIRM_PERSISTENCE_FLUSH_COMMAND); + if (!dependencies.listen && !dependencies.confirm && window.voicestudio) { + return window.voicestudio.app.onPersistenceFlush(async () => { + try { + await flushApplicationPersistence(dependencies); + } catch (error) { + warn('[persistence] orderly exit flush failed', error); + } }); + } + let listen = dependencies.listen; + if (!listen) return () => {}; + const confirm = dependencies.confirm ?? (async () => {}); let completion: Promise | null = null; try { diff --git a/frontend/src/utils/playback.js b/electron/src/shared/utils/playback.js similarity index 100% rename from frontend/src/utils/playback.js rename to electron/src/shared/utils/playback.js diff --git a/frontend/src/utils/playback.test.js b/electron/src/shared/utils/playback.test.js similarity index 100% rename from frontend/src/utils/playback.test.js rename to electron/src/shared/utils/playback.test.js diff --git a/frontend/src/utils/prefKeys.js b/electron/src/shared/utils/prefKeys.js similarity index 100% rename from frontend/src/utils/prefKeys.js rename to electron/src/shared/utils/prefKeys.js diff --git a/frontend/src/utils/prefKeys.test.js b/electron/src/shared/utils/prefKeys.test.js similarity index 100% rename from frontend/src/utils/prefKeys.test.js rename to electron/src/shared/utils/prefKeys.test.js diff --git a/frontend/src/utils/projectState.js b/electron/src/shared/utils/projectState.js similarity index 100% rename from frontend/src/utils/projectState.js rename to electron/src/shared/utils/projectState.js diff --git a/frontend/src/utils/readTextFile.d.ts b/electron/src/shared/utils/readTextFile.d.ts similarity index 100% rename from frontend/src/utils/readTextFile.d.ts rename to electron/src/shared/utils/readTextFile.d.ts diff --git a/frontend/src/utils/readTextFile.js b/electron/src/shared/utils/readTextFile.js similarity index 100% rename from frontend/src/utils/readTextFile.js rename to electron/src/shared/utils/readTextFile.js diff --git a/frontend/src/utils/relativeTime.js b/electron/src/shared/utils/relativeTime.js similarity index 100% rename from frontend/src/utils/relativeTime.js rename to electron/src/shared/utils/relativeTime.js diff --git a/frontend/src/utils/relativeTime.test.js b/electron/src/shared/utils/relativeTime.test.js similarity index 100% rename from frontend/src/utils/relativeTime.test.js rename to electron/src/shared/utils/relativeTime.test.js diff --git a/frontend/src/utils/remoteBackendProbe.test.ts b/electron/src/shared/utils/remoteBackendProbe.test.ts similarity index 100% rename from frontend/src/utils/remoteBackendProbe.test.ts rename to electron/src/shared/utils/remoteBackendProbe.test.ts diff --git a/frontend/src/utils/remoteBackendProbe.ts b/electron/src/shared/utils/remoteBackendProbe.ts similarity index 100% rename from frontend/src/utils/remoteBackendProbe.ts rename to electron/src/shared/utils/remoteBackendProbe.ts diff --git a/frontend/src/utils/routingNotice.js b/electron/src/shared/utils/routingNotice.js similarity index 100% rename from frontend/src/utils/routingNotice.js rename to electron/src/shared/utils/routingNotice.js diff --git a/frontend/src/utils/runCrashRecord.ts b/electron/src/shared/utils/runCrashRecord.ts similarity index 100% rename from frontend/src/utils/runCrashRecord.ts rename to electron/src/shared/utils/runCrashRecord.ts diff --git a/frontend/src/utils/scriptToStory.js b/electron/src/shared/utils/scriptToStory.js similarity index 100% rename from frontend/src/utils/scriptToStory.js rename to electron/src/shared/utils/scriptToStory.js diff --git a/frontend/src/utils/scriptToStory.test.js b/electron/src/shared/utils/scriptToStory.test.js similarity index 100% rename from frontend/src/utils/scriptToStory.test.js rename to electron/src/shared/utils/scriptToStory.test.js diff --git a/frontend/src/utils/scrub.d.ts b/electron/src/shared/utils/scrub.d.ts similarity index 100% rename from frontend/src/utils/scrub.d.ts rename to electron/src/shared/utils/scrub.d.ts diff --git a/frontend/src/utils/scrub.js b/electron/src/shared/utils/scrub.js similarity index 100% rename from frontend/src/utils/scrub.js rename to electron/src/shared/utils/scrub.js diff --git a/frontend/src/utils/seed.d.ts b/electron/src/shared/utils/seed.d.ts similarity index 100% rename from frontend/src/utils/seed.d.ts rename to electron/src/shared/utils/seed.d.ts diff --git a/frontend/src/utils/seed.js b/electron/src/shared/utils/seed.js similarity index 100% rename from frontend/src/utils/seed.js rename to electron/src/shared/utils/seed.js diff --git a/frontend/src/utils/segmentParts.d.ts b/electron/src/shared/utils/segmentParts.d.ts similarity index 100% rename from frontend/src/utils/segmentParts.d.ts rename to electron/src/shared/utils/segmentParts.d.ts diff --git a/frontend/src/utils/segmentParts.js b/electron/src/shared/utils/segmentParts.js similarity index 100% rename from frontend/src/utils/segmentParts.js rename to electron/src/shared/utils/segmentParts.js diff --git a/frontend/src/utils/segmentParts.test.js b/electron/src/shared/utils/segmentParts.test.js similarity index 100% rename from frontend/src/utils/segmentParts.test.js rename to electron/src/shared/utils/segmentParts.test.js diff --git a/frontend/src/utils/segments.d.ts b/electron/src/shared/utils/segments.d.ts similarity index 100% rename from frontend/src/utils/segments.d.ts rename to electron/src/shared/utils/segments.d.ts diff --git a/frontend/src/utils/segments.js b/electron/src/shared/utils/segments.js similarity index 100% rename from frontend/src/utils/segments.js rename to electron/src/shared/utils/segments.js diff --git a/frontend/src/utils/shortcutAccelerator.d.ts b/electron/src/shared/utils/shortcutAccelerator.d.ts similarity index 100% rename from frontend/src/utils/shortcutAccelerator.d.ts rename to electron/src/shared/utils/shortcutAccelerator.d.ts diff --git a/frontend/src/utils/shortcutAccelerator.js b/electron/src/shared/utils/shortcutAccelerator.js similarity index 100% rename from frontend/src/utils/shortcutAccelerator.js rename to electron/src/shared/utils/shortcutAccelerator.js diff --git a/frontend/src/utils/splashWatchdog.js b/electron/src/shared/utils/splashWatchdog.js similarity index 100% rename from frontend/src/utils/splashWatchdog.js rename to electron/src/shared/utils/splashWatchdog.js diff --git a/frontend/src/utils/splitStoryText.d.ts b/electron/src/shared/utils/splitStoryText.d.ts similarity index 100% rename from frontend/src/utils/splitStoryText.d.ts rename to electron/src/shared/utils/splitStoryText.d.ts diff --git a/frontend/src/utils/splitStoryText.js b/electron/src/shared/utils/splitStoryText.js similarity index 100% rename from frontend/src/utils/splitStoryText.js rename to electron/src/shared/utils/splitStoryText.js diff --git a/frontend/src/utils/sseParse.d.ts b/electron/src/shared/utils/sseParse.d.ts similarity index 100% rename from frontend/src/utils/sseParse.d.ts rename to electron/src/shared/utils/sseParse.d.ts diff --git a/frontend/src/utils/sseParse.js b/electron/src/shared/utils/sseParse.js similarity index 100% rename from frontend/src/utils/sseParse.js rename to electron/src/shared/utils/sseParse.js diff --git a/frontend/src/utils/ssmlLite.js b/electron/src/shared/utils/ssmlLite.js similarity index 100% rename from frontend/src/utils/ssmlLite.js rename to electron/src/shared/utils/ssmlLite.js diff --git a/frontend/src/utils/staleBuild.js b/electron/src/shared/utils/staleBuild.js similarity index 100% rename from frontend/src/utils/staleBuild.js rename to electron/src/shared/utils/staleBuild.js diff --git a/frontend/src/utils/staleBuild.test.js b/electron/src/shared/utils/staleBuild.test.js similarity index 100% rename from frontend/src/utils/staleBuild.test.js rename to electron/src/shared/utils/staleBuild.test.js diff --git a/frontend/src/utils/storageWarnings.d.ts b/electron/src/shared/utils/storageWarnings.d.ts similarity index 100% rename from frontend/src/utils/storageWarnings.d.ts rename to electron/src/shared/utils/storageWarnings.d.ts diff --git a/frontend/src/utils/storageWarnings.js b/electron/src/shared/utils/storageWarnings.js similarity index 100% rename from frontend/src/utils/storageWarnings.js rename to electron/src/shared/utils/storageWarnings.js diff --git a/frontend/src/utils/storyCast.js b/electron/src/shared/utils/storyCast.js similarity index 100% rename from frontend/src/utils/storyCast.js rename to electron/src/shared/utils/storyCast.js diff --git a/frontend/src/utils/storyCast.test.js b/electron/src/shared/utils/storyCast.test.js similarity index 100% rename from frontend/src/utils/storyCast.test.js rename to electron/src/shared/utils/storyCast.test.js diff --git a/frontend/src/utils/storyExport.d.ts b/electron/src/shared/utils/storyExport.d.ts similarity index 100% rename from frontend/src/utils/storyExport.d.ts rename to electron/src/shared/utils/storyExport.d.ts diff --git a/frontend/src/utils/storyExport.js b/electron/src/shared/utils/storyExport.js similarity index 100% rename from frontend/src/utils/storyExport.js rename to electron/src/shared/utils/storyExport.js diff --git a/frontend/src/utils/storyExport.test.js b/electron/src/shared/utils/storyExport.test.js similarity index 100% rename from frontend/src/utils/storyExport.test.js rename to electron/src/shared/utils/storyExport.test.js diff --git a/frontend/src/utils/storyReorder.d.ts b/electron/src/shared/utils/storyReorder.d.ts similarity index 100% rename from frontend/src/utils/storyReorder.d.ts rename to electron/src/shared/utils/storyReorder.d.ts diff --git a/frontend/src/utils/storyReorder.js b/electron/src/shared/utils/storyReorder.js similarity index 100% rename from frontend/src/utils/storyReorder.js rename to electron/src/shared/utils/storyReorder.js diff --git a/frontend/src/utils/storyReorder.test.js b/electron/src/shared/utils/storyReorder.test.js similarity index 100% rename from frontend/src/utils/storyReorder.test.js rename to electron/src/shared/utils/storyReorder.test.js diff --git a/frontend/src/utils/storyToScript.js b/electron/src/shared/utils/storyToScript.js similarity index 100% rename from frontend/src/utils/storyToScript.js rename to electron/src/shared/utils/storyToScript.js diff --git a/frontend/src/utils/storyToScript.test.js b/electron/src/shared/utils/storyToScript.test.js similarity index 100% rename from frontend/src/utils/storyToScript.test.js rename to electron/src/shared/utils/storyToScript.test.js diff --git a/frontend/src/utils/storyToSpans.d.ts b/electron/src/shared/utils/storyToSpans.d.ts similarity index 100% rename from frontend/src/utils/storyToSpans.d.ts rename to electron/src/shared/utils/storyToSpans.d.ts diff --git a/frontend/src/utils/storyToSpans.js b/electron/src/shared/utils/storyToSpans.js similarity index 100% rename from frontend/src/utils/storyToSpans.js rename to electron/src/shared/utils/storyToSpans.js diff --git a/frontend/src/utils/storyTokens.js b/electron/src/shared/utils/storyTokens.js similarity index 100% rename from frontend/src/utils/storyTokens.js rename to electron/src/shared/utils/storyTokens.js diff --git a/frontend/src/utils/storyTokens.test.js b/electron/src/shared/utils/storyTokens.test.js similarity index 100% rename from frontend/src/utils/storyTokens.test.js rename to electron/src/shared/utils/storyTokens.test.js diff --git a/frontend/src/utils/streamingTts.js b/electron/src/shared/utils/streamingTts.js similarity index 100% rename from frontend/src/utils/streamingTts.js rename to electron/src/shared/utils/streamingTts.js diff --git a/frontend/src/utils/timeline.d.ts b/electron/src/shared/utils/timeline.d.ts similarity index 100% rename from frontend/src/utils/timeline.d.ts rename to electron/src/shared/utils/timeline.d.ts diff --git a/frontend/src/utils/timeline.js b/electron/src/shared/utils/timeline.js similarity index 100% rename from frontend/src/utils/timeline.js rename to electron/src/shared/utils/timeline.js diff --git a/frontend/src/utils/timeline.test.js b/electron/src/shared/utils/timeline.test.js similarity index 100% rename from frontend/src/utils/timeline.test.js rename to electron/src/shared/utils/timeline.test.js diff --git a/frontend/src/utils/transcriptionFormat.d.ts b/electron/src/shared/utils/transcriptionFormat.d.ts similarity index 100% rename from frontend/src/utils/transcriptionFormat.d.ts rename to electron/src/shared/utils/transcriptionFormat.d.ts diff --git a/frontend/src/utils/transcriptionFormat.js b/electron/src/shared/utils/transcriptionFormat.js similarity index 100% rename from frontend/src/utils/transcriptionFormat.js rename to electron/src/shared/utils/transcriptionFormat.js diff --git a/frontend/src/utils/transcriptionsStore.d.ts b/electron/src/shared/utils/transcriptionsStore.d.ts similarity index 100% rename from frontend/src/utils/transcriptionsStore.d.ts rename to electron/src/shared/utils/transcriptionsStore.d.ts diff --git a/frontend/src/utils/transcriptionsStore.js b/electron/src/shared/utils/transcriptionsStore.js similarity index 100% rename from frontend/src/utils/transcriptionsStore.js rename to electron/src/shared/utils/transcriptionsStore.js diff --git a/frontend/src/utils/transcriptionsStore.test.js b/electron/src/shared/utils/transcriptionsStore.test.js similarity index 100% rename from frontend/src/utils/transcriptionsStore.test.js rename to electron/src/shared/utils/transcriptionsStore.test.js diff --git a/frontend/src/utils/translationProviderFields.d.ts b/electron/src/shared/utils/translationProviderFields.d.ts similarity index 100% rename from frontend/src/utils/translationProviderFields.d.ts rename to electron/src/shared/utils/translationProviderFields.d.ts diff --git a/frontend/src/utils/translationProviderFields.js b/electron/src/shared/utils/translationProviderFields.js similarity index 100% rename from frontend/src/utils/translationProviderFields.js rename to electron/src/shared/utils/translationProviderFields.js diff --git a/frontend/src/utils/translatorPrivacy.d.ts b/electron/src/shared/utils/translatorPrivacy.d.ts similarity index 100% rename from frontend/src/utils/translatorPrivacy.d.ts rename to electron/src/shared/utils/translatorPrivacy.d.ts diff --git a/frontend/src/utils/translatorPrivacy.js b/electron/src/shared/utils/translatorPrivacy.js similarity index 100% rename from frontend/src/utils/translatorPrivacy.js rename to electron/src/shared/utils/translatorPrivacy.js diff --git a/frontend/src/utils/uiScaleEngine.js b/electron/src/shared/utils/uiScaleEngine.js similarity index 100% rename from frontend/src/utils/uiScaleEngine.js rename to electron/src/shared/utils/uiScaleEngine.js diff --git a/frontend/src/utils/uiScaleEngine.test.js b/electron/src/shared/utils/uiScaleEngine.test.js similarity index 100% rename from frontend/src/utils/uiScaleEngine.test.js rename to electron/src/shared/utils/uiScaleEngine.test.js diff --git a/frontend/src/utils/uiScaleSuggestion.js b/electron/src/shared/utils/uiScaleSuggestion.js similarity index 100% rename from frontend/src/utils/uiScaleSuggestion.js rename to electron/src/shared/utils/uiScaleSuggestion.js diff --git a/frontend/src/utils/uiScaleSuggestion.test.js b/electron/src/shared/utils/uiScaleSuggestion.test.js similarity index 100% rename from frontend/src/utils/uiScaleSuggestion.test.js rename to electron/src/shared/utils/uiScaleSuggestion.test.js diff --git a/frontend/src/utils/updateChannel.js b/electron/src/shared/utils/updateChannel.js similarity index 100% rename from frontend/src/utils/updateChannel.js rename to electron/src/shared/utils/updateChannel.js diff --git a/frontend/src/utils/updateChannel.test.ts b/electron/src/shared/utils/updateChannel.test.ts similarity index 100% rename from frontend/src/utils/updateChannel.test.ts rename to electron/src/shared/utils/updateChannel.test.ts diff --git a/frontend/src/utils/updatePresentation.js b/electron/src/shared/utils/updatePresentation.js similarity index 100% rename from frontend/src/utils/updatePresentation.js rename to electron/src/shared/utils/updatePresentation.js diff --git a/frontend/src/utils/updatePresentation.test.js b/electron/src/shared/utils/updatePresentation.test.js similarity index 100% rename from frontend/src/utils/updatePresentation.test.js rename to electron/src/shared/utils/updatePresentation.test.js diff --git a/frontend/src/utils/updater.js b/electron/src/shared/utils/updater.js similarity index 75% rename from frontend/src/utils/updater.js rename to electron/src/shared/utils/updater.js index e12a77c52..abb7cbf97 100644 --- a/frontend/src/utils/updater.js +++ b/electron/src/shared/utils/updater.js @@ -19,13 +19,12 @@ import { normalizeChannel } from './updateChannel'; import { flushApplicationPersistence } from './persistenceLifecycle'; export function isTauri() { - return typeof window !== 'undefined' && '__TAURI_INTERNALS__' in window; + return typeof window !== 'undefined' && !!window.voicestudio; } async function currentChannel() { try { - const { invoke } = await import('@tauri-apps/api/core'); - return normalizeChannel(await invoke('get_update_channel')); + return normalizeChannel((await window.voicestudio.updates.getState()).channel); } catch { return 'stable'; } @@ -48,11 +47,11 @@ export async function checkForUpdate(store) { } try { store.setUpdateChecking(); - const { invoke } = await import('@tauri-apps/api/core'); const channel = await currentChannel(); - const update = await invoke('check_update', { channel }); - if (update) { - store.setUpdateAvailable(update.version, update.notes || null); + await window.voicestudio.updates.setChannel(channel); + const update = await window.voicestudio.updates.check(); + if (update.status === 'available' && update.availableVersion) { + store.setUpdateAvailable(update.availableVersion, update.notes || null); // Announce it where the user is looking. The footer's version dot stays // as the persistent, non-intrusive marker; this is the one-time nudge. // Lazy so the toast never loads in a browser/dev build that can't update. @@ -63,7 +62,7 @@ export async function checkForUpdate(store) { // state (footer dot, Settings → Updates) is what has to survive. try { const { showUpdateToast } = await import('../components/UpdateToast'); - showUpdateToast(update.version); + showUpdateToast(update.availableVersion); } catch (e) { console.debug('Update toast failed to load (non-fatal):', e); } @@ -79,20 +78,11 @@ export async function checkForUpdate(store) { export async function installUpdate(store) { if (!isTauri()) return; - let unlisten; try { - const [{ invoke }, { listen }, { relaunch }] = await Promise.all([ - import('@tauri-apps/api/core'), - import('@tauri-apps/api/event'), - import('@tauri-apps/plugin-process'), - ]); const channel = await currentChannel(); + await window.voicestudio.updates.setChannel(channel); store.setUpdateProgress(0); - unlisten = await listen('update://progress', (ev) => { - const { downloaded = 0, total = 0 } = ev?.payload || {}; - if (total > 0) store.setUpdateProgress(Math.min(99, (downloaded / total) * 100)); - }); - await invoke('install_update', { channel }); + await window.voicestudio.updates.download(); store.setUpdateReady(); try { await flushApplicationPersistence(); @@ -101,30 +91,24 @@ export async function installUpdate(store) { // that successful state as an install error or strand the relaunch. console.warn('[persistence] installed-update flush failed', error); } - await relaunch(); + await window.voicestudio.updates.install(); } catch (e) { console.warn('Update install failed:', e); store.setUpdateError((e && e.message) || String(e) || 'Update failed'); } finally { - if (unlisten) unlisten(); + // Electron owns updater listeners and removes them with the window. } } /** Fetch the project's releases (changelog/history) via the Rust command. [] outside Tauri / on error. */ export async function listReleases(channel) { if (!isTauri()) return []; - const { invoke } = await import('@tauri-apps/api/core'); - const data = await invoke('list_releases', { channel }); + const data = await window.voicestudio.updates.listReleases(normalizeChannel(channel)); return Array.isArray(data) ? data : []; } /** Current app version via Tauri, or null outside a packaged build. */ export async function fetchAppVersion() { if (!isTauri()) return null; - try { - const { getVersion } = await import('@tauri-apps/api/app'); - return await getVersion(); - } catch { - return null; - } + return window.voicestudio.app.version; } diff --git a/frontend/src/utils/updater.test.js b/electron/src/shared/utils/updater.test.js similarity index 100% rename from frontend/src/utils/updater.test.js rename to electron/src/shared/utils/updater.test.js diff --git a/frontend/src/utils/updatesApi.js b/electron/src/shared/utils/updatesApi.js similarity index 100% rename from frontend/src/utils/updatesApi.js rename to electron/src/shared/utils/updatesApi.js diff --git a/frontend/src/utils/utils.test.js b/electron/src/shared/utils/utils.test.js similarity index 100% rename from frontend/src/utils/utils.test.js rename to electron/src/shared/utils/utils.test.js diff --git a/frontend/src/utils/voiceIcons.js b/electron/src/shared/utils/voiceIcons.js similarity index 100% rename from frontend/src/utils/voiceIcons.js rename to electron/src/shared/utils/voiceIcons.js diff --git a/frontend/src/utils/voiceInstruct.d.ts b/electron/src/shared/utils/voiceInstruct.d.ts similarity index 100% rename from frontend/src/utils/voiceInstruct.d.ts rename to electron/src/shared/utils/voiceInstruct.d.ts diff --git a/frontend/src/utils/voiceInstruct.js b/electron/src/shared/utils/voiceInstruct.js similarity index 100% rename from frontend/src/utils/voiceInstruct.js rename to electron/src/shared/utils/voiceInstruct.js diff --git a/frontend/src/utils/voiceInstruct.test.js b/electron/src/shared/utils/voiceInstruct.test.js similarity index 100% rename from frontend/src/utils/voiceInstruct.test.js rename to electron/src/shared/utils/voiceInstruct.test.js diff --git a/frontend/src/utils/watchFolder.js b/electron/src/shared/utils/watchFolder.js similarity index 100% rename from frontend/src/utils/watchFolder.js rename to electron/src/shared/utils/watchFolder.js diff --git a/frontend/src/utils/watchFolder.test.js b/electron/src/shared/utils/watchFolder.test.js similarity index 100% rename from frontend/src/utils/watchFolder.test.js rename to electron/src/shared/utils/watchFolder.test.js diff --git a/frontend/src/utils/watchFolderTracker.d.ts b/electron/src/shared/utils/watchFolderTracker.d.ts similarity index 100% rename from frontend/src/utils/watchFolderTracker.d.ts rename to electron/src/shared/utils/watchFolderTracker.d.ts diff --git a/frontend/src/utils/watchFolderTracker.js b/electron/src/shared/utils/watchFolderTracker.js similarity index 100% rename from frontend/src/utils/watchFolderTracker.js rename to electron/src/shared/utils/watchFolderTracker.js diff --git a/frontend/src/utils/waveformPan.js b/electron/src/shared/utils/waveformPan.js similarity index 100% rename from frontend/src/utils/waveformPan.js rename to electron/src/shared/utils/waveformPan.js diff --git a/frontend/src/utils/waveformPan.test.js b/electron/src/shared/utils/waveformPan.test.js similarity index 100% rename from frontend/src/utils/waveformPan.test.js rename to electron/src/shared/utils/waveformPan.test.js diff --git a/frontend/src/utils/webCompat.js b/electron/src/shared/utils/webCompat.js similarity index 100% rename from frontend/src/utils/webCompat.js rename to electron/src/shared/utils/webCompat.js diff --git a/electron/tests/locale-source-keys.mjs b/electron/tests/locale-source-keys.mjs index eb90ff23e..c75a2ac8e 100644 --- a/electron/tests/locale-source-keys.mjs +++ b/electron/tests/locale-source-keys.mjs @@ -31,7 +31,7 @@ const callPattern = /\b(?:t|tr)\(\s*(['"])([A-Za-z0-9_.:-]+)\1/g; const transPattern = /\bi18nKey\s*=\s*(['"])([A-Za-z0-9_.:-]+)\1/g; const sharedControls = ['SearchableSelect', 'VoiceSelector'].map((name) => - new URL(`../../frontend/src/components/${name}.jsx`, import.meta.url)); + new URL(`../src/shared/components/${name}.jsx`, import.meta.url)); for (const file of [...await sourceFiles(sourceDirectory), ...sharedControls]) { const source = await readFile(file, 'utf8'); for (const pattern of [callPattern, transPattern]) { diff --git a/electron/tests/renderer-smoke.vite.config.mjs b/electron/tests/renderer-smoke.vite.config.mjs index 9c073a4ba..88bb82c5d 100644 --- a/electron/tests/renderer-smoke.vite.config.mjs +++ b/electron/tests/renderer-smoke.vite.config.mjs @@ -35,6 +35,7 @@ export default defineConfig({ resolve: { alias: { '@': resolve(rendererRoot, 'src'), + '@shared': resolve(rendererRoot, '../shared'), '@vercel/oidc': resolve(rendererRoot, 'src/lib/vercel-oidc-browser.ts'), }, dedupe: ['react', 'react-dom'], diff --git a/electron/tsconfig.node.json b/electron/tsconfig.node.json index 4973a7fe2..1fdf6a94d 100644 --- a/electron/tsconfig.node.json +++ b/electron/tsconfig.node.json @@ -22,6 +22,7 @@ "vite.web.config.ts", "src/main/**/*", "src/preload/**/*", - "src/shared/**/*" + "src/shared/web-api-routing.ts", + "src/shared/repair-request.ts" ] } diff --git a/electron/tsconfig.web.json b/electron/tsconfig.web.json index c6f8583ed..62677639f 100644 --- a/electron/tsconfig.web.json +++ b/electron/tsconfig.web.json @@ -19,29 +19,31 @@ "resolveJsonModule": true, "noEmit": true, "paths": { - "@/*": ["./src/renderer/src/*"] + "@/*": ["./src/renderer/src/*"], + "@shared/*": ["./src/shared/*"] } }, "include": [ "src/renderer/src/**/*", "src/preload/index.d.ts", - "src/shared/**/*", "src/renderer/env.d.ts", - "../frontend/src/utils/languageRejection.ts", - "../frontend/src/utils/generationFailureMessage.ts", - "../frontend/src/utils/coalescedJsonStorage.ts", - "../frontend/src/utils/indexedDbLongformStore.ts", - "../frontend/src/utils/cookieExport.ts", - "../frontend/src/api/types.ts", - "../frontend/src/api/donation.ts", - "../frontend/src/api/authSession.ts", - "../frontend/src/utils/runCrashRecord.ts", - "../frontend/src/utils/nativeExit.ts", - "../frontend/src/utils/backendContact.ts", - "../frontend/src/utils/deploymentMode.ts", - "../frontend/src/utils/errorDocsMap.ts", - "../frontend/src/utils/analytics.ts", - "../frontend/src/api/external.ts", - "../frontend/src/api/dialects.ts" + "src/shared/utils/languageRejection.ts", + "src/shared/utils/generationFailureMessage.ts", + "src/shared/utils/coalescedJsonStorage.ts", + "src/shared/utils/indexedDbLongformStore.ts", + "src/shared/utils/cookieExport.ts", + "src/shared/api/types.ts", + "src/shared/api/donation.ts", + "src/shared/api/authSession.ts", + "src/shared/utils/runCrashRecord.ts", + "src/shared/utils/nativeExit.ts", + "src/shared/utils/backendContact.ts", + "src/shared/utils/deploymentMode.ts", + "src/shared/utils/errorDocsMap.ts", + "src/shared/utils/analytics.ts", + "src/shared/api/external.ts", + "src/shared/api/dialects.ts", + "src/shared/repair-request.ts", + "src/shared/web-api-routing.ts" ] } diff --git a/electron/vite.config.ts b/electron/vite.config.ts index c601882b8..3d1ff2dfc 100644 --- a/electron/vite.config.ts +++ b/electron/vite.config.ts @@ -20,6 +20,7 @@ export default defineConfig({ resolve: { alias: { '@': resolve(import.meta.dirname, 'src/renderer/src'), + '@shared': resolve(import.meta.dirname, 'src/shared'), '@vercel/oidc': resolve(import.meta.dirname, 'src/renderer/src/lib/vercel-oidc-browser.ts'), }, dedupe: ['react', 'react-dom'], @@ -29,7 +30,11 @@ export default defineConfig({ environment: 'jsdom', globals: true, setupFiles: ['./src/renderer/src/test/setup.ts'], - include: ['src/**/*.test.{ts,tsx}'], + include: [ + 'src/main/**/*.test.{ts,tsx}', + 'src/renderer/**/*.test.{ts,tsx}', + 'src/shared/repair-request.test.ts', + ], css: false, }, }); diff --git a/electron/vite.web.config.ts b/electron/vite.web.config.ts index 6a7047570..db15ad345 100644 --- a/electron/vite.web.config.ts +++ b/electron/vite.web.config.ts @@ -34,6 +34,7 @@ export default defineConfig({ resolve: { alias: { '@': resolve(root, 'src'), + '@shared': resolve(import.meta.dirname, 'src/shared'), '@vercel/oidc': resolve(root, 'src/lib/vercel-oidc-browser.ts'), }, dedupe: ['react', 'react-dom'], diff --git a/frontend/src/api/external.ts b/frontend/src/api/external.ts deleted file mode 100644 index fbdf1f039..000000000 --- a/frontend/src/api/external.ts +++ /dev/null @@ -1,34 +0,0 @@ -/** - * openExternal — open a URL in the user's default browser. - * - * In a Tauri desktop app `window.open()` is blocked by the webview. - * This helper uses `@tauri-apps/plugin-opener` when available and - * falls back to `window.open()` for browser-based dev mode. - */ - -const isTauri = - typeof window !== 'undefined' && - !!((window as any).__TAURI_INTERNALS__ || (window as any).__TAURI__); - -let _openUrl: ((url: string) => Promise) | null = null; - -/** - * Open an external URL in the system default browser. - * @param {string} url — the URL to open - */ -export async function openExternal(url: string) { - if (isTauri) { - try { - if (!_openUrl) { - const mod = await import('@tauri-apps/plugin-opener'); - _openUrl = mod.openUrl as (url: string) => Promise; - } - await _openUrl(url); - return; - } catch (err) { - console.warn('[openExternal] Tauri opener failed, falling back:', err); - } - } - // Fallback for browser dev mode - window.open(url, '_blank', 'noopener,noreferrer'); -} diff --git a/package.json b/package.json index d13993684..8572a252c 100644 --- a/package.json +++ b/package.json @@ -36,9 +36,6 @@ "dist:dir": "bun run --cwd electron dist:dir --publish never" }, "workspaces": ["electron"], - "dependencies": { - "posthog-js": "^1.434.14" - }, "devDependencies": { "concurrently": "^10", "playwright": "^1.63.0", diff --git a/scripts/render_demos_omnivoice.py b/scripts/render_demos_omnivoice.py index a0bab2871..59c7a9a20 100755 --- a/scripts/render_demos_omnivoice.py +++ b/scripts/render_demos_omnivoice.py @@ -72,7 +72,7 @@ CLONE_VOICE_INSTRUCT = "female, young adult, low pitch, american accent" CLONE_RENDER_STEPS = 48 # Dictation replay scripts. `text` MUST match SCRIPTS in -# frontend/src/components/DictationDemo.jsx verbatim — the card shows that +# electron/src/shared/components/DictationDemo.jsx verbatim — the card shows that # string as "what you would say" and then shows what the recogniser heard, so # any drift between the two reads as a transcription error. DICTATION_SCRIPTS = [ diff --git a/scripts/translate_all.py b/scripts/translate_all.py index 3b6cf543c..421be5c1a 100644 --- a/scripts/translate_all.py +++ b/scripts/translate_all.py @@ -5,7 +5,7 @@ import time from deep_translator import GoogleTranslator LOCALES_DIR = os.path.join( - os.path.dirname(os.path.abspath(__file__)), "..", "frontend", "src", "i18n", "locales" + os.path.dirname(os.path.abspath(__file__)), "..", "electron", "src", "shared", "i18n", "locales" ) LANGUAGES = [ diff --git a/tests/backend/core/test_error_docs_map.py b/tests/backend/core/test_error_docs_map.py index defe37e77..2895223e4 100644 --- a/tests/backend/core/test_error_docs_map.py +++ b/tests/backend/core/test_error_docs_map.py @@ -1,7 +1,7 @@ """Tests for backend/core/error_docs_map.py — error → docs URL taxonomy. The locked taxonomy is the contract Phase 5's bug reporter consumes and -the TS-side `frontend/src/utils/errorDocsMap.ts` mirrors. These tests pin +the TS-side `electron/src/shared/utils/errorDocsMap.ts` mirrors. These tests pin both the keys and that every URL points back to the project repo. """ from __future__ import annotations diff --git a/tests/backend/services/test_tts_backend_language_enforcement_2104.py b/tests/backend/services/test_tts_backend_language_enforcement_2104.py index 8a344ac66..6ae570fe8 100644 --- a/tests/backend/services/test_tts_backend_language_enforcement_2104.py +++ b/tests/backend/services/test_tts_backend_language_enforcement_2104.py @@ -197,7 +197,7 @@ def test_every_picker_label_resolves_to_an_explicit_code(_StubBackend): from pathlib import Path root = Path(__file__).resolve().parents[3] be = _StubBackend(["en"]) - for picker in [root / "frontend/src/languages.json", root / "electron/src/renderer/src/lib/languages.json"]: + for picker in [root / "electron/src/shared/languages.json", root / "electron/src/renderer/src/lib/languages.json"]: for label in json.loads(picker.read_text()): code = be._normalize_language_code(label) if label.lower() == "auto": diff --git a/tests/frontend/apiClient.test.mjs b/tests/frontend/apiClient.test.mjs index e009a3e9d..f2bf67dc9 100644 --- a/tests/frontend/apiClient.test.mjs +++ b/tests/frontend/apiClient.test.mjs @@ -1,4 +1,4 @@ -// Unit tests for frontend/src/api/client.ts URL composition + error handling. +// Unit tests for electron/src/shared/api/client.ts URL composition + error handling. // Runs under node:test with a synthetic fetch mock so no backend is needed. import { test, mock } from 'node:test'; @@ -6,7 +6,7 @@ import assert from 'node:assert/strict'; // bun/node strip .ts extension when type='module' is set in package.json; // without that we load via bun's loader by requesting the .ts path. -const clientPath = new URL('../../frontend/src/api/client.ts', import.meta.url).pathname; +const clientPath = new URL('../../electron/src/shared/api/client.ts', import.meta.url).pathname; const { API, apiUrl, apiFetch, apiJson, apiPost, ApiError } = await import(clientPath); diff --git a/tests/frontend/audioTrim.test.mjs b/tests/frontend/audioTrim.test.mjs index 951cf62fc..c16dc60c4 100644 --- a/tests/frontend/audioTrim.test.mjs +++ b/tests/frontend/audioTrim.test.mjs @@ -3,7 +3,7 @@ import assert from 'node:assert/strict'; import { clamp, encodeWav, computePeaksFromChannel, pickTickInterval, xToTime, pickHandle, applyDrag, zoomAtCursor, zoomCenter, sliceToMono, -} from '../../frontend/src/utils/audioTrim.js'; +} from '../../electron/src/shared/utils/audioTrim.js'; test('clamp', () => { assert.equal(clamp(5, 0, 10), 5); diff --git a/tests/frontend/bootstrap-splash-hook-order.test.mjs b/tests/frontend/bootstrap-splash-hook-order.test.mjs index 71d59a9bb..f4a939f45 100644 --- a/tests/frontend/bootstrap-splash-hook-order.test.mjs +++ b/tests/frontend/bootstrap-splash-hook-order.test.mjs @@ -29,7 +29,7 @@ import { readFileSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; const src = readFileSync( - fileURLToPath(new URL('../../frontend/src/components/BootstrapSplash.jsx', import.meta.url)), + fileURLToPath(new URL('../../electron/src/shared/components/BootstrapSplash.jsx', import.meta.url)), 'utf8', ); diff --git a/tests/frontend/describeVoice.test.mjs b/tests/frontend/describeVoice.test.mjs index 431f70af5..fa8f70712 100644 --- a/tests/frontend/describeVoice.test.mjs +++ b/tests/frontend/describeVoice.test.mjs @@ -6,8 +6,8 @@ import { test } from 'node:test'; import assert from 'node:assert/strict'; -const utilPath = new URL('../../frontend/src/utils/voiceInstruct.js', import.meta.url).pathname; -const constantsPath = new URL('../../frontend/src/utils/constants.js', import.meta.url).pathname; +const utilPath = new URL('../../electron/src/shared/utils/voiceInstruct.js', import.meta.url).pathname; +const constantsPath = new URL('../../electron/src/shared/utils/constants.js', import.meta.url).pathname; const { mergeDescribedAttrs } = await import(utilPath); const { CATEGORIES } = await import(constantsPath); diff --git a/tests/frontend/format.test.mjs b/tests/frontend/format.test.mjs index 332dee958..56e84d75b 100644 --- a/tests/frontend/format.test.mjs +++ b/tests/frontend/format.test.mjs @@ -1,8 +1,8 @@ -// Unit tests for frontend/src/utils/format.js — timecode formatter. +// Unit tests for electron/src/shared/utils/format.js — timecode formatter. import { test } from 'node:test'; import assert from 'node:assert/strict'; -import { formatTime } from '../../frontend/src/utils/format.js'; +import { formatTime } from '../../electron/src/shared/utils/format.js'; test('formatTime seconds below a minute', () => { diff --git a/tests/probe/specs/i18n_parity.probe.yaml b/tests/probe/specs/i18n_parity.probe.yaml index 10070d18e..16df9847f 100644 --- a/tests/probe/specs/i18n_parity.probe.yaml +++ b/tests/probe/specs/i18n_parity.probe.yaml @@ -1,6 +1,6 @@ # i18n spec — localization structural integrity (CLAUDE.md hard rule). # -# Actor: read frontend/src/i18n/locales/*.json. The test supplies locales_dir. +# Actor: read electron/src/shared/i18n/locales/*.json. The test supplies locales_dir. # # Gates only on valid JSON. Orphan-key detection and coverage are ADVISORY: the # repo currently has real orphan keys (non-en locales carry gallery.cat_* and @@ -12,7 +12,7 @@ layer: i18n steps: - actor: fs - read: frontend/src/i18n/locales/*.json + read: electron/src/shared/i18n/locales/*.json capture: { locales_dir: $.locales_dir } judge: diff --git a/tests/probe/test_probe_i18n.py b/tests/probe/test_probe_i18n.py index d66b951d8..0c747a252 100644 --- a/tests/probe/test_probe_i18n.py +++ b/tests/probe/test_probe_i18n.py @@ -12,7 +12,7 @@ from . import spec as probe_spec from .judges import i18n as I _SPEC = os.path.join(os.path.dirname(__file__), "specs", "i18n_parity.probe.yaml") -_LOCALES = str(Path(__file__).resolve().parents[2] / "frontend" / "src" / "i18n" / "locales") +_LOCALES = str(Path(__file__).resolve().parents[2] / "electron" / "src" / "shared" / "i18n" / "locales") def _write_locales(tmp_path, mapping): diff --git a/tests/scripts/test_crash_class_report.py b/tests/scripts/test_crash_class_report.py index 16e953d9a..aad1b56fe 100644 --- a/tests/scripts/test_crash_class_report.py +++ b/tests/scripts/test_crash_class_report.py @@ -5,7 +5,7 @@ Pins two things: - title → sub-class mapping matches the auto-reporter's real title shapes (seeded from error messages, so titles are machine-stable), and - body → build bucket mapping matches the exact `**Build status:**` lines - the bug reporter stamps (frontend/src/utils/bugReport.js) — a drift in + the bug reporter stamps (electron/src/shared/utils/bugReport.js) — a drift in either side silently zeroes the metric. """ @@ -50,7 +50,7 @@ def test_title_bucketing(report, title, expected): def test_build_status_lines_match_the_reporter_stamps(report): - # These literals must stay in lockstep with frontend/src/utils/bugReport.js + # These literals must stay in lockstep with electron/src/shared/utils/bugReport.js # captureContext() — the stamps are the metric's only version signal. assert report.OUTDATED.search("**Build status:** OUTDATED — `v0.5.0` was already out when this was filed") assert report.CURRENT.search("**Build status:** current at filing time (latest `v0.5.0`)") @@ -79,6 +79,6 @@ def test_classify_build(report, body, version, expected): def test_reporter_source_still_emits_the_stamps(report): # Fail here (not in production silence) if bugReport.js rewords the marker. - src = (SCRIPT_PATH.parents[1] / "frontend/src/utils/bugReport.js").read_text(encoding="utf-8") + src = (SCRIPT_PATH.parents[1] / "electron/src/shared/utils/bugReport.js").read_text(encoding="utf-8") assert "**Build status:** OUTDATED" in src assert "**Build status:** current at filing time" in src diff --git a/tests/test_analytics_lifecycle.py b/tests/test_analytics_lifecycle.py index 939a3c6b7..85729b247 100644 --- a/tests/test_analytics_lifecycle.py +++ b/tests/test_analytics_lifecycle.py @@ -207,13 +207,13 @@ def test_crash_source_is_single_the_frontend_never_emits_one(): crash source. The frontend SDK wrapper must never grow its own crash event (the shell's marker describes the same death the sentinel reports).""" ts = os.path.join( - os.path.dirname(__file__), "..", "frontend", "src", "utils", "analytics.ts" + os.path.dirname(__file__), "..", "electron", "src", "shared", "utils", "analytics.ts" ) with open(ts, encoding="utf-8") as f: src = f.read() assert "app_crashed" not in src crash_ts = os.path.join( - os.path.dirname(__file__), "..", "frontend", "src", "utils", "backendCrash.ts" + os.path.dirname(__file__), "..", "electron", "src", "shared", "utils", "backendCrash.ts" ) with open(crash_ts, encoding="utf-8") as f: assert "app_crashed" not in f.read() diff --git a/tests/test_analytics_optin.py b/tests/test_analytics_optin.py index 62160665e..db285286b 100644 --- a/tests/test_analytics_optin.py +++ b/tests/test_analytics_optin.py @@ -235,12 +235,12 @@ def test_frontend_allowlist_mirrors_backend(): import re ts_path = os.path.join( - os.path.dirname(__file__), "..", "frontend", "src", "utils", "analytics.ts" + os.path.dirname(__file__), "..", "electron", "src", "shared", "utils", "analytics.ts" ) with open(ts_path, encoding="utf-8") as f: src = f.read() m = re.search(r"ALLOWED_PROPS\s*=\s*new Set\(\[(.*?)\]\)", src, re.S) - assert m, "ALLOWED_PROPS Set not found in frontend/src/utils/analytics.ts" + assert m, "ALLOWED_PROPS Set not found in electron/src/shared/utils/analytics.ts" frontend = set(re.findall(r"'([a-z_]+)'", m.group(1))) assert frontend == set(analytics._ALLOWED_PROPS) diff --git a/tests/test_auth_gate_detail_lockstep.py b/tests/test_auth_gate_detail_lockstep.py index 68f58c4d5..4f5f842d5 100644 --- a/tests/test_auth_gate_detail_lockstep.py +++ b/tests/test_auth_gate_detail_lockstep.py @@ -5,7 +5,7 @@ mode-distinct ``detail`` (``_admin_gate_403`` in backend/api/dependencies.py): "loopback origin or admin API key required" in server mode, plain "loopback origin required" on the desktop build. The SPA's ``apiFetch`` routes a 403 to the API-key login gate exactly when the detail contains the substring -"admin api key" (frontend/src/api/client.ts) — i.e. when presenting the key +"admin api key" (electron/src/shared/api/client.ts) — i.e. when presenting the key could actually satisfy the gate. The per-mode behaviour is pinned by tests/test_loopback_server_mode.py; this file pins the LITERAL contract across layers: a backend reword keeps backend tests green while the frontend matcher @@ -20,7 +20,7 @@ from pathlib import Path ROOT = Path(__file__).resolve().parents[1] DEPS = ROOT / "backend" / "api" / "dependencies.py" -CLIENT = ROOT / "frontend" / "src" / "api" / "client.ts" +CLIENT = ROOT / "electron" / "src" / "shared" / "api" / "client.ts" def _frontend_sniff() -> str: @@ -28,7 +28,7 @@ def _frontend_sniff() -> str: text = CLIENT.read_text(encoding="utf-8") # adminGate403 = ... detail.toLowerCase().includes('') m = re.search(r"adminGate403 =.*?includes\('([^']+)'\)", text, re.DOTALL) - assert m, "adminGate403 matcher not found in frontend/src/api/client.ts" + assert m, "adminGate403 matcher not found in electron/src/shared/api/client.ts" return m.group(1) @@ -42,7 +42,7 @@ def test_key_named_details_match_frontend_sniff(): details = _key_named_details() assert details, ( "no 'admin API key' detail literal left in dependencies.py — moved or " - "reworded? Update frontend/src/api/client.ts in the same change." + "reworded? Update electron/src/shared/api/client.ts in the same change." ) sniff = _frontend_sniff() for detail in details: @@ -50,7 +50,7 @@ def test_key_named_details_match_frontend_sniff(): assert sniff in detail.lower(), ( f"backend detail {detail!r} no longer contains the frontend matcher " f"{sniff!r} — the SPA would stop routing it to the API-key gate. " - "Update frontend/src/api/client.ts in the same change." + "Update electron/src/shared/api/client.ts in the same change." ) diff --git a/tests/test_clone_ref_silence_ladder.py b/tests/test_clone_ref_silence_ladder.py index 3de81ae30..01d53c249 100644 --- a/tests/test_clone_ref_silence_ladder.py +++ b/tests/test_clone_ref_silence_ladder.py @@ -16,7 +16,7 @@ The fix (fail-before/pass-after — `remove_silence_safe` and * `validate_clone_reference` raises the one remaining hard failure — a clip with genuinely no audio (empty / digital silence / NaN) — with the machine-readable ``[clone_ref_unusable]`` marker the frontend maps to a - localized, actionable message (frontend/src/utils/errorToast.jsx → + localized, actionable message (electron/src/shared/utils/errorToast.jsx → tts_errors.ref_audio_unusable). All clone producers share this path (`create_voice_clone_prompt` is the single diff --git a/tests/test_demo_assets_exist.py b/tests/test_demo_assets_exist.py index e928802e1..f983d5618 100644 --- a/tests/test_demo_assets_exist.py +++ b/tests/test_demo_assets_exist.py @@ -37,7 +37,7 @@ _BACKEND = os.path.join(_REPO_ROOT, "backend") _DEMO_ROOT = os.path.join(_BACKEND, "assets", "samples") _DICTATION_DEMO = os.path.join( - _REPO_ROOT, "frontend", "src", "components", "DictationDemo.jsx" + _REPO_ROOT, "electron", "src", "shared", "components", "DictationDemo.jsx" ) diff --git a/tests/test_diarization_error_class.py b/tests/test_diarization_error_class.py index 59f83333e..1ff0a178d 100644 --- a/tests/test_diarization_error_class.py +++ b/tests/test_diarization_error_class.py @@ -216,7 +216,7 @@ class TestErrorDocsDeeplink: def test_pyannote_license_required_is_in_locked_taxonomy(self): """If this test fails, the 5-class taxonomy was bumped without - also bumping the TS mirror — see frontend/src/utils/errorDocsMap.ts + also bumping the TS mirror — see electron/src/shared/utils/errorDocsMap.ts and its keys-sync test.""" from core import error_docs_map assert "PYANNOTE_LICENSE_REQUIRED" in error_docs_map.ERROR_DOCS diff --git a/tests/test_dictation_model_copy.py b/tests/test_dictation_model_copy.py index 334f4e3b6..495d6a0a6 100644 --- a/tests/test_dictation_model_copy.py +++ b/tests/test_dictation_model_copy.py @@ -6,7 +6,7 @@ import json from pathlib import Path -_LOCALES = Path(__file__).resolve().parents[1] / "frontend" / "src" / "i18n" / "locales" +_LOCALES = Path(__file__).resolve().parents[1] / "electron" / "src" / "shared" / "i18n" / "locales" def test_recommended_badge_copy_belongs_to_whisper_tiny_in_every_locale(): diff --git a/tests/test_dub_source_lang_1960.py b/tests/test_dub_source_lang_1960.py index 8b975a870..7539c15a1 100644 --- a/tests/test_dub_source_lang_1960.py +++ b/tests/test_dub_source_lang_1960.py @@ -23,7 +23,7 @@ from fastapi import HTTPException from api.routers.dub_core import _DUB_SOURCE_LANG_CODES, _source_lang_override _REPO = pathlib.Path(__file__).resolve().parents[1] -_LANGUAGES_JS = _REPO / "frontend" / "src" / "utils" / "languages.js" +_LANGUAGES_JS = _REPO / "electron" / "src" / "shared" / "utils" / "languages.js" def test_the_rejection_names_the_code(): diff --git a/tests/test_electron_only_ui.py b/tests/test_electron_only_ui.py index 2ce0d1a7e..5154a6d89 100644 --- a/tests/test_electron_only_ui.py +++ b/tests/test_electron_only_ui.py @@ -7,12 +7,13 @@ ROOT = Path(__file__).resolve().parents[1] def test_tauri_shell_and_legacy_ui_entrypoints_are_removed(): assert not (ROOT / "frontend/src-tauri").exists() + assert not (ROOT / "frontend/src").exists() assert not (ROOT / ".github/workflows/release.yml").exists() for path in ( "frontend/index.html", - "frontend/src/main.jsx", - "frontend/src/main-app.jsx", - "frontend/src/App.jsx", + "electron/src/shared/main.jsx", + "electron/src/shared/main-app.jsx", + "electron/src/shared/App.jsx", "scripts/desktop-dev.mjs", "scripts/desktop-dev-launch.mjs", "scripts/desktop-prod.sh", diff --git a/tests/test_engine_unavailable_reason_1866.py b/tests/test_engine_unavailable_reason_1866.py index 557407c06..5370349b9 100644 --- a/tests/test_engine_unavailable_reason_1866.py +++ b/tests/test_engine_unavailable_reason_1866.py @@ -136,7 +136,7 @@ def test_a_license_gate_keeps_the_words_the_accept_button_needs(diagnostic, one_ # detail split (engines/engineDisplay.js, used by the row and the panel). source = ( Path(__file__).resolve().parents[1] - / "frontend/src/components/engines/engineDisplay.js" + / "electron/src/shared/components/engines/engineDisplay.js" ).read_text(encoding="utf-8") m = re.search(r"function reasonMentionsLicense\(reason\)[^}]*?return /([^/]+)/(\w*)\.test", source, re.S) assert m, "engineDisplay.reasonMentionsLicense changed shape" diff --git a/tests/test_first_sound_instruct.py b/tests/test_first_sound_instruct.py index 7a2affe58..0eb55e677 100644 --- a/tests/test_first_sound_instruct.py +++ b/tests/test_first_sound_instruct.py @@ -6,7 +6,7 @@ def test_first_sound_instruction_passes_runtime_taxonomy_validation(): from omnivoice.models.omnivoice import _resolve_instruct defaults = json.loads( - (Path(__file__).parents[1] / "frontend/src/utils/firstSound.json").read_text() + (Path(__file__).parents[1] / "electron/src/shared/utils/firstSound.json").read_text() ) instruct = defaults["instruct"] # VoiceDesign requires a nonempty description; OmniVoice validates tokens. diff --git a/tests/test_issue_fixes.py b/tests/test_issue_fixes.py index 2314b46b4..09857bf72 100644 --- a/tests/test_issue_fixes.py +++ b/tests/test_issue_fixes.py @@ -32,8 +32,8 @@ NEW_DISCORD = "discord.gg/bzQavDfVV9" _LINK_FILES = [ "README.md", ".github/CONTRIBUTING.md", - "frontend/src/pages/EnterprisePage.jsx", - "frontend/src/components/LogsFooter.jsx", + "electron/src/shared/pages/EnterprisePage.jsx", + "electron/src/shared/components/LogsFooter.jsx", ] @@ -43,7 +43,7 @@ def test_discord_link_updated(relpath): filepath = _REPO / relpath if not filepath.exists(): pytest.skip(f"{relpath} not found") - content = filepath.read_text() + content = filepath.read_text(encoding="utf-8") assert OLD_DISCORD not in content, f"{relpath} still contains expired link {OLD_DISCORD}" assert NEW_DISCORD in content, f"{relpath} missing new link {NEW_DISCORD}" diff --git a/tests/test_locale_parity.py b/tests/test_locale_parity.py index 1733d7d14..6d716e9e3 100644 --- a/tests/test_locale_parity.py +++ b/tests/test_locale_parity.py @@ -1,7 +1,7 @@ """Locale key parity — all 21 i18n files stay in lockstep with en.json. Replaces the manual locale sweeps: CLAUDE.md's Localization rule routes every -UI string through ``frontend/src/i18n/locales/*.json``, which only works if +UI string through ``electron/src/shared/i18n/locales/*.json``, which only works if every file parses, carries no keys en.json doesn't have, and preserves en's ``{{placeholder}}`` tokens. Real bug classes this pins down: @@ -28,7 +28,7 @@ import pytest _LOCALES_DIR = os.path.join( os.path.dirname(os.path.dirname(os.path.abspath(__file__))), - "frontend", "src", "i18n", "locales", + "electron", "src", "shared", "i18n", "locales", ) _EN = "en" @@ -465,7 +465,7 @@ def test_dub_plan_actions_and_explanations_are_translated(locale): def test_locale_objects_have_no_duplicate_keys(): from pathlib import Path root = Path(__file__).resolve().parents[1] - for directory in (root / "frontend/src/i18n/locales", root / "electron/src/renderer/src/i18n/locales"): + for directory in (root / "electron/src/shared/i18n/locales", root / "electron/src/renderer/src/i18n/locales"): for path in directory.glob("*.json"): def unique_object(pairs): result = {} diff --git a/tests/test_longform_parser.py b/tests/test_longform_parser.py index c55b20f72..ff730dadc 100644 --- a/tests/test_longform_parser.py +++ b/tests/test_longform_parser.py @@ -1,6 +1,6 @@ """Canonical longform parser (#27) — pytest side of the cross-impl golden corpus. -This suite and ``frontend/src/test/longformParser.test.js`` load the SAME JSON +This suite and ``electron/src/shared/test/longformParser.test.js`` load the SAME JSON (`tests/fixtures/longform_parser_cases.json`) and assert both impls produce it byte-for-byte. A divergence cannot pass both suites — the side that drifts fails its own assertion against the shared truth. diff --git a/tests/test_no_committed_analytics_token.py b/tests/test_no_committed_analytics_token.py index c5e72d6e3..5c249ae16 100644 --- a/tests/test_no_committed_analytics_token.py +++ b/tests/test_no_committed_analytics_token.py @@ -8,7 +8,7 @@ data access — PostHog's client keys are designed to ship in client code) is committed as an in-repo default in the two files that implement analytics: backend/core/analytics.py (_PUBLIC_PROJECT_TOKEN) - frontend/src/utils/analytics.ts (PUBLIC_PROJECT_TOKEN) + electron/src/shared/utils/analytics.ts (PUBLIC_PROJECT_TOKEN) This guard pins the new contract: a `phc_` literal may exist ONLY there, both files must actually carry one, and the two must be the SAME token (one PostHog @@ -31,7 +31,7 @@ _POSTHOG_KEY_RE = re.compile(r"phc_[A-Za-z0-9]{20,}") # The ONLY tracked files allowed to contain a `phc_` literal (#1193). _CANONICAL_TOKEN_FILES = ( "backend/core/analytics.py", - "frontend/src/utils/analytics.ts", + "electron/src/shared/utils/analytics.ts", ) _SKIP_DIRS = {"node_modules", ".git", "target", "dist", "build", ".venv", "zig-out"} @@ -103,7 +103,7 @@ def test_both_canonical_files_carry_the_same_default_token(): def test_the_frontend_reads_its_token_override_from_the_build_env(): """The build-time override mechanism must stay in place.""" - src = (_REPO / "frontend/src/utils/analytics.ts").read_text(encoding="utf-8") + src = (_REPO / "electron/src/shared/utils/analytics.ts").read_text(encoding="utf-8") assert "VITE_POSTHOG_KEY" in src diff --git a/tests/test_no_hardcoded_cjk.py b/tests/test_no_hardcoded_cjk.py index fd654c53e..af91f9e07 100644 --- a/tests/test_no_hardcoded_cjk.py +++ b/tests/test_no_hardcoded_cjk.py @@ -1,8 +1,8 @@ """Hard rule: no hardcoded non-English (CJK) *user-facing* text outside the translation layer. -UI strings must go through i18n (``frontend/src/i18n/locales/*.json`` via -``t('...')``); native language names live in ``frontend/src/i18n/index.ts``. +UI strings must go through i18n (``electron/src/shared/i18n/locales/*.json`` via +``t('...')``); native language names live in ``electron/src/shared/i18n/index.ts``. This guards against contributors hardcoding Chinese/Japanese/Korean display strings in component or app code (see CLAUDE.md > Conventions). @@ -41,7 +41,7 @@ _SKIP_EXT = { # CJK (test-fixture descriptions, model/engine identifiers like CosyVoice # speaker IDs, multilingual sample text) — they are documentation, not shipped # UI strings, so they belong on the same footing as the allowlisted docs below. -_ALLOWED_PREFIXES = ("frontend/src/i18n/", "electron/src/renderer/src/i18n/", "docs/specs/") +_ALLOWED_PREFIXES = ("electron/src/shared/i18n/", "electron/src/renderer/src/i18n/", "docs/specs/") # Functional / data / documentation files where CJK is intentional and required. _ALLOWED_FILES = { @@ -60,22 +60,22 @@ _ALLOWED_FILES = { "backend/services/subtitle_segmenter.py", "backend/services/text_normalization.py", # spoken range word per language ("20~30" must not read as one number) "backend/core/http_headers.py", # docstring quotes the CJK filename that 500'd the header (#1262) - "frontend/src/components/DubSegmentRow.jsx", - "frontend/src/components/StoriesEditor.jsx", - "frontend/src/utils/voiceInstruct.js", + "electron/src/shared/components/DubSegmentRow.jsx", + "electron/src/shared/components/StoriesEditor.jsx", + "electron/src/shared/utils/voiceInstruct.js", "omnivoice/utils/text.py", # Model / engine vocabulary & identifiers (the model/engine requires these) "backend/services/tts_backend.py", # CosyVoice speaker IDs "backend/core/personalities.py", # Chinese-dialect showcase preset "backend/core/archetypes.py", # Chinese-dialect + JA/KO multilingual preview sample text "backend/core/describe_voice.py", # pinyin → Chinese-dialect token mapping (model vocabulary, #317) - "frontend/src/utils/constants.js", # Chinese-dialect picker names + "electron/src/shared/utils/constants.js", # Chinese-dialect picker names "omnivoice/models/omnivoice.py", # instruct-mode vocabulary "omnivoice/utils/duration.py", "omnivoice/utils/voice_design.py", # EN/CJK attribute maps "backend/migrations/versions/0007_rebuild_poisoned_design_instruct.py", # frozen CJK dialect-tag snapshot for the instruct heal (#564) # Localized error matching (classify OS errors reported in Chinese, #72) - "frontend/src/utils/errorDocsMap.ts", + "electron/src/shared/utils/errorDocsMap.ts", # WER evaluation data "omnivoice/eval/wer/fleurs.py", "omnivoice/eval/wer/punctuations.lst", @@ -157,7 +157,7 @@ def test_no_hardcoded_cjk_outside_locales(): if offenders: msg = [ "Hardcoded non-English (CJK) text found outside the translation layer.", - "Move user-facing strings into frontend/src/i18n/locales/*.json (or use English).", + "Move user-facing strings into electron/src/shared/i18n/locales/*.json (or use English).", "If functional CJK (regex/model-vocab/data/fixture), add the file to _ALLOWED_FILES here.", "", ] diff --git a/tests/test_no_windows_hostile_paths.py b/tests/test_no_windows_hostile_paths.py index b533d4bf2..94cc56080 100644 --- a/tests/test_no_windows_hostile_paths.py +++ b/tests/test_no_windows_hostile_paths.py @@ -102,7 +102,7 @@ def test_rejects_every_shape_windows_refuses(rel): [ "backend/core/version.py", "docs/adr/0001-something.md", - "frontend/src/i18n/locales/zh-CN.json", + "electron/src/shared/i18n/locales/zh-CN.json", "tests/test_no_windows_hostile_paths.py", "scripts/build-omnivoice-tts.sh", "bin/omnivoice-tts-linux-aarch64", diff --git a/tests/test_pockettts_deferred.py b/tests/test_pockettts_deferred.py index 5e6299220..569927693 100644 --- a/tests/test_pockettts_deferred.py +++ b/tests/test_pockettts_deferred.py @@ -160,7 +160,7 @@ def test_every_locale_discloses_hugging_face_model_access(): import json from pathlib import Path - locales = Path(__file__).resolve().parents[1] / "frontend/src/i18n/locales" + locales = Path(__file__).resolve().parents[1] / "electron/src/shared/i18n/locales" paths = sorted(locales.glob("*.json")) assert len(paths) == 21 for path in paths: diff --git a/tests/test_port_in_use_exit.py b/tests/test_port_in_use_exit.py index de2b982db..762ccfb55 100644 --- a/tests/test_port_in_use_exit.py +++ b/tests/test_port_in_use_exit.py @@ -44,7 +44,7 @@ def test_electron_shell_agrees_on_the_exit_code(): def test_frontend_crash_hint_agrees_on_the_exit_code(): - src = _read("frontend", "src", "utils", "backendCrash.ts") + src = _read("electron", "src", "shared", "utils", "backendCrash.ts") assert f"marker.exit_code === {_EXPECTED_EXIT}" in src diff --git a/tests/test_profile_language_rejection_2156.py b/tests/test_profile_language_rejection_2156.py index f2298d49a..c8139763b 100644 --- a/tests/test_profile_language_rejection_2156.py +++ b/tests/test_profile_language_rejection_2156.py @@ -8,7 +8,7 @@ got: 'Auto', or switch to a multilingual engine … They had left it on Auto. The UI omits `language` entirely while its picker -reads "Auto" (`frontend/src/hooks/useProfiles.js`: `if (reqLang && reqLang !== +reads "Auto" (`electron/src/shared/hooks/useProfiles.js`: `if (reqLang && reqLang !== 'Auto') formData.append(...)`), and #533 fills that gap from the selected voice profile. So "Auto" is precisely how 'Persian' got there — the one remedy the message leads with is the state the user was already in, and nothing in it diff --git a/tests/test_voicestudio_branding.py b/tests/test_voicestudio_branding.py index 5f37e4923..2b2677588 100644 --- a/tests/test_voicestudio_branding.py +++ b/tests/test_voicestudio_branding.py @@ -44,9 +44,9 @@ def test_visible_brand_surfaces_say_voicestudio() -> None: def test_brand_mark_is_shared_and_fills_the_icon() -> None: - mark = (ROOT / "frontend/src/components/brand/VoiceStudioMark.jsx").read_text() - header = (ROOT / "frontend/src/components/Header.jsx").read_text() - about = (ROOT / "frontend/src/components/settings/AboutTab.jsx").read_text() + mark = (ROOT / "electron/src/shared/components/brand/VoiceStudioMark.jsx").read_text() + header = (ROOT / "electron/src/shared/components/Header.jsx").read_text() + about = (ROOT / "electron/src/shared/components/settings/AboutTab.jsx").read_text() logo = (ROOT / "docs/logo.svg").read_text() favicon = (ROOT / "electron/public/favicon.svg").read_text() @@ -106,7 +106,7 @@ def test_active_source_launch_is_electron_and_web_ports_clean_quietly() -> None: def test_icon_rail_has_no_static_section_captions_and_keeps_air_between_items() -> None: - rail = (ROOT / "frontend/src/components/NavRail.jsx").read_text() + rail = (ROOT / "electron/src/shared/components/NavRail.jsx").read_text() for stale_caption in ("Start", "Create", "Workflows", "Reference"): assert stale_caption not in rail assert "pt-[18px]" in rail