2026-03-02 11:55:51 +01:00
|
|
|
import { useCallback, useRef } from 'react'
|
2026-04-14 11:55:48 +02:00
|
|
|
import type { AiAgentId, AiAgentsStatus } from '../lib/aiAgents'
|
2026-04-14 14:16:55 +02:00
|
|
|
import type { VaultAiGuidanceStatus } from '../lib/vaultAiGuidance'
|
2026-02-25 13:31:19 +01:00
|
|
|
import { useAppKeyboard } from './useAppKeyboard'
|
|
|
|
|
import { useCommandRegistry } from './useCommandRegistry'
|
|
|
|
|
import type { CommandAction } from './useCommandRegistry'
|
|
|
|
|
import { useKeyboardNavigation } from './useKeyboardNavigation'
|
feat: populate macOS menu bar with native menus (File, Edit, View, Window) (#77)
* feat: populate macOS menu bar with File, Edit, View, Window menus
Add complete native macOS menu structure with all app actions:
- Laputa menu: About, Settings (Cmd+,), Hide/Quit
- File: New Note (Cmd+N), Quick Open (Cmd+P), Save (Cmd+S), Close Tab (Cmd+W)
- Edit: standard Undo/Redo/Cut/Copy/Paste/Select All
- View: Editor Only (Cmd+1), Editor+Notes (Cmd+2), All Panels (Cmd+3),
Toggle Inspector, Command Palette (Cmd+K)
- Window: Minimize, Maximize, Close Window
All accelerators registered via Tauri menu API. Menu events dispatched
to frontend via useMenuEvents hook. Save/Close Tab items dynamically
disabled when no note tab is active.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: wrap Enter selection assertion in waitFor for effect re-registration
* fix: resolve rebase conflict markers in menu.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 20:05:24 +01:00
|
|
|
import { useMenuEvents } from './useMenuEvents'
|
refactor: remove theming system entirely
Remove all theme switching, creation, and management functionality
from the app — backend (Rust theme module, Tauri commands, menu items,
startup tasks, vault seeding), frontend (useThemeManager, ThemePropertyEditor,
themeSchema, command palette Appearance group, settings panel appearance
section, isDarkTheme prop chain), mock data, and all related tests.
Editor styling via theme.json/EditorTheme.css is preserved (not user theming).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 19:57:58 +01:00
|
|
|
import type { SidebarSelection, SidebarFilter, VaultEntry } from '../types'
|
2026-03-18 03:43:23 +01:00
|
|
|
import type { NoteListFilter } from '../utils/noteListHelpers'
|
2026-02-25 13:31:19 +01:00
|
|
|
import type { ViewMode } from './useViewMode'
|
2026-04-16 01:36:44 +02:00
|
|
|
import type { NoteListMultiSelectionCommands } from '../components/note-list/multiSelectionCommands'
|
2026-02-25 13:31:19 +01:00
|
|
|
|
|
|
|
|
interface AppCommandsConfig {
|
|
|
|
|
activeTabPath: string | null
|
|
|
|
|
activeTabPathRef: React.MutableRefObject<string | null>
|
|
|
|
|
entries: VaultEntry[]
|
2026-04-06 10:29:27 +02:00
|
|
|
visibleNotesRef: React.RefObject<VaultEntry[]>
|
2026-04-16 01:36:44 +02:00
|
|
|
multiSelectionCommandRef: React.MutableRefObject<NoteListMultiSelectionCommands | null>
|
2026-02-25 13:31:19 +01:00
|
|
|
modifiedCount: number
|
|
|
|
|
selection: SidebarSelection
|
|
|
|
|
onQuickOpen: () => void
|
|
|
|
|
onCommandPalette: () => void
|
feat: full-text search with qmd backend and SearchPanel UI (Cmd+Shift+F) (#64)
* feat: add search backend (qmd CLI) and design file
- Add search.rs: qmd integration for keyword (BM25), semantic (vsearch),
and hybrid search modes via CLI JSON output
- Register search_vault Tauri command in lib.rs
- Design file with 3 frames: empty, results, no-results states
- Fix pre-existing test failures: install @tauri-apps/plugin-opener,
add mock in test setup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add SearchPanel UI with Cmd+Shift+F shortcut
- SearchPanel component: full-text search overlay with keyword/semantic
mode toggle, debounced search (200ms), arrow key navigation, result
count + elapsed time display, note type badges from vault entries
- Cmd+Shift+F shortcut registered in useAppKeyboard
- Mock search_vault handler in mock-tauri for browser dev mode
- SearchResult/SearchResponse types in types.ts
- Tests: 15 new tests for SearchPanel + 2 for keyboard shortcut
- scrollIntoView mock in test setup for jsdom compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: correct SearchPanel imports for Tauri/browser dual-mode
Use invoke from @tauri-apps/api/core and mockInvoke from mock-tauri
with a searchCall wrapper, fixing the TypeScript build error.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: make test_detect_collection_fallback robust when qmd not installed
* fix: reset localStorage between App tests to prevent view mode state leak
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 17:09:50 +01:00
|
|
|
onSearch: () => void
|
2026-02-25 13:31:19 +01:00
|
|
|
onCreateNote: () => void
|
2026-02-28 19:13:29 +01:00
|
|
|
onCreateNoteOfType: (type: string) => void
|
2026-02-25 13:31:19 +01:00
|
|
|
onSave: () => void
|
|
|
|
|
onOpenSettings: () => void
|
2026-04-10 12:45:37 +02:00
|
|
|
onOpenFeedback?: () => void
|
2026-04-06 12:21:56 +02:00
|
|
|
onDeleteNote: (path: string) => void
|
2026-02-25 13:31:19 +01:00
|
|
|
onArchiveNote: (path: string) => void
|
|
|
|
|
onUnarchiveNote: (path: string) => void
|
|
|
|
|
onCommitPush: () => void
|
2026-03-19 09:51:06 +01:00
|
|
|
onPull?: () => void
|
2026-03-03 02:27:42 +01:00
|
|
|
onResolveConflicts?: () => void
|
2026-02-25 13:31:19 +01:00
|
|
|
onSetViewMode: (mode: ViewMode) => void
|
|
|
|
|
onToggleInspector: () => void
|
2026-03-03 02:00:48 +01:00
|
|
|
onToggleDiff?: () => void
|
2026-03-02 18:38:25 +01:00
|
|
|
onToggleRawEditor?: () => void
|
2026-03-03 02:00:48 +01:00
|
|
|
activeNoteModified: boolean
|
2026-02-28 12:41:57 +01:00
|
|
|
onZoomIn: () => void
|
|
|
|
|
onZoomOut: () => void
|
|
|
|
|
onZoomReset: () => void
|
|
|
|
|
zoomLevel: number
|
2026-02-25 13:31:19 +01:00
|
|
|
onSelect: (sel: SidebarSelection) => void
|
2026-04-10 13:52:39 +02:00
|
|
|
showInbox?: boolean
|
2026-02-25 13:31:19 +01:00
|
|
|
onReplaceActiveTab: (entry: VaultEntry) => void
|
|
|
|
|
onSelectNote: (entry: VaultEntry) => void
|
2026-02-25 19:39:12 +01:00
|
|
|
onGoBack?: () => void
|
|
|
|
|
onGoForward?: () => void
|
|
|
|
|
canGoBack?: boolean
|
|
|
|
|
canGoForward?: boolean
|
2026-03-01 16:04:51 +01:00
|
|
|
onOpenVault?: () => void
|
2026-03-03 00:31:10 +01:00
|
|
|
onCreateType?: () => void
|
2026-03-02 05:00:29 +01:00
|
|
|
onToggleAIChat?: () => void
|
2026-03-02 23:48:01 +01:00
|
|
|
onCheckForUpdates?: () => void
|
2026-03-03 02:26:41 +01:00
|
|
|
onRemoveActiveVault?: () => void
|
|
|
|
|
onRestoreGettingStarted?: () => void
|
|
|
|
|
isGettingStartedHidden?: boolean
|
|
|
|
|
vaultCount?: number
|
2026-03-04 13:11:58 +01:00
|
|
|
mcpStatus?: string
|
|
|
|
|
onInstallMcp?: () => void
|
2026-04-14 11:55:48 +02:00
|
|
|
aiAgentsStatus?: AiAgentsStatus
|
2026-04-14 14:16:55 +02:00
|
|
|
vaultAiGuidanceStatus?: VaultAiGuidanceStatus
|
2026-04-13 19:37:59 +02:00
|
|
|
onOpenAiAgents?: () => void
|
2026-04-14 14:16:55 +02:00
|
|
|
onRestoreVaultAiGuidance?: () => void
|
2026-04-14 11:55:48 +02:00
|
|
|
onSetDefaultAiAgent?: (agent: AiAgentId) => void
|
|
|
|
|
selectedAiAgent?: AiAgentId
|
2026-04-13 19:37:59 +02:00
|
|
|
onCycleDefaultAiAgent?: () => void
|
|
|
|
|
selectedAiAgentLabel?: string
|
2026-04-04 16:40:15 +02:00
|
|
|
claudeCodeStatus?: string
|
|
|
|
|
claudeCodeVersion?: string
|
2026-03-09 00:35:21 +01:00
|
|
|
onReloadVault?: () => void
|
2026-03-07 12:39:55 +01:00
|
|
|
onRepairVault?: () => void
|
2026-03-17 22:42:55 +01:00
|
|
|
onSetNoteIcon?: () => void
|
|
|
|
|
onRemoveNoteIcon?: () => void
|
|
|
|
|
activeNoteHasIcon?: boolean
|
2026-03-18 03:43:23 +01:00
|
|
|
noteListFilter?: NoteListFilter
|
|
|
|
|
onSetNoteListFilter?: (filter: NoteListFilter) => void
|
2026-03-19 08:47:25 +01:00
|
|
|
onOpenInNewWindow?: () => void
|
2026-04-03 17:20:33 +02:00
|
|
|
onToggleFavorite?: (path: string) => void
|
2026-04-04 20:54:16 +02:00
|
|
|
onToggleOrganized?: (path: string) => void
|
2026-04-16 02:18:43 +02:00
|
|
|
onCustomizeNoteListColumns?: () => void
|
|
|
|
|
canCustomizeNoteListColumns?: boolean
|
2026-04-07 20:09:04 +02:00
|
|
|
onRestoreDeletedNote?: () => void
|
|
|
|
|
canRestoreDeletedNote?: boolean
|
2026-02-25 13:31:19 +01:00
|
|
|
}
|
|
|
|
|
|
2026-04-12 23:14:03 +02:00
|
|
|
function createKeyboardActions(
|
|
|
|
|
config: AppCommandsConfig,
|
|
|
|
|
): Omit<Parameters<typeof useAppKeyboard>[0], 'onArchiveNote'> {
|
|
|
|
|
return {
|
2026-02-25 13:31:19 +01:00
|
|
|
onQuickOpen: config.onQuickOpen,
|
|
|
|
|
onCommandPalette: config.onCommandPalette,
|
feat: full-text search with qmd backend and SearchPanel UI (Cmd+Shift+F) (#64)
* feat: add search backend (qmd CLI) and design file
- Add search.rs: qmd integration for keyword (BM25), semantic (vsearch),
and hybrid search modes via CLI JSON output
- Register search_vault Tauri command in lib.rs
- Design file with 3 frames: empty, results, no-results states
- Fix pre-existing test failures: install @tauri-apps/plugin-opener,
add mock in test setup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add SearchPanel UI with Cmd+Shift+F shortcut
- SearchPanel component: full-text search overlay with keyword/semantic
mode toggle, debounced search (200ms), arrow key navigation, result
count + elapsed time display, note type badges from vault entries
- Cmd+Shift+F shortcut registered in useAppKeyboard
- Mock search_vault handler in mock-tauri for browser dev mode
- SearchResult/SearchResponse types in types.ts
- Tests: 15 new tests for SearchPanel + 2 for keyboard shortcut
- scrollIntoView mock in test setup for jsdom compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: correct SearchPanel imports for Tauri/browser dual-mode
Use invoke from @tauri-apps/api/core and mockInvoke from mock-tauri
with a searchCall wrapper, fixing the TypeScript build error.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: make test_detect_collection_fallback robust when qmd not installed
* fix: reset localStorage between App tests to prevent view mode state leak
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 17:09:50 +01:00
|
|
|
onSearch: config.onSearch,
|
2026-02-25 13:31:19 +01:00
|
|
|
onCreateNote: config.onCreateNote,
|
|
|
|
|
onSave: config.onSave,
|
|
|
|
|
onOpenSettings: config.onOpenSettings,
|
2026-04-06 12:21:56 +02:00
|
|
|
onDeleteNote: config.onDeleteNote,
|
2026-02-25 13:31:19 +01:00
|
|
|
onSetViewMode: config.onSetViewMode,
|
2026-02-28 12:41:57 +01:00
|
|
|
onZoomIn: config.onZoomIn,
|
|
|
|
|
onZoomOut: config.onZoomOut,
|
|
|
|
|
onZoomReset: config.onZoomReset,
|
2026-02-25 19:39:12 +01:00
|
|
|
onGoBack: config.onGoBack,
|
|
|
|
|
onGoForward: config.onGoForward,
|
2026-03-02 05:00:29 +01:00
|
|
|
onToggleAIChat: config.onToggleAIChat,
|
2026-03-02 19:12:11 +01:00
|
|
|
onToggleRawEditor: config.onToggleRawEditor,
|
2026-03-30 18:45:45 +02:00
|
|
|
onToggleInspector: config.onToggleInspector,
|
2026-04-03 17:20:33 +02:00
|
|
|
onToggleFavorite: config.onToggleFavorite,
|
2026-04-10 12:08:17 +02:00
|
|
|
onToggleOrganized: config.onToggleOrganized,
|
2026-03-19 08:47:25 +01:00
|
|
|
onOpenInNewWindow: config.onOpenInNewWindow,
|
2026-02-25 13:31:19 +01:00
|
|
|
activeTabPathRef: config.activeTabPathRef,
|
2026-04-16 01:36:44 +02:00
|
|
|
multiSelectionCommandRef: config.multiSelectionCommandRef,
|
2026-04-12 23:14:03 +02:00
|
|
|
}
|
|
|
|
|
}
|
2026-02-25 13:31:19 +01:00
|
|
|
|
2026-04-12 23:14:03 +02:00
|
|
|
function createMenuEventHandlers(
|
|
|
|
|
config: AppCommandsConfig,
|
|
|
|
|
selectFilter: (filter: SidebarFilter) => void,
|
|
|
|
|
viewChanges: () => void,
|
|
|
|
|
): Omit<Parameters<typeof useMenuEvents>[0], 'onArchiveNote'> {
|
|
|
|
|
return {
|
feat: populate macOS menu bar with native menus (File, Edit, View, Window) (#77)
* feat: populate macOS menu bar with File, Edit, View, Window menus
Add complete native macOS menu structure with all app actions:
- Laputa menu: About, Settings (Cmd+,), Hide/Quit
- File: New Note (Cmd+N), Quick Open (Cmd+P), Save (Cmd+S), Close Tab (Cmd+W)
- Edit: standard Undo/Redo/Cut/Copy/Paste/Select All
- View: Editor Only (Cmd+1), Editor+Notes (Cmd+2), All Panels (Cmd+3),
Toggle Inspector, Command Palette (Cmd+K)
- Window: Minimize, Maximize, Close Window
All accelerators registered via Tauri menu API. Menu events dispatched
to frontend via useMenuEvents hook. Save/Close Tab items dynamically
disabled when no note tab is active.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: wrap Enter selection assertion in waitFor for effect re-registration
* fix: resolve rebase conflict markers in menu.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 20:05:24 +01:00
|
|
|
onSetViewMode: config.onSetViewMode,
|
|
|
|
|
onCreateNote: config.onCreateNote,
|
feat: reorganize menu bar with Go, Note, and Vault menus
Add missing command palette commands to menu bar and reorganize into
logical groups: File, Edit, View, Go, Note, Vault, Window. New menus
expose navigation filters, note actions, vault management, themes, and
git operations. Context-sensitive items (archive, trash, diff, raw
editor, commit, conflicts) are greyed out when not applicable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 14:13:54 +01:00
|
|
|
onCreateType: config.onCreateType,
|
feat: populate macOS menu bar with native menus (File, Edit, View, Window) (#77)
* feat: populate macOS menu bar with File, Edit, View, Window menus
Add complete native macOS menu structure with all app actions:
- Laputa menu: About, Settings (Cmd+,), Hide/Quit
- File: New Note (Cmd+N), Quick Open (Cmd+P), Save (Cmd+S), Close Tab (Cmd+W)
- Edit: standard Undo/Redo/Cut/Copy/Paste/Select All
- View: Editor Only (Cmd+1), Editor+Notes (Cmd+2), All Panels (Cmd+3),
Toggle Inspector, Command Palette (Cmd+K)
- Window: Minimize, Maximize, Close Window
All accelerators registered via Tauri menu API. Menu events dispatched
to frontend via useMenuEvents hook. Save/Close Tab items dynamically
disabled when no note tab is active.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: wrap Enter selection assertion in waitFor for effect re-registration
* fix: resolve rebase conflict markers in menu.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 20:05:24 +01:00
|
|
|
onQuickOpen: config.onQuickOpen,
|
|
|
|
|
onSave: config.onSave,
|
|
|
|
|
onOpenSettings: config.onOpenSettings,
|
|
|
|
|
onToggleInspector: config.onToggleInspector,
|
|
|
|
|
onCommandPalette: config.onCommandPalette,
|
2026-02-28 12:41:57 +01:00
|
|
|
onZoomIn: config.onZoomIn,
|
|
|
|
|
onZoomOut: config.onZoomOut,
|
|
|
|
|
onZoomReset: config.onZoomReset,
|
2026-04-06 12:21:56 +02:00
|
|
|
onDeleteNote: config.onDeleteNote,
|
feat: keyboard-first navigation — menu bar shortcuts, note list nav, inspector Tab/Enter (#158)
* feat: keyboard-first navigation — menu bar shortcuts, note list nav, inspector Tab/Enter
- Add missing menu bar items: Archive Note (⌘E), Trash Note (⌘⌫),
Find in Vault (⌘⇧F), Go Back (⌘[), Go Forward (⌘])
- Wire new menu events through useMenuEvents → useAppCommands
- Note list: ↑↓ moves highlight, Enter opens selected note (useNoteListKeyboard hook)
- Inspector properties: Tab between rows, Enter to start editing
- Settings panel: auto-focus first input on open
- Extract StatusDot, StateBadge, noteItemStyle from NoteItem (reduces complexity)
- Extract dispatchActiveTabEvent/dispatchOptionalEvent from useMenuEvents
- 21 new tests (useNoteListKeyboard + useMenuEvents for new events)
- All 1275 frontend tests pass, 319 Rust tests pass
- CodeScene quality gates: passed (NoteItem improved from 22→18 complexity)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* design: keyboard-first-nav wireframes (note list highlight, menu shortcuts, inspector tab nav)
* test: add search.rs coverage for fallback branches (qmd_uri_to_vault_path, extract_clean_snippet)
* chore: exclude search.rs and lib.rs from coverage (qmd integration + Tauri setup code)
---------
Co-authored-by: Test <test@test.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 19:32:15 +01:00
|
|
|
onSearch: config.onSearch,
|
feat: reorganize menu bar with Go, Note, and Vault menus
Add missing command palette commands to menu bar and reorganize into
logical groups: File, Edit, View, Go, Note, Vault, Window. New menus
expose navigation filters, note actions, vault management, themes, and
git operations. Context-sensitive items (archive, trash, diff, raw
editor, commit, conflicts) are greyed out when not applicable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 14:13:54 +01:00
|
|
|
onToggleRawEditor: config.onToggleRawEditor,
|
|
|
|
|
onToggleDiff: config.onToggleDiff,
|
|
|
|
|
onToggleAIChat: config.onToggleAIChat,
|
2026-04-10 12:08:17 +02:00
|
|
|
onToggleOrganized: config.onToggleOrganized,
|
feat: keyboard-first navigation — menu bar shortcuts, note list nav, inspector Tab/Enter (#158)
* feat: keyboard-first navigation — menu bar shortcuts, note list nav, inspector Tab/Enter
- Add missing menu bar items: Archive Note (⌘E), Trash Note (⌘⌫),
Find in Vault (⌘⇧F), Go Back (⌘[), Go Forward (⌘])
- Wire new menu events through useMenuEvents → useAppCommands
- Note list: ↑↓ moves highlight, Enter opens selected note (useNoteListKeyboard hook)
- Inspector properties: Tab between rows, Enter to start editing
- Settings panel: auto-focus first input on open
- Extract StatusDot, StateBadge, noteItemStyle from NoteItem (reduces complexity)
- Extract dispatchActiveTabEvent/dispatchOptionalEvent from useMenuEvents
- 21 new tests (useNoteListKeyboard + useMenuEvents for new events)
- All 1275 frontend tests pass, 319 Rust tests pass
- CodeScene quality gates: passed (NoteItem improved from 22→18 complexity)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* design: keyboard-first-nav wireframes (note list highlight, menu shortcuts, inspector tab nav)
* test: add search.rs coverage for fallback branches (qmd_uri_to_vault_path, extract_clean_snippet)
* chore: exclude search.rs and lib.rs from coverage (qmd integration + Tauri setup code)
---------
Co-authored-by: Test <test@test.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 19:32:15 +01:00
|
|
|
onGoBack: config.onGoBack,
|
|
|
|
|
onGoForward: config.onGoForward,
|
2026-03-03 13:19:09 +01:00
|
|
|
onCheckForUpdates: config.onCheckForUpdates,
|
feat: reorganize menu bar with Go, Note, and Vault menus
Add missing command palette commands to menu bar and reorganize into
logical groups: File, Edit, View, Go, Note, Vault, Window. New menus
expose navigation filters, note actions, vault management, themes, and
git operations. Context-sensitive items (archive, trash, diff, raw
editor, commit, conflicts) are greyed out when not applicable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 14:13:54 +01:00
|
|
|
onSelectFilter: selectFilter,
|
|
|
|
|
onOpenVault: config.onOpenVault,
|
|
|
|
|
onRemoveActiveVault: config.onRemoveActiveVault,
|
|
|
|
|
onRestoreGettingStarted: config.onRestoreGettingStarted,
|
|
|
|
|
onCommitPush: config.onCommitPush,
|
2026-03-19 09:51:06 +01:00
|
|
|
onPull: config.onPull,
|
feat: reorganize menu bar with Go, Note, and Vault menus
Add missing command palette commands to menu bar and reorganize into
logical groups: File, Edit, View, Go, Note, Vault, Window. New menus
expose navigation filters, note actions, vault management, themes, and
git operations. Context-sensitive items (archive, trash, diff, raw
editor, commit, conflicts) are greyed out when not applicable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 14:13:54 +01:00
|
|
|
onResolveConflicts: config.onResolveConflicts,
|
|
|
|
|
onViewChanges: viewChanges,
|
|
|
|
|
onInstallMcp: config.onInstallMcp,
|
2026-03-09 00:35:21 +01:00
|
|
|
onReloadVault: config.onReloadVault,
|
2026-03-07 12:39:55 +01:00
|
|
|
onRepairVault: config.onRepairVault,
|
2026-03-19 08:47:25 +01:00
|
|
|
onOpenInNewWindow: config.onOpenInNewWindow,
|
2026-04-07 20:09:04 +02:00
|
|
|
onRestoreDeletedNote: config.onRestoreDeletedNote,
|
feat: populate macOS menu bar with native menus (File, Edit, View, Window) (#77)
* feat: populate macOS menu bar with File, Edit, View, Window menus
Add complete native macOS menu structure with all app actions:
- Laputa menu: About, Settings (Cmd+,), Hide/Quit
- File: New Note (Cmd+N), Quick Open (Cmd+P), Save (Cmd+S), Close Tab (Cmd+W)
- Edit: standard Undo/Redo/Cut/Copy/Paste/Select All
- View: Editor Only (Cmd+1), Editor+Notes (Cmd+2), All Panels (Cmd+3),
Toggle Inspector, Command Palette (Cmd+K)
- Window: Minimize, Maximize, Close Window
All accelerators registered via Tauri menu API. Menu events dispatched
to frontend via useMenuEvents hook. Save/Close Tab items dynamically
disabled when no note tab is active.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: wrap Enter selection assertion in waitFor for effect re-registration
* fix: resolve rebase conflict markers in menu.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 20:05:24 +01:00
|
|
|
activeTabPathRef: config.activeTabPathRef,
|
2026-04-16 01:36:44 +02:00
|
|
|
multiSelectionCommandRef: config.multiSelectionCommandRef,
|
feat: populate macOS menu bar with native menus (File, Edit, View, Window) (#77)
* feat: populate macOS menu bar with File, Edit, View, Window menus
Add complete native macOS menu structure with all app actions:
- Laputa menu: About, Settings (Cmd+,), Hide/Quit
- File: New Note (Cmd+N), Quick Open (Cmd+P), Save (Cmd+S), Close Tab (Cmd+W)
- Edit: standard Undo/Redo/Cut/Copy/Paste/Select All
- View: Editor Only (Cmd+1), Editor+Notes (Cmd+2), All Panels (Cmd+3),
Toggle Inspector, Command Palette (Cmd+K)
- Window: Minimize, Maximize, Close Window
All accelerators registered via Tauri menu API. Menu events dispatched
to frontend via useMenuEvents hook. Save/Close Tab items dynamically
disabled when no note tab is active.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: wrap Enter selection assertion in waitFor for effect re-registration
* fix: resolve rebase conflict markers in menu.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 20:05:24 +01:00
|
|
|
activeTabPath: config.activeTabPath,
|
feat: reorganize menu bar with Go, Note, and Vault menus
Add missing command palette commands to menu bar and reorganize into
logical groups: File, Edit, View, Go, Note, Vault, Window. New menus
expose navigation filters, note actions, vault management, themes, and
git operations. Context-sensitive items (archive, trash, diff, raw
editor, commit, conflicts) are greyed out when not applicable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 14:13:54 +01:00
|
|
|
modifiedCount: config.modifiedCount,
|
2026-04-07 20:09:04 +02:00
|
|
|
hasRestorableDeletedNote: config.canRestoreDeletedNote,
|
2026-04-12 23:14:03 +02:00
|
|
|
}
|
|
|
|
|
}
|
feat: populate macOS menu bar with native menus (File, Edit, View, Window) (#77)
* feat: populate macOS menu bar with File, Edit, View, Window menus
Add complete native macOS menu structure with all app actions:
- Laputa menu: About, Settings (Cmd+,), Hide/Quit
- File: New Note (Cmd+N), Quick Open (Cmd+P), Save (Cmd+S), Close Tab (Cmd+W)
- Edit: standard Undo/Redo/Cut/Copy/Paste/Select All
- View: Editor Only (Cmd+1), Editor+Notes (Cmd+2), All Panels (Cmd+3),
Toggle Inspector, Command Palette (Cmd+K)
- Window: Minimize, Maximize, Close Window
All accelerators registered via Tauri menu API. Menu events dispatched
to frontend via useMenuEvents hook. Save/Close Tab items dynamically
disabled when no note tab is active.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: wrap Enter selection assertion in waitFor for effect re-registration
* fix: resolve rebase conflict markers in menu.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 20:05:24 +01:00
|
|
|
|
2026-04-12 23:14:03 +02:00
|
|
|
function createCommandRegistryConfig(config: AppCommandsConfig): Parameters<typeof useCommandRegistry>[0] {
|
|
|
|
|
return {
|
2026-02-25 13:31:19 +01:00
|
|
|
activeTabPath: config.activeTabPath,
|
|
|
|
|
entries: config.entries,
|
|
|
|
|
modifiedCount: config.modifiedCount,
|
|
|
|
|
onQuickOpen: config.onQuickOpen,
|
|
|
|
|
onCreateNote: config.onCreateNote,
|
2026-02-28 19:13:29 +01:00
|
|
|
onCreateNoteOfType: config.onCreateNoteOfType,
|
2026-02-25 13:31:19 +01:00
|
|
|
onSave: config.onSave,
|
|
|
|
|
onOpenSettings: config.onOpenSettings,
|
2026-04-10 12:45:37 +02:00
|
|
|
onOpenFeedback: config.onOpenFeedback,
|
2026-04-06 12:21:56 +02:00
|
|
|
onDeleteNote: config.onDeleteNote,
|
2026-02-25 13:31:19 +01:00
|
|
|
onArchiveNote: config.onArchiveNote,
|
|
|
|
|
onUnarchiveNote: config.onUnarchiveNote,
|
|
|
|
|
onCommitPush: config.onCommitPush,
|
2026-03-19 09:51:06 +01:00
|
|
|
onPull: config.onPull,
|
2026-03-03 02:27:42 +01:00
|
|
|
onResolveConflicts: config.onResolveConflicts,
|
2026-02-25 13:31:19 +01:00
|
|
|
onSetViewMode: config.onSetViewMode,
|
|
|
|
|
onToggleInspector: config.onToggleInspector,
|
2026-03-03 02:00:48 +01:00
|
|
|
onToggleDiff: config.onToggleDiff,
|
2026-03-02 18:38:25 +01:00
|
|
|
onToggleRawEditor: config.onToggleRawEditor,
|
feat: reorganize menu bar with Go, Note, and Vault menus
Add missing command palette commands to menu bar and reorganize into
logical groups: File, Edit, View, Go, Note, Vault, Window. New menus
expose navigation filters, note actions, vault management, themes, and
git operations. Context-sensitive items (archive, trash, diff, raw
editor, commit, conflicts) are greyed out when not applicable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 14:13:54 +01:00
|
|
|
onToggleAIChat: config.onToggleAIChat,
|
|
|
|
|
onOpenVault: config.onOpenVault,
|
2026-03-03 02:00:48 +01:00
|
|
|
activeNoteModified: config.activeNoteModified,
|
2026-02-28 12:41:57 +01:00
|
|
|
onZoomIn: config.onZoomIn,
|
|
|
|
|
onZoomOut: config.onZoomOut,
|
|
|
|
|
onZoomReset: config.onZoomReset,
|
|
|
|
|
zoomLevel: config.zoomLevel,
|
2026-02-25 13:31:19 +01:00
|
|
|
onSelect: config.onSelect,
|
2026-04-10 13:52:39 +02:00
|
|
|
showInbox: config.showInbox,
|
2026-02-25 19:39:12 +01:00
|
|
|
onGoBack: config.onGoBack,
|
|
|
|
|
onGoForward: config.onGoForward,
|
|
|
|
|
canGoBack: config.canGoBack,
|
|
|
|
|
canGoForward: config.canGoForward,
|
2026-03-02 23:48:01 +01:00
|
|
|
onCheckForUpdates: config.onCheckForUpdates,
|
feat: reorganize menu bar with Go, Note, and Vault menus
Add missing command palette commands to menu bar and reorganize into
logical groups: File, Edit, View, Go, Note, Vault, Window. New menus
expose navigation filters, note actions, vault management, themes, and
git operations. Context-sensitive items (archive, trash, diff, raw
editor, commit, conflicts) are greyed out when not applicable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 14:13:54 +01:00
|
|
|
onCreateType: config.onCreateType,
|
2026-03-03 02:26:41 +01:00
|
|
|
onRemoveActiveVault: config.onRemoveActiveVault,
|
|
|
|
|
onRestoreGettingStarted: config.onRestoreGettingStarted,
|
|
|
|
|
isGettingStartedHidden: config.isGettingStartedHidden,
|
|
|
|
|
vaultCount: config.vaultCount,
|
2026-03-04 13:11:58 +01:00
|
|
|
mcpStatus: config.mcpStatus,
|
|
|
|
|
onInstallMcp: config.onInstallMcp,
|
2026-04-14 11:55:48 +02:00
|
|
|
aiAgentsStatus: config.aiAgentsStatus,
|
2026-04-14 14:16:55 +02:00
|
|
|
vaultAiGuidanceStatus: config.vaultAiGuidanceStatus,
|
2026-04-13 19:37:59 +02:00
|
|
|
onOpenAiAgents: config.onOpenAiAgents,
|
2026-04-14 14:16:55 +02:00
|
|
|
onRestoreVaultAiGuidance: config.onRestoreVaultAiGuidance,
|
2026-04-14 11:55:48 +02:00
|
|
|
onSetDefaultAiAgent: config.onSetDefaultAiAgent,
|
|
|
|
|
selectedAiAgent: config.selectedAiAgent,
|
2026-04-13 19:37:59 +02:00
|
|
|
onCycleDefaultAiAgent: config.onCycleDefaultAiAgent,
|
|
|
|
|
selectedAiAgentLabel: config.selectedAiAgentLabel,
|
2026-03-09 00:35:21 +01:00
|
|
|
onReloadVault: config.onReloadVault,
|
2026-03-07 12:39:55 +01:00
|
|
|
onRepairVault: config.onRepairVault,
|
2026-03-17 22:42:55 +01:00
|
|
|
onSetNoteIcon: config.onSetNoteIcon,
|
|
|
|
|
onRemoveNoteIcon: config.onRemoveNoteIcon,
|
|
|
|
|
activeNoteHasIcon: config.activeNoteHasIcon,
|
2026-03-18 03:43:23 +01:00
|
|
|
selection: config.selection,
|
|
|
|
|
noteListFilter: config.noteListFilter,
|
|
|
|
|
onSetNoteListFilter: config.onSetNoteListFilter,
|
2026-03-19 08:47:25 +01:00
|
|
|
onOpenInNewWindow: config.onOpenInNewWindow,
|
2026-04-04 20:54:16 +02:00
|
|
|
onToggleFavorite: config.onToggleFavorite,
|
|
|
|
|
onToggleOrganized: config.onToggleOrganized,
|
2026-04-16 02:18:43 +02:00
|
|
|
onCustomizeNoteListColumns: config.onCustomizeNoteListColumns,
|
|
|
|
|
canCustomizeNoteListColumns: config.canCustomizeNoteListColumns,
|
2026-04-07 20:09:04 +02:00
|
|
|
onRestoreDeletedNote: config.onRestoreDeletedNote,
|
|
|
|
|
canRestoreDeletedNote: config.canRestoreDeletedNote,
|
2026-04-12 23:14:03 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Sets up keyboard shortcuts, command registry, menu events, and keyboard navigation. */
|
|
|
|
|
export function useAppCommands(config: AppCommandsConfig): CommandAction[] {
|
|
|
|
|
const entriesRef = useRef(config.entries)
|
|
|
|
|
// eslint-disable-next-line react-hooks/refs
|
|
|
|
|
entriesRef.current = config.entries
|
|
|
|
|
|
|
|
|
|
const toggleArchive = useCallback((path: string) => {
|
|
|
|
|
const entry = entriesRef.current.find(e => e.path === path)
|
|
|
|
|
;(entry?.archived ? config.onUnarchiveNote : config.onArchiveNote)(path)
|
|
|
|
|
}, [config.onArchiveNote, config.onUnarchiveNote])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const { onSelect } = config
|
|
|
|
|
|
|
|
|
|
const selectFilter = useCallback((filter: SidebarFilter) => {
|
|
|
|
|
const safeFilter = !config.showInbox && filter === 'inbox' ? 'all' : filter
|
|
|
|
|
onSelect({ kind: 'filter', filter: safeFilter })
|
|
|
|
|
}, [config.showInbox, onSelect])
|
|
|
|
|
|
|
|
|
|
const viewChanges = useCallback(() => {
|
|
|
|
|
onSelect({ kind: 'filter', filter: 'changes' })
|
|
|
|
|
}, [onSelect])
|
|
|
|
|
|
|
|
|
|
const keyboardActions = createKeyboardActions(config)
|
|
|
|
|
const menuEventHandlers = createMenuEventHandlers(config, selectFilter, viewChanges)
|
|
|
|
|
|
|
|
|
|
useAppKeyboard({ ...keyboardActions, onArchiveNote: toggleArchive })
|
|
|
|
|
|
|
|
|
|
useMenuEvents({ ...menuEventHandlers, onArchiveNote: toggleArchive })
|
|
|
|
|
|
|
|
|
|
const commands = useCommandRegistry(createCommandRegistryConfig(config))
|
2026-02-25 13:31:19 +01:00
|
|
|
|
|
|
|
|
useKeyboardNavigation({
|
|
|
|
|
activeTabPath: config.activeTabPath,
|
2026-04-06 10:29:27 +02:00
|
|
|
visibleNotesRef: config.visibleNotesRef,
|
2026-02-25 13:31:19 +01:00
|
|
|
onReplaceActiveTab: config.onReplaceActiveTab,
|
|
|
|
|
onSelectNote: config.onSelectNote,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return commands
|
|
|
|
|
}
|