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-26 08:18:47 +02:00
|
|
|
import type { AppLocale, UiLanguagePreference } from '../lib/i18n'
|
2026-04-29 02:35:52 +02:00
|
|
|
import type { ThemeMode } from '../lib/themeMode'
|
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'
|
2026-04-29 19:26:24 +02:00
|
|
|
import type { NoteWidthMode, SidebarSelection, SidebarFilter, VaultEntry } from '../types'
|
2026-04-19 16:18:35 +02:00
|
|
|
import { requestAddRemote } from '../utils/addRemoteEvents'
|
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-04-27 10:12:13 +02:00
|
|
|
onFindInNote?: () => void
|
|
|
|
|
onReplaceInNote?: () => 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-04-28 20:41:07 +02:00
|
|
|
selectedViewName?: string
|
|
|
|
|
onMoveSelectedViewUp?: () => void
|
|
|
|
|
onMoveSelectedViewDown?: () => void
|
|
|
|
|
canMoveSelectedViewUp?: boolean
|
|
|
|
|
canMoveSelectedViewDown?: boolean
|
2026-04-29 19:26:24 +02:00
|
|
|
noteWidth?: NoteWidthMode
|
|
|
|
|
defaultNoteWidth?: NoteWidthMode
|
|
|
|
|
onSetNoteWidth?: (mode: NoteWidthMode) => void
|
|
|
|
|
onSetDefaultNoteWidth?: (mode: NoteWidthMode) => 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-22 17:16:56 +02:00
|
|
|
onRenameFolder?: () => void
|
|
|
|
|
onDeleteFolder?: () => 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-04-19 01:06:40 +02:00
|
|
|
onCreateEmptyVault?: () => void
|
2026-04-19 16:18:35 +02:00
|
|
|
onAddRemote?: () => void
|
|
|
|
|
canAddRemote?: boolean
|
2026-04-26 17:08:14 +02:00
|
|
|
isGitVault?: boolean
|
|
|
|
|
onInitializeGit?: () => 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-04-26 08:18:47 +02:00
|
|
|
locale?: AppLocale
|
|
|
|
|
systemLocale?: AppLocale
|
|
|
|
|
selectedUiLanguage?: UiLanguagePreference
|
|
|
|
|
onSetUiLanguage?: (language: UiLanguagePreference) => void
|
2026-04-29 02:35:52 +02:00
|
|
|
onSetThemeMode?: (mode: ThemeMode) => void
|
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
|
2026-04-22 23:56:00 +02:00
|
|
|
onChangeNoteType?: () => void
|
|
|
|
|
onMoveNoteToFolder?: () => void
|
|
|
|
|
canMoveNoteToFolder?: boolean
|
2026-03-17 22:42:55 +01:00
|
|
|
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-27 01:45:16 +02:00
|
|
|
onRevealActiveFile?: (path: string) => void
|
|
|
|
|
onCopyActiveFilePath?: (path: string) => void
|
|
|
|
|
onOpenActiveFileExternal?: (path: string) => void
|
|
|
|
|
onRevealSelectedFolder?: () => void
|
|
|
|
|
onCopySelectedFolderPath?: () => 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-18 20:31:25 +02:00
|
|
|
noteListColumnsLabel?: string
|
2026-04-07 20:09:04 +02:00
|
|
|
onRestoreDeletedNote?: () => void
|
|
|
|
|
canRestoreDeletedNote?: boolean
|
2026-02-25 13:31:19 +01:00
|
|
|
}
|
|
|
|
|
|
2026-04-19 16:18:35 +02:00
|
|
|
type CommandRegistryConfig = Parameters<typeof useCommandRegistry>[0]
|
|
|
|
|
type CommandRegistrySelectionState = Pick<
|
|
|
|
|
CommandRegistryConfig,
|
|
|
|
|
| 'activeNoteModified'
|
|
|
|
|
| 'onZoomIn'
|
|
|
|
|
| 'onZoomOut'
|
|
|
|
|
| 'onZoomReset'
|
|
|
|
|
| 'zoomLevel'
|
|
|
|
|
| 'onSelect'
|
2026-04-22 17:16:56 +02:00
|
|
|
| 'onRenameFolder'
|
|
|
|
|
| 'onDeleteFolder'
|
2026-04-27 01:45:16 +02:00
|
|
|
| 'onRevealSelectedFolder'
|
|
|
|
|
| 'onCopySelectedFolderPath'
|
2026-04-19 16:18:35 +02:00
|
|
|
| 'showInbox'
|
|
|
|
|
| 'onGoBack'
|
|
|
|
|
| 'onGoForward'
|
|
|
|
|
| 'canGoBack'
|
|
|
|
|
| 'canGoForward'
|
|
|
|
|
| 'selection'
|
|
|
|
|
>
|
|
|
|
|
type CommandRegistryCoreActions = Pick<
|
|
|
|
|
CommandRegistryConfig,
|
|
|
|
|
| 'activeTabPath'
|
|
|
|
|
| 'entries'
|
|
|
|
|
| 'modifiedCount'
|
|
|
|
|
| 'onQuickOpen'
|
|
|
|
|
| 'onCreateNote'
|
|
|
|
|
| 'onCreateNoteOfType'
|
|
|
|
|
| 'onSave'
|
2026-04-27 10:12:13 +02:00
|
|
|
| 'onFindInNote'
|
|
|
|
|
| 'onReplaceInNote'
|
2026-04-19 16:18:35 +02:00
|
|
|
| 'onOpenSettings'
|
|
|
|
|
| 'onOpenFeedback'
|
|
|
|
|
| 'onDeleteNote'
|
|
|
|
|
| 'onArchiveNote'
|
|
|
|
|
| 'onUnarchiveNote'
|
|
|
|
|
| 'onCommitPush'
|
|
|
|
|
| 'onPull'
|
|
|
|
|
| 'onResolveConflicts'
|
|
|
|
|
| 'onSetViewMode'
|
|
|
|
|
| 'onToggleInspector'
|
|
|
|
|
| 'onToggleDiff'
|
|
|
|
|
| 'onToggleRawEditor'
|
2026-04-28 20:41:07 +02:00
|
|
|
| 'selectedViewName'
|
|
|
|
|
| 'onMoveSelectedViewUp'
|
|
|
|
|
| 'onMoveSelectedViewDown'
|
|
|
|
|
| 'canMoveSelectedViewUp'
|
|
|
|
|
| 'canMoveSelectedViewDown'
|
2026-04-29 19:26:24 +02:00
|
|
|
| 'noteWidth'
|
|
|
|
|
| 'defaultNoteWidth'
|
|
|
|
|
| 'onSetNoteWidth'
|
|
|
|
|
| 'onSetDefaultNoteWidth'
|
2026-04-19 16:18:35 +02:00
|
|
|
| 'onToggleAIChat'
|
|
|
|
|
>
|
|
|
|
|
type CommandRegistryVaultActions = Pick<
|
|
|
|
|
CommandRegistryConfig,
|
|
|
|
|
| 'onOpenVault'
|
|
|
|
|
| 'onCreateEmptyVault'
|
|
|
|
|
| 'onAddRemote'
|
|
|
|
|
| 'canAddRemote'
|
2026-04-26 17:08:14 +02:00
|
|
|
| 'isGitVault'
|
|
|
|
|
| 'onInitializeGit'
|
2026-04-19 16:18:35 +02:00
|
|
|
| 'onCheckForUpdates'
|
|
|
|
|
| 'onCreateType'
|
2026-04-26 08:18:47 +02:00
|
|
|
| 'locale'
|
|
|
|
|
| 'systemLocale'
|
|
|
|
|
| 'selectedUiLanguage'
|
|
|
|
|
| 'onSetUiLanguage'
|
2026-04-29 02:35:52 +02:00
|
|
|
| 'onSetThemeMode'
|
2026-04-19 16:18:35 +02:00
|
|
|
| 'onRemoveActiveVault'
|
|
|
|
|
| 'onRestoreGettingStarted'
|
|
|
|
|
| 'isGettingStartedHidden'
|
|
|
|
|
| 'vaultCount'
|
|
|
|
|
| 'onReloadVault'
|
|
|
|
|
| 'onRepairVault'
|
|
|
|
|
| 'onOpenInNewWindow'
|
2026-04-27 01:45:16 +02:00
|
|
|
| 'onRevealActiveFile'
|
|
|
|
|
| 'onCopyActiveFilePath'
|
|
|
|
|
| 'onOpenActiveFileExternal'
|
2026-04-19 16:18:35 +02:00
|
|
|
| 'onRestoreDeletedNote'
|
|
|
|
|
| 'canRestoreDeletedNote'
|
|
|
|
|
>
|
|
|
|
|
type CommandRegistryAiActions = Pick<
|
|
|
|
|
CommandRegistryConfig,
|
|
|
|
|
| 'mcpStatus'
|
|
|
|
|
| 'onInstallMcp'
|
|
|
|
|
| 'aiAgentsStatus'
|
|
|
|
|
| 'vaultAiGuidanceStatus'
|
|
|
|
|
| 'onOpenAiAgents'
|
|
|
|
|
| 'onRestoreVaultAiGuidance'
|
|
|
|
|
| 'onSetDefaultAiAgent'
|
|
|
|
|
| 'selectedAiAgent'
|
|
|
|
|
| 'onCycleDefaultAiAgent'
|
|
|
|
|
| 'selectedAiAgentLabel'
|
|
|
|
|
>
|
|
|
|
|
type CommandRegistryNoteActions = Pick<
|
|
|
|
|
CommandRegistryConfig,
|
|
|
|
|
| 'onSetNoteIcon'
|
|
|
|
|
| 'onRemoveNoteIcon'
|
2026-04-22 23:56:00 +02:00
|
|
|
| 'onChangeNoteType'
|
|
|
|
|
| 'onMoveNoteToFolder'
|
|
|
|
|
| 'canMoveNoteToFolder'
|
2026-04-19 16:18:35 +02:00
|
|
|
| 'activeNoteHasIcon'
|
|
|
|
|
| 'noteListFilter'
|
|
|
|
|
| 'onSetNoteListFilter'
|
|
|
|
|
| 'onToggleFavorite'
|
|
|
|
|
| 'onToggleOrganized'
|
|
|
|
|
| 'onCustomizeNoteListColumns'
|
|
|
|
|
| 'canCustomizeNoteListColumns'
|
|
|
|
|
| 'noteListColumnsLabel'
|
|
|
|
|
>
|
|
|
|
|
|
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-04-27 10:12:13 +02:00
|
|
|
onFindInNote: config.onFindInNote,
|
|
|
|
|
onReplaceInNote: config.onReplaceInNote,
|
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'> {
|
2026-04-19 16:18:35 +02:00
|
|
|
return {
|
|
|
|
|
...createMenuEventActionHandlers(config, selectFilter),
|
|
|
|
|
...createMenuEventVaultHandlers(config, viewChanges),
|
|
|
|
|
...createMenuEventState(config),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function createMenuEventActionHandlers(
|
|
|
|
|
config: AppCommandsConfig,
|
|
|
|
|
selectFilter: (filter: SidebarFilter) => void,
|
|
|
|
|
): Pick<
|
|
|
|
|
Omit<Parameters<typeof useMenuEvents>[0], 'onArchiveNote'>,
|
|
|
|
|
| 'onSetViewMode'
|
|
|
|
|
| 'onCreateNote'
|
|
|
|
|
| 'onCreateType'
|
|
|
|
|
| 'onQuickOpen'
|
|
|
|
|
| 'onSave'
|
|
|
|
|
| 'onOpenSettings'
|
|
|
|
|
| 'onToggleInspector'
|
|
|
|
|
| 'onCommandPalette'
|
|
|
|
|
| 'onZoomIn'
|
|
|
|
|
| 'onZoomOut'
|
|
|
|
|
| 'onZoomReset'
|
|
|
|
|
| 'onDeleteNote'
|
2026-04-27 10:12:13 +02:00
|
|
|
| 'onFindInNote'
|
|
|
|
|
| 'onReplaceInNote'
|
2026-04-19 16:18:35 +02:00
|
|
|
| 'onSearch'
|
|
|
|
|
| 'onToggleRawEditor'
|
|
|
|
|
| 'onToggleDiff'
|
|
|
|
|
| 'onToggleAIChat'
|
|
|
|
|
| 'onToggleOrganized'
|
|
|
|
|
| 'onGoBack'
|
|
|
|
|
| 'onGoForward'
|
|
|
|
|
| 'onCheckForUpdates'
|
|
|
|
|
| 'onSelectFilter'
|
|
|
|
|
> {
|
2026-04-12 23:14:03 +02:00
|
|
|
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,
|
2026-04-27 10:12:13 +02:00
|
|
|
onFindInNote: config.onFindInNote,
|
|
|
|
|
onReplaceInNote: config.onReplaceInNote,
|
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,
|
2026-04-19 16:18:35 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function createMenuEventVaultHandlers(
|
|
|
|
|
config: AppCommandsConfig,
|
|
|
|
|
viewChanges: () => void,
|
|
|
|
|
): Pick<
|
|
|
|
|
Omit<Parameters<typeof useMenuEvents>[0], 'onArchiveNote'>,
|
|
|
|
|
| 'onOpenVault'
|
|
|
|
|
| 'onRemoveActiveVault'
|
|
|
|
|
| 'onRestoreGettingStarted'
|
|
|
|
|
| 'onAddRemote'
|
|
|
|
|
| 'onCommitPush'
|
|
|
|
|
| 'onPull'
|
|
|
|
|
| 'onResolveConflicts'
|
|
|
|
|
| 'onViewChanges'
|
|
|
|
|
| 'onInstallMcp'
|
|
|
|
|
| 'onReloadVault'
|
|
|
|
|
| 'onRepairVault'
|
|
|
|
|
| 'onOpenInNewWindow'
|
|
|
|
|
| 'onRestoreDeletedNote'
|
|
|
|
|
> {
|
|
|
|
|
return {
|
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
|
|
|
onOpenVault: config.onOpenVault,
|
|
|
|
|
onRemoveActiveVault: config.onRemoveActiveVault,
|
|
|
|
|
onRestoreGettingStarted: config.onRestoreGettingStarted,
|
2026-04-19 16:18:35 +02:00
|
|
|
onAddRemote: config.onAddRemote ?? requestAddRemote,
|
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
|
|
|
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,
|
2026-04-19 16:18:35 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function createMenuEventState(
|
|
|
|
|
config: AppCommandsConfig,
|
|
|
|
|
): Pick<
|
|
|
|
|
Omit<Parameters<typeof useMenuEvents>[0], 'onArchiveNote'>,
|
|
|
|
|
| 'activeTabPathRef'
|
|
|
|
|
| 'multiSelectionCommandRef'
|
|
|
|
|
| 'activeTabPath'
|
|
|
|
|
| 'modifiedCount'
|
|
|
|
|
| 'hasRestorableDeletedNote'
|
|
|
|
|
| 'hasNoRemote'
|
|
|
|
|
> {
|
|
|
|
|
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
|
|
|
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-19 16:18:35 +02:00
|
|
|
hasNoRemote: config.canAddRemote ?? true,
|
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-19 16:18:35 +02:00
|
|
|
function createCommandRegistrySelectionConfig(
|
|
|
|
|
config: AppCommandsConfig,
|
|
|
|
|
): CommandRegistrySelectionState {
|
|
|
|
|
return {
|
|
|
|
|
activeNoteModified: config.activeNoteModified,
|
|
|
|
|
onZoomIn: config.onZoomIn,
|
|
|
|
|
onZoomOut: config.onZoomOut,
|
|
|
|
|
onZoomReset: config.onZoomReset,
|
|
|
|
|
zoomLevel: config.zoomLevel,
|
|
|
|
|
onSelect: config.onSelect,
|
2026-04-22 17:16:56 +02:00
|
|
|
onRenameFolder: config.onRenameFolder,
|
|
|
|
|
onDeleteFolder: config.onDeleteFolder,
|
2026-04-27 01:45:16 +02:00
|
|
|
onRevealSelectedFolder: config.onRevealSelectedFolder,
|
|
|
|
|
onCopySelectedFolderPath: config.onCopySelectedFolderPath,
|
2026-04-19 16:18:35 +02:00
|
|
|
showInbox: config.showInbox,
|
|
|
|
|
onGoBack: config.onGoBack,
|
|
|
|
|
onGoForward: config.onGoForward,
|
|
|
|
|
canGoBack: config.canGoBack,
|
|
|
|
|
canGoForward: config.canGoForward,
|
|
|
|
|
selection: config.selection,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function createCommandRegistryCoreConfig(
|
|
|
|
|
config: AppCommandsConfig,
|
|
|
|
|
): CommandRegistryCoreActions {
|
2026-04-12 23:14:03 +02:00
|
|
|
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,
|
2026-04-28 20:41:07 +02:00
|
|
|
selectedViewName: config.selectedViewName,
|
|
|
|
|
onMoveSelectedViewUp: config.onMoveSelectedViewUp,
|
|
|
|
|
onMoveSelectedViewDown: config.onMoveSelectedViewDown,
|
|
|
|
|
canMoveSelectedViewUp: config.canMoveSelectedViewUp,
|
|
|
|
|
canMoveSelectedViewDown: config.canMoveSelectedViewDown,
|
2026-04-27 10:12:13 +02:00
|
|
|
onFindInNote: config.onFindInNote,
|
|
|
|
|
onReplaceInNote: config.onReplaceInNote,
|
2026-04-29 19:26:24 +02:00
|
|
|
noteWidth: config.noteWidth,
|
|
|
|
|
defaultNoteWidth: config.defaultNoteWidth,
|
|
|
|
|
onSetNoteWidth: config.onSetNoteWidth,
|
|
|
|
|
onSetDefaultNoteWidth: config.onSetDefaultNoteWidth,
|
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,
|
2026-04-19 16:18:35 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function createCommandRegistryVaultConfig(
|
|
|
|
|
config: AppCommandsConfig,
|
|
|
|
|
): CommandRegistryVaultActions {
|
|
|
|
|
return {
|
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
|
|
|
onOpenVault: config.onOpenVault,
|
2026-04-19 01:06:40 +02:00
|
|
|
onCreateEmptyVault: config.onCreateEmptyVault,
|
2026-04-19 16:18:35 +02:00
|
|
|
onAddRemote: config.onAddRemote ?? requestAddRemote,
|
|
|
|
|
canAddRemote: config.canAddRemote ?? true,
|
2026-04-26 17:08:14 +02:00
|
|
|
isGitVault: config.isGitVault,
|
|
|
|
|
onInitializeGit: config.onInitializeGit,
|
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-04-26 08:18:47 +02:00
|
|
|
locale: config.locale,
|
|
|
|
|
systemLocale: config.systemLocale,
|
|
|
|
|
selectedUiLanguage: config.selectedUiLanguage,
|
|
|
|
|
onSetUiLanguage: config.onSetUiLanguage,
|
2026-04-29 02:35:52 +02:00
|
|
|
onSetThemeMode: config.onSetThemeMode,
|
2026-03-03 02:26:41 +01:00
|
|
|
onRemoveActiveVault: config.onRemoveActiveVault,
|
|
|
|
|
onRestoreGettingStarted: config.onRestoreGettingStarted,
|
|
|
|
|
isGettingStartedHidden: config.isGettingStartedHidden,
|
|
|
|
|
vaultCount: config.vaultCount,
|
2026-04-19 16:18:35 +02:00
|
|
|
onReloadVault: config.onReloadVault,
|
|
|
|
|
onRepairVault: config.onRepairVault,
|
|
|
|
|
onOpenInNewWindow: config.onOpenInNewWindow,
|
2026-04-27 01:45:16 +02:00
|
|
|
onRevealActiveFile: config.onRevealActiveFile,
|
|
|
|
|
onCopyActiveFilePath: config.onCopyActiveFilePath,
|
|
|
|
|
onOpenActiveFileExternal: config.onOpenActiveFileExternal,
|
2026-04-19 16:18:35 +02:00
|
|
|
onRestoreDeletedNote: config.onRestoreDeletedNote,
|
|
|
|
|
canRestoreDeletedNote: config.canRestoreDeletedNote,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function createCommandRegistryAiConfig(
|
|
|
|
|
config: AppCommandsConfig,
|
|
|
|
|
): CommandRegistryAiActions {
|
|
|
|
|
return {
|
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-04-19 16:18:35 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function createCommandRegistryNoteConfig(
|
|
|
|
|
config: AppCommandsConfig,
|
|
|
|
|
): CommandRegistryNoteActions {
|
|
|
|
|
return {
|
2026-03-17 22:42:55 +01:00
|
|
|
onSetNoteIcon: config.onSetNoteIcon,
|
|
|
|
|
onRemoveNoteIcon: config.onRemoveNoteIcon,
|
2026-04-22 23:56:00 +02:00
|
|
|
onChangeNoteType: config.onChangeNoteType,
|
|
|
|
|
onMoveNoteToFolder: config.onMoveNoteToFolder,
|
|
|
|
|
canMoveNoteToFolder: config.canMoveNoteToFolder,
|
2026-03-17 22:42:55 +01:00
|
|
|
activeNoteHasIcon: config.activeNoteHasIcon,
|
2026-03-18 03:43:23 +01:00
|
|
|
noteListFilter: config.noteListFilter,
|
|
|
|
|
onSetNoteListFilter: config.onSetNoteListFilter,
|
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-18 20:31:25 +02:00
|
|
|
noteListColumnsLabel: config.noteListColumnsLabel,
|
2026-04-19 16:18:35 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function createCommandRegistryConfig(config: AppCommandsConfig): CommandRegistryConfig {
|
|
|
|
|
return {
|
|
|
|
|
...createCommandRegistryCoreConfig(config),
|
|
|
|
|
...createCommandRegistrySelectionConfig(config),
|
|
|
|
|
...createCommandRegistryVaultConfig(config),
|
|
|
|
|
...createCommandRegistryAiConfig(config),
|
|
|
|
|
...createCommandRegistryNoteConfig(config),
|
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
|
|
|
|
|
}
|