Commit Graph

7 Commits

Author SHA1 Message Date
gsxdsm
06ec0e606e FN-7866: add auto-save toggle for the workspace file editor (default on)
Adds a shared, persisted auto-save preference for workspace text-file editing, defaulted to on, surfaced as a toolbar toggle in both the Files modal and right-dock Files view.

- Add useAutoSavePreference hook: persists the fn-file-editor-auto-save localStorage preference, broadcasts same-window changes via a custom event (storage events only reach other documents), and defaults to true.
- Extend useWorkspaceFileEditor with an autoSave flag that debounces (800ms) and triggers save() for a loaded, editable file with real pending changes, keyed by workspace+file+content to avoid re-firing on failed writes.
- Add an Auto-save toggle button to FileEditor's toolbar (autoSaveEnabled/onToggleAutoSave/canToggleAutoSave props), hidden for read-only/preview/binary files.
- Wire the shared preference into FileBrowserModal and DockFilesView, disabling auto-save for binary files in the modal.
- Add fileEditor.autoSave / fileEditor.toggleAutoSave i18n strings and document the new default behavior in docs/dashboard-guide.md.
- Add/extend tests covering the new hook, debounced auto-save behavior, and toolbar toggle wiring across FileEditor, FileBrowserModal, and DockFilesView.

Files changed:
 docs/dashboard-guide.md                            |   3 +
 .../dashboard/app/components/DockFilesView.tsx     |   6 +-
 .../dashboard/app/components/FileBrowserModal.tsx  |  20 ++--
 packages/dashboard/app/components/FileEditor.tsx   |  17 +++-
 .../components/__tests__/DockFilesView.test.tsx    |  37 ++++++-
 .../components/__tests__/FileBrowserModal.test.tsx |  86 +++++++++++++---
 .../app/components/__tests__/FileEditor.test.tsx   |  56 +++++++++++
 .../hooks/__tests__/useAutoSavePreference.test.ts  |  66 +++++++++++++
 .../hooks/__tests__/useWorkspaceFileEditor.test.ts | 108 +++++++++++++++++++++
 .../dashboard/app/hooks/useAutoSavePreference.ts   |  79 +++++++++++++++
 .../dashboard/app/hooks/useWorkspaceFileEditor.ts  |  47 ++++++++-
 packages/i18n/locales/en/app.json                  |   2 +
 12 files changed, 500 insertions(+), 27 deletions(-)

Fusion-Task-Id: FN-7866

Fusion-Task-Lineage: 0604de18-666d-4872-abce-2a3886c9ea55

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 12:49:37 -07:00
gsxdsm
1e49494bac feat(i18n): full-sweep string migration — 5,930 keys across 5 locales (#1352)
Migration (multi-agent sweep over 216 files, 60 batches):
- Every user-visible dashboard + TUI string moved to t() with the exact
  English inline default (en rendering byte-identical)
- Catalogs merged from per-batch fragments: en/zh-CN/zh-TW/fr/es now
  carry ~5,930 keys each across common/app/errors/cli namespaces;
  CLI bundles regenerated (6 locales incl. ko)

Integration fixes:
- 18 type errors: reserved {{count}} interpolations renamed, malformed
  plural call, hand-rolled t-param types replaced with TFunction<"app">
- 23 lint errors: superseded label constants/helpers removed
- ExecutorStatusBar hook-order violation (keyboard-open early return
  moved below hooks)
- TUI tests wrapped in I18nextProvider (uninitialized fallback renders
  literal {{placeholders}}); dashboard vitest.setup boots a minimal en
  i18next instance for the same reason

Known WIP (next commits): ~457 residual strings across 50 batches,
Korean drafts for swept keys, and a dashboard test-suite pass that is
still being stabilized (~283 failures under investigation — fake-timer
waitFor interaction, likely stale node_modules vs merged lockfile).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 19:06:53 -07:00
gsxdsm
3fbb7c47cf refactor: eliminate ~400 no-explicit-any warnings across the workspace
Parallel subagent pass: four typescript-pro agents on non-overlapping scopes.

Patterns applied:
- catch (err: any) { ... err.message ... } → catch (err) { ... getErrorMessage(err) ... }
  using the new @fusion/core helper. Bare catch {} where the error was unused.
- SQLite row types: defined typed XxxRow interfaces per table and cast
  .all()/.get() results via `as unknown as XxxRow[]` (the double cast is
  required because better-sqlite3 returns Record<string, SQLOutputValue>).
- rowToX(row: any) converters: typed argument with the matching row interface.
- Dynamic settings key writes: (settings as Record<string, unknown>)[key].
- React event handlers and setState callbacks: inferred types or concrete
  React.{Mouse,Change,Form}Event<...> where needed.
- pi-claude-cli: local PiMessage / PiContext duck types to avoid re-typing
  pi-ai concrete shapes; typed Claude stream event message fields.

72 files changed, ~400 anys eliminated. Typecheck passes across the workspace.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 23:02:36 -07:00
Fusion
123ec5949f feat(FN-1862): add completion state tracking for onboarding
- Add markOnboardingCompleted() to set completedAt timestamp when user finishes onboarding
- Add isOnboardingCompleted() to check if onboarding was completed (vs dismissed)
- Update ModelOnboardingModal to call markOnboardingCompleted on successful completion
- Skip onboarding auto-open when already completed locally
- Add completion state tracking tests in ModelOnboardingModal.test.tsx
- Add model-onboarding-state unit tests
- Update useAuthOnboarding to check local completion state before auto-opening
- Document localStorage completion state tracking pattern in .fusion/memory.md
2026-04-14 23:44:40 -07:00
gsxdsm
2800f57d78 feat(FN-1748): merge fusion/fn-1748 2026-04-14 22:45:59 -07:00
gsxdsm
c9cd9284d7 fix: project-scope terminal, file browser, agent execution, and heartbeat monitor
- TerminalService: use per-project instance map instead of destructive singleton
- File browser: thread projectId through API functions, hooks, and components
- Workspace file editor: pass projectId to read/write operations
- Agent heartbeat: guard execution with project scope validation
- Agent runs/stop: validate heartbeatMonitor matches scoped project
- CLI dashboard/serve: pass rootDir to heartbeatMonitor via server options
- Add getRootDir() to HeartbeatMonitor for scope comparison

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-04-12 18:38:26 -07:00
gsxdsm
f2c00ad147 feat(KB-175): move file browser to header with workspace support
- Add workspace file APIs and hooks for session-scoped file browsing
- Create WorkspaceSelector component for switching between workspaces
- Update FileBrowserModal with workspace mode and improved UX
- Add files button to header with workspace-aware file browsing
- Add session files indicator to task cards for quick file access
- Include comprehensive tests for all new components and hooks
2026-03-31 01:26:57 -07:00