void
+ showInbox: boolean
inboxCount: number
activeCount: number
archivedCount: number
}) {
return (
- onSelect({ kind: 'filter', filter: 'inbox' })}
- />
+ {showInbox && (
+ onSelect({ kind: 'filter', filter: 'inbox' })}
+ />
+ )}
, "onChange"> {
+ checked?: boolean
+ onCheckedChange?: (checked: boolean) => void
+}
+
+function Switch({
+ checked = false,
+ className,
+ onCheckedChange,
+ onClick,
+ type = "button",
+ ...props
+}: SwitchProps) {
+ return (
+
+ )
+}
+
+export { Switch }
diff --git a/src/hooks/commands/navigationCommands.ts b/src/hooks/commands/navigationCommands.ts
index 0d1692f7..8247a3bf 100644
--- a/src/hooks/commands/navigationCommands.ts
+++ b/src/hooks/commands/navigationCommands.ts
@@ -4,6 +4,7 @@ import type { SidebarSelection } from '../../types'
interface NavigationCommandsConfig {
onQuickOpen: () => void
onSelect: (sel: SidebarSelection) => void
+ showInbox?: boolean
onOpenDailyNote: () => void
onGoBack?: () => void
onGoForward?: () => void
@@ -12,15 +13,25 @@ interface NavigationCommandsConfig {
}
export function buildNavigationCommands(config: NavigationCommandsConfig): CommandAction[] {
- const { onQuickOpen, onSelect, onGoBack, onGoForward, canGoBack, canGoForward } = config
- return [
+ const { onQuickOpen, onSelect, showInbox = true, onGoBack, onGoForward, canGoBack, canGoForward } = config
+ const commands: CommandAction[] = [
{ id: 'search-notes', label: 'Search Notes', group: 'Navigation', shortcut: '⌘P', keywords: ['find', 'open', 'quick'], enabled: true, execute: onQuickOpen },
{ id: 'go-all', label: 'Go to All Notes', group: 'Navigation', keywords: ['filter'], enabled: true, execute: () => onSelect({ kind: 'filter', filter: 'all' }) },
{ id: 'go-archived', label: 'Go to Archived', group: 'Navigation', keywords: [], enabled: true, execute: () => onSelect({ kind: 'filter', filter: 'archived' }) },
{ id: 'go-changes', label: 'Go to Changes', group: 'Navigation', keywords: ['git', 'modified', 'pending'], enabled: true, execute: () => onSelect({ kind: 'filter', filter: 'changes' }) },
{ id: 'go-pulse', label: 'Go to Pulse', group: 'Navigation', keywords: ['activity', 'history', 'commits', 'git', 'feed'], enabled: true, execute: () => onSelect({ kind: 'filter', filter: 'pulse' }) },
- { id: 'go-inbox', label: 'Go to Inbox', group: 'Navigation', keywords: ['inbox', 'unlinked', 'orphan', 'unorganized', 'triage'], enabled: true, execute: () => onSelect({ kind: 'filter', filter: 'inbox' }) },
{ id: 'go-back', label: 'Go Back', group: 'Navigation', shortcut: '⌘[', keywords: ['previous', 'history', 'back'], enabled: !!canGoBack, execute: () => onGoBack?.() },
{ id: 'go-forward', label: 'Go Forward', group: 'Navigation', shortcut: '⌘]', keywords: ['next', 'history', 'forward'], enabled: !!canGoForward, execute: () => onGoForward?.() },
]
+ if (showInbox) {
+ commands.splice(5, 0, {
+ id: 'go-inbox',
+ label: 'Go to Inbox',
+ group: 'Navigation',
+ keywords: ['inbox', 'unlinked', 'orphan', 'unorganized', 'triage'],
+ enabled: true,
+ execute: () => onSelect({ kind: 'filter', filter: 'inbox' }),
+ })
+ }
+ return commands
}
diff --git a/src/hooks/useAppCommands.ts b/src/hooks/useAppCommands.ts
index 6e2a5039..327ed09b 100644
--- a/src/hooks/useAppCommands.ts
+++ b/src/hooks/useAppCommands.ts
@@ -40,6 +40,7 @@ interface AppCommandsConfig {
onZoomReset: () => void
zoomLevel: number
onSelect: (sel: SidebarSelection) => void
+ showInbox?: boolean
onReplaceActiveTab: (entry: VaultEntry) => void
onSelectNote: (entry: VaultEntry) => void
onGoBack?: () => void
@@ -89,8 +90,9 @@ export function useAppCommands(config: AppCommandsConfig): CommandAction[] {
const { onSelect } = config
const selectFilter = useCallback((filter: SidebarFilter) => {
- onSelect({ kind: 'filter', filter })
- }, [onSelect])
+ const safeFilter = !config.showInbox && filter === 'inbox' ? 'all' : filter
+ onSelect({ kind: 'filter', filter: safeFilter })
+ }, [config.showInbox, onSelect])
const viewChanges = useCallback(() => {
onSelect({ kind: 'filter', filter: 'changes' })
@@ -191,6 +193,7 @@ export function useAppCommands(config: AppCommandsConfig): CommandAction[] {
onZoomReset: config.onZoomReset,
zoomLevel: config.zoomLevel,
onSelect: config.onSelect,
+ showInbox: config.showInbox,
onOpenDailyNote: config.onOpenDailyNote,
onGoBack: config.onGoBack,
onGoForward: config.onGoForward,
diff --git a/src/hooks/useCommandRegistry.test.ts b/src/hooks/useCommandRegistry.test.ts
index 91f734ec..d30c6b4c 100644
--- a/src/hooks/useCommandRegistry.test.ts
+++ b/src/hooks/useCommandRegistry.test.ts
@@ -201,6 +201,12 @@ describe('useCommandRegistry', () => {
expect(findCommand(result.current, 'archive-note')?.shortcut).toBeUndefined()
})
+ it('omits Inbox navigation when the explicit workflow is disabled', () => {
+ const config = makeConfig({ showInbox: false })
+ const { result } = renderHook(() => useCommandRegistry(config))
+ expect(findCommand(result.current, 'go-inbox')).toBeUndefined()
+ })
+
it('includes Give Feedback in the Settings group when available', () => {
const onOpenFeedback = vi.fn()
const config = makeConfig({ onOpenFeedback })
diff --git a/src/hooks/useCommandRegistry.ts b/src/hooks/useCommandRegistry.ts
index b61c27db..a0f96586 100644
--- a/src/hooks/useCommandRegistry.ts
+++ b/src/hooks/useCommandRegistry.ts
@@ -61,6 +61,7 @@ interface CommandRegistryConfig {
zoomLevel: number
onSelect: (sel: SidebarSelection) => void
onOpenDailyNote: () => void
+ showInbox?: boolean
onGoBack?: () => void
onGoForward?: () => void
canGoBack?: boolean
@@ -83,6 +84,7 @@ export function useCommandRegistry(config: CommandRegistryConfig): import('./com
activeNoteModified,
onZoomIn, onZoomOut, onZoomReset, zoomLevel,
onSelect, onOpenDailyNote,
+ showInbox,
onGoBack, onGoForward, canGoBack, canGoForward,
onCheckForUpdates, onCreateType,
onRemoveActiveVault, onRestoreGettingStarted, isGettingStartedHidden, vaultCount,
@@ -108,7 +110,7 @@ export function useCommandRegistry(config: CommandRegistryConfig): import('./com
const vaultTypes = useMemo(() => extractVaultTypes(entries), [entries])
return useMemo(() => [
- ...buildNavigationCommands({ onQuickOpen, onSelect, onOpenDailyNote, onGoBack, onGoForward, canGoBack, canGoForward }),
+ ...buildNavigationCommands({ onQuickOpen, onSelect, onOpenDailyNote, showInbox, onGoBack, onGoForward, canGoBack, canGoForward }),
...buildNoteCommands({
hasActiveNote, activeTabPath, isArchived,
onCreateNote, onCreateType, onOpenDailyNote, onSave,
@@ -138,6 +140,7 @@ export function useCommandRegistry(config: CommandRegistryConfig): import('./com
onCheckForUpdates,
onZoomIn, onZoomOut, onZoomReset, zoomLevel,
onSelect, onOpenDailyNote,
+ showInbox,
onGoBack, onGoForward, canGoBack, canGoForward,
vaultTypes,
onRemoveActiveVault, onRestoreGettingStarted, isGettingStartedHidden, vaultCount,
diff --git a/src/types.ts b/src/types.ts
index 6ca27ea5..d37d37df 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -155,6 +155,7 @@ export type SearchMode = 'keyword' | 'semantic' | 'hybrid'
/** Vault-scoped UI configuration stored locally per vault path. */
export interface InboxConfig {
noteListProperties: string[] | null
+ explicitOrganization?: boolean | null
}
/** Vault-scoped UI configuration stored locally per vault path. */
diff --git a/src/utils/organizationWorkflow.test.ts b/src/utils/organizationWorkflow.test.ts
new file mode 100644
index 00000000..f6f0407f
--- /dev/null
+++ b/src/utils/organizationWorkflow.test.ts
@@ -0,0 +1,36 @@
+import { describe, expect, it } from 'vitest'
+import {
+ ALL_NOTES_SELECTION,
+ INBOX_SELECTION,
+ getDefaultSelectionForOrganization,
+ isExplicitOrganizationEnabled,
+ sanitizeSelectionForOrganization,
+} from './organizationWorkflow'
+
+describe('organizationWorkflow', () => {
+ it('treats the setting as enabled by default', () => {
+ expect(isExplicitOrganizationEnabled(undefined)).toBe(true)
+ expect(isExplicitOrganizationEnabled(null)).toBe(true)
+ })
+
+ it('treats explicit false as disabled', () => {
+ expect(isExplicitOrganizationEnabled(false)).toBe(false)
+ })
+
+ it('defaults to Inbox when explicit organization is enabled', () => {
+ expect(getDefaultSelectionForOrganization(true)).toEqual(INBOX_SELECTION)
+ })
+
+ it('defaults to All Notes when explicit organization is disabled', () => {
+ expect(getDefaultSelectionForOrganization(false)).toEqual(ALL_NOTES_SELECTION)
+ })
+
+ it('replaces Inbox selection with All Notes when the workflow is disabled', () => {
+ expect(sanitizeSelectionForOrganization(INBOX_SELECTION, false)).toEqual(ALL_NOTES_SELECTION)
+ })
+
+ it('leaves non-Inbox selections unchanged when the workflow is disabled', () => {
+ const selection = { kind: 'filter', filter: 'archived' } as const
+ expect(sanitizeSelectionForOrganization(selection, false)).toEqual(selection)
+ })
+})
diff --git a/src/utils/organizationWorkflow.ts b/src/utils/organizationWorkflow.ts
new file mode 100644
index 00000000..bddda965
--- /dev/null
+++ b/src/utils/organizationWorkflow.ts
@@ -0,0 +1,22 @@
+import type { SidebarSelection } from '../types'
+
+export const INBOX_SELECTION: SidebarSelection = { kind: 'filter', filter: 'inbox' }
+export const ALL_NOTES_SELECTION: SidebarSelection = { kind: 'filter', filter: 'all' }
+
+export function isExplicitOrganizationEnabled(explicitOrganization?: boolean | null): boolean {
+ return explicitOrganization !== false
+}
+
+export function getDefaultSelectionForOrganization(explicitOrganization?: boolean | null): SidebarSelection {
+ return isExplicitOrganizationEnabled(explicitOrganization) ? INBOX_SELECTION : ALL_NOTES_SELECTION
+}
+
+export function sanitizeSelectionForOrganization(
+ selection: SidebarSelection,
+ explicitOrganization?: boolean | null,
+): SidebarSelection {
+ if (!isExplicitOrganizationEnabled(explicitOrganization) && selection.kind === 'filter' && selection.filter === 'inbox') {
+ return ALL_NOTES_SELECTION
+ }
+ return selection
+}