diff --git a/docs/ABSTRACTIONS.md b/docs/ABSTRACTIONS.md index 64bc6523..0e791990 100644 --- a/docs/ABSTRACTIONS.md +++ b/docs/ABSTRACTIONS.md @@ -352,6 +352,8 @@ The renderer uses `viewOrdering` helpers to convert drag or command-palette move 5. Sorts by `modified_at` descending 6. Skips unparseable files with a warning log +All Notes starts from Markdown notes and excludes Markdown files under `attachments/`. `src/utils/allNotesFileVisibility.ts` resolves the installation-local PDF, image, and unsupported-file toggles from app settings; `noteListHelpers` applies that policy only to All Notes filtering and counts. Folder/root browsing continues to show files from the selected folder independently of those All Notes toggles. + The folder tree hides the legacy `type/` directory, since those type documents already appear through the Types sidebar section. Default vault folders such as `attachments/` and `views/` remain visible alongside user-created folders under the synthetic vault-root row. Command-facing vault content is filtered through `vault::filter_gitignored_entries`, `vault::filter_gitignored_folders`, and `vault::filter_gitignored_paths` when the app setting `hide_gitignored_files` is enabled. The cache still stores the complete scan; `list_vault`, `reload_vault`, `list_vault_folders`, and search apply the visibility filter at the boundary before React consumes entries. The filter batches paths through `git check-ignore --no-index --stdin`, so negated and specific `.gitignore` patterns follow Git semantics as closely as the app can reasonably support. @@ -757,10 +759,13 @@ interface Settings { note_width_mode: 'normal' | 'wide' | null default_ai_agent: 'claude_code' | 'codex' | 'opencode' | 'pi' | 'gemini' | null hide_gitignored_files: boolean | null // null = default true + all_notes_show_pdfs: boolean | null // null = default false + all_notes_show_images: boolean | null // null = default false + all_notes_show_unsupported: boolean | null // null = default false } ``` -Managed by `useSettings` hook and `SettingsPanel` component. `theme_mode` is installation-local because it controls device comfort rather than vault structure; the Settings panel and command-palette light/dark actions both update that same value. `ui_language` is also installation-local: `null` follows the supported system language with English fallback, while explicit values pin the UI language for this installation. Stored legacy aliases such as `zh-Hans` are normalized to canonical locale codes before the setting reaches React state. `note_width_mode` is the installation-local default for rich-editor note width; individual notes can override it with `_width` when they already have frontmatter. `default_ai_agent` is an installation-local preference that selects which supported CLI agent the AI panel, command palette AI mode, and status bar should target by default. `hide_gitignored_files` is also installation-local and defaults to `true`; changing it reloads entries, search, saved views, and folders without restarting. The AutoGit fields are also installation-local: `useAutoGit` consumes them to schedule automatic checkpoints, while `useCommitFlow` and the status bar quick action reuse the same checkpoint runner and deterministic automatic commit message generation. +Managed by `useSettings` hook and `SettingsPanel` component. `theme_mode` is installation-local because it controls device comfort rather than vault structure; the Settings panel and command-palette light/dark actions both update that same value. `ui_language` is also installation-local: `null` follows the supported system language with English fallback, while explicit values pin the UI language for this installation. Stored legacy aliases such as `zh-Hans` are normalized to canonical locale codes before the setting reaches React state. `note_width_mode` is the installation-local default for rich-editor note width; individual notes can override it with `_width` when they already have frontmatter. `default_ai_agent` is an installation-local preference that selects which supported CLI agent the AI panel, command palette AI mode, and status bar should target by default. `hide_gitignored_files` is also installation-local and defaults to `true`; changing it reloads entries, search, saved views, and folders without restarting. The `all_notes_show_pdfs`, `all_notes_show_images`, and `all_notes_show_unsupported` flags are installation-local All Notes category toggles that default off and update the list/counts without changing vault files. The AutoGit fields are also installation-local: `useAutoGit` consumes them to schedule automatic checkpoints, while `useCommitFlow` and the status bar quick action reuse the same checkpoint runner and deterministic automatic commit message generation. ## Telemetry diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index e15d2bf4..6139e71b 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -26,6 +26,7 @@ When deciding where to persist a piece of data, ask: **"Would the user want this | Property display order | Window size / position | | Per-note `_width` rich-editor width override | Default rich-editor note width | | Vault-authored `.gitignore` patterns | Whether this installation hides Gitignored files | +| Per-vault All Notes note-list column overrides | All Notes PDF/image/unsupported file visibility | | Any user-visible customization of how content is organized or displayed | Any machine-specific or credential-type setting | **Rule:** If the information is about *how the content is structured or presented* and the user would expect it to be consistent wherever they open their vault, store it in the vault (frontmatter of the relevant note, using the `_field` underscore convention for system properties). If it's about *this specific installation of the app*, store it in `~/.config/com.tolaria.app/settings.json` or localStorage. @@ -37,6 +38,7 @@ Examples: - ✅ App settings: `zoom: 1.3` (machine-specific preference) - ✅ App settings: `ui_language: "zh-CN"` (installation-specific UI language) - ✅ App settings: `note_width_mode: "wide"` (installation-specific default for notes without an override) +- ✅ App settings: `all_notes_show_images: true` (installation-specific All Notes file-category visibility) ### No hardcoded exceptions @@ -812,7 +814,7 @@ No Redux or global context. State lives in the root `App.tsx` and custom hooks: | `useCommitFlow` | Commit dialog state, shared manual/automatic checkpoint runner | Git commit/push orchestration | | `useGitRemoteStatus` | `remoteStatus`, `refreshRemoteStatus()` | On-demand remote detection for commit UI | | `useUnifiedSearch` | Query, results, loading state | Keyword search | -| `useSettings` | App settings (telemetry, release channel, theme mode, UI language, auto-sync interval, AutoGit thresholds, default AI agent, Gitignored-content visibility) | Persistent settings | +| `useSettings` | App settings (telemetry, release channel, theme mode, UI language, auto-sync interval, AutoGit thresholds, default AI agent, Gitignored-content visibility, All Notes file visibility) | Persistent settings | | `useVaultConfig` | Per-vault UI preferences, AI permission mode | Vault-specific config | | `appCommandDispatcher` | Canonical shortcut/menu command IDs | Shared execution path for renderer and native menu commands | diff --git a/lara.lock b/lara.lock index 50394df1..5f7a41e8 100644 --- a/lara.lock +++ b/lara.lock @@ -11,7 +11,7 @@ files: command.openSettings: 638c05f4f159a403e04aebe94b46a2a8 command.openSettings.keywords: ab6b5e03395f4db955ed9cbfd4de33b7 command.openLanguageSettings: e5a425aa6222fab3df66c0e1e0ca4183 - command.openLanguageSettings.keywords: 68efcb7e847b1a9d472baa609824be80 + command.openLanguageSettings.keywords: 639afefdd1c238b381bc1f963288f389 command.useSystemLanguage: b7f0315c47d4a59faa2a49571fcf1fca command.openH1Setting: 05b4f6edc0e98b29670e8ee902cdb9bf command.toggleGitignoredFilesVisibility: 0a2d3ea4e8ff8b00a801183caeb97a03 @@ -131,6 +131,14 @@ files: settings.vaultContent.description: a53487bf1c7898a1459dc1510e216f7d settings.vaultContent.hideGitignored: 2c07ee6c8bfe746d356f44275d42f90e settings.vaultContent.hideGitignoredDescription: e8b1ddfa416610f9d6eb299fa123a1d6 + settings.allNotesVisibility.title: 0e07c3d48b91e1a4c42c1ff3e5751ec3 + settings.allNotesVisibility.description: bc9caa48296281401aad694fed65a2d9 + settings.allNotesVisibility.pdfs: 76663c34a88bd4225613a1a947127bcf + settings.allNotesVisibility.pdfsDescription: 33bfa167c125ddd713f40af11d233121 + settings.allNotesVisibility.images: fff0d600f8a0b5e19e88bfb821dd1157 + settings.allNotesVisibility.imagesDescription: 54e1fe8f20b426de2fe457322862fb4b + settings.allNotesVisibility.unsupported: 91de79ad2f20abd62e445f20584d3b8e + settings.allNotesVisibility.unsupportedDescription: c1ecaa108af2de4680ab535585c475e8 settings.aiAgents.title: 27f08387b26e1ceeb1b60bd9c97e7a47 settings.aiAgents.description: a13222e67eb121676ff6dfc7b085f02d settings.aiAgents.default: 6af573559fd05d8c35bc57b41cc78e24 @@ -487,5 +495,7 @@ files: locale.ptPT: 71bfc0d79772120b52c1c0782450ff84 locale.es419: edbf64ac382b82a54795fb409beb54be locale.zhCN: 1e81fc32fea0e9f3a978661e4b5e484d + locale.zhTW: d0bb8c23f6e4f8c8037b6774ba912036 locale.jaJP: f32ced6a9ba164c4b3c047fd1d7c882e locale.koKR: d0bdb3cde477d82e766da05ebda50ccb + locale.vi: 7b80fae85640c16cdb0261bef0c27636 diff --git a/src-tauri/src/settings.rs b/src-tauri/src/settings.rs index 683dcbad..7008eec6 100644 --- a/src-tauri/src/settings.rs +++ b/src-tauri/src/settings.rs @@ -26,6 +26,9 @@ pub struct Settings { pub initial_h1_auto_rename_enabled: Option, pub default_ai_agent: Option, pub hide_gitignored_files: Option, + pub all_notes_show_pdfs: Option, + pub all_notes_show_images: Option, + pub all_notes_show_unsupported: Option, } fn normalize_optional_string(value: Option) -> Option { @@ -136,6 +139,9 @@ fn normalize_settings(settings: Settings) -> Settings { initial_h1_auto_rename_enabled: settings.initial_h1_auto_rename_enabled, default_ai_agent: normalize_default_ai_agent(settings.default_ai_agent.as_deref()), hide_gitignored_files: settings.hide_gitignored_files, + all_notes_show_pdfs: settings.all_notes_show_pdfs, + all_notes_show_images: settings.all_notes_show_images, + all_notes_show_unsupported: settings.all_notes_show_unsupported, } } @@ -280,6 +286,9 @@ mod tests { initial_h1_auto_rename_enabled: Some(false), default_ai_agent: Some("codex".to_string()), hide_gitignored_files: Some(false), + all_notes_show_pdfs: Some(true), + all_notes_show_images: Some(true), + all_notes_show_unsupported: Some(false), }; let json = serde_json::to_string(&settings).unwrap(); let parsed: Settings = serde_json::from_str(&json).unwrap(); @@ -309,6 +318,9 @@ mod tests { initial_h1_auto_rename_enabled: Some(false), default_ai_agent: Some("codex".to_string()), hide_gitignored_files: Some(false), + all_notes_show_pdfs: Some(true), + all_notes_show_images: Some(false), + all_notes_show_unsupported: Some(true), ..Default::default() }); assert_eq!(loaded.auto_pull_interval_minutes, Some(10)); @@ -323,6 +335,9 @@ mod tests { assert_eq!(loaded.initial_h1_auto_rename_enabled, Some(false)); assert_eq!(loaded.default_ai_agent.as_deref(), Some("codex")); assert_eq!(loaded.hide_gitignored_files, Some(false)); + assert_eq!(loaded.all_notes_show_pdfs, Some(true)); + assert_eq!(loaded.all_notes_show_images, Some(false)); + assert_eq!(loaded.all_notes_show_unsupported, Some(true)); } #[test] diff --git a/src/App.tsx b/src/App.tsx index 9a50276d..cb050dc4 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -87,6 +87,7 @@ import type { SidebarSelection, InboxPeriod, VaultEntry, ViewDefinition } from ' import type { NoteListItem } from './utils/ai-context' import { initializeNoteProperties } from './utils/initializeNoteProperties' import { filterEntries, filterInboxEntries, type NoteListFilter } from './utils/noteListHelpers' +import { resolveAllNotesFileVisibility } from './utils/allNotesFileVisibility' import { openNoteInNewWindow } from './utils/openNoteWindow' import { refreshPulledVaultState } from './utils/pulledVaultRefresh' import { isNoteWindow, getNoteWindowParams, getNoteWindowPathCandidates, type NoteWindowParams } from './utils/windowMode' @@ -430,6 +431,10 @@ function App() { () => resolveEffectiveLocale(settings.ui_language, [systemLocale]), [settings.ui_language, systemLocale], ) + const allNotesFileVisibility = useMemo( + () => resolveAllNotesFileVisibility(settings), + [settings], + ) const selectedUiLanguage = settings.ui_language ?? SYSTEM_UI_LANGUAGE useEffect(() => { document.documentElement.lang = appLocale @@ -1546,11 +1551,16 @@ function App() { const aiNoteList = useMemo(() => { const isInbox = effectiveSelection.kind === 'filter' && effectiveSelection.filter === 'inbox' - const filtered = isInbox ? filterInboxEntries(vault.entries, inboxPeriod) : filterEntries(vault.entries, effectiveSelection, undefined, vault.views) + const filtered = isInbox + ? filterInboxEntries(vault.entries, inboxPeriod) + : filterEntries(vault.entries, effectiveSelection, { + views: vault.views, + allNotesFileVisibility, + }) return filtered.map(e => ({ path: e.path, title: e.title, type: e.isA ?? 'Note', })) - }, [vault.entries, vault.views, effectiveSelection, inboxPeriod]) + }, [allNotesFileVisibility, vault.entries, vault.views, effectiveSelection, inboxPeriod]) const aiNoteListFilter = useMemo(() => { if (effectiveSelection.kind === 'sectionGroup') return { type: effectiveSelection.type, query: '' } @@ -1622,7 +1632,7 @@ function App() { {sidebarVisible && ( <>
- +
@@ -1633,7 +1643,7 @@ function App() { {effectiveSelection.kind === 'filter' && effectiveSelection.filter === 'pulse' ? ( handleSetViewMode('all')} locale={appLocale} /> ) : ( - + )} diff --git a/src/components/SettingsPanel.test.tsx b/src/components/SettingsPanel.test.tsx index 4da711da..780465db 100644 --- a/src/components/SettingsPanel.test.tsx +++ b/src/components/SettingsPanel.test.tsx @@ -19,6 +19,9 @@ const emptySettings: Settings = { ui_language: null, default_ai_agent: null, hide_gitignored_files: null, + all_notes_show_pdfs: null, + all_notes_show_images: null, + all_notes_show_unsupported: null, } function installPointerCapturePolyfill() { @@ -107,6 +110,9 @@ describe('SettingsPanel', () => { release_channel: null, theme_mode: 'light', hide_gitignored_files: true, + all_notes_show_pdfs: false, + all_notes_show_images: false, + all_notes_show_unsupported: false, })) expect(onClose).toHaveBeenCalled() }) @@ -125,6 +131,56 @@ describe('SettingsPanel', () => { expect(onClose).toHaveBeenCalled() }) + it('renders All Notes file visibility checkboxes off by default', () => { + render( + + ) + + expect(screen.getByText('All Notes visibility')).toBeInTheDocument() + expect(within(screen.getByTestId('settings-all-notes-show-pdfs')).getByRole('checkbox')).toHaveAttribute('aria-checked', 'false') + expect(within(screen.getByTestId('settings-all-notes-show-images')).getByRole('checkbox')).toHaveAttribute('aria-checked', 'false') + expect(within(screen.getByTestId('settings-all-notes-show-unsupported')).getByRole('checkbox')).toHaveAttribute('aria-checked', 'false') + }) + + it('preserves saved All Notes file visibility checkboxes', () => { + render( + + ) + + expect(within(screen.getByTestId('settings-all-notes-show-pdfs')).getByRole('checkbox')).toHaveAttribute('aria-checked', 'true') + expect(within(screen.getByTestId('settings-all-notes-show-images')).getByRole('checkbox')).toHaveAttribute('aria-checked', 'true') + expect(within(screen.getByTestId('settings-all-notes-show-unsupported')).getByRole('checkbox')).toHaveAttribute('aria-checked', 'false') + }) + + it('saves All Notes file visibility from keyboard toggles before Escape close', () => { + render( + + ) + + const pdfCheckbox = within(screen.getByTestId('settings-all-notes-show-pdfs')).getByRole('checkbox') + pdfCheckbox.focus() + fireEvent.keyDown(pdfCheckbox, { key: ' ', code: 'Space' }) + fireEvent.keyUp(pdfCheckbox, { key: ' ', code: 'Space' }) + fireEvent.keyDown(screen.getByTestId('settings-panel'), { key: 'Escape' }) + + expect(onSave).toHaveBeenCalledWith(expect.objectContaining({ + all_notes_show_pdfs: true, + all_notes_show_images: false, + all_notes_show_unsupported: false, + })) + expect(onClose).toHaveBeenCalled() + }) + it('defaults the color mode control to light', () => { render( diff --git a/src/components/SettingsPanel.tsx b/src/components/SettingsPanel.tsx index 391f74d7..aa953dda 100644 --- a/src/components/SettingsPanel.tsx +++ b/src/components/SettingsPanel.tsx @@ -14,6 +14,7 @@ import { type KeyboardEvent as ReactKeyboardEvent, type MouseEvent as ReactMouseEvent, type ReactNode, + type RefObject, } from 'react' import { Moon, Sun, X } from '@phosphor-icons/react' import { Copy } from 'lucide-react' @@ -38,6 +39,11 @@ import { import { normalizeReleaseChannel, serializeReleaseChannel, type ReleaseChannel } from '../lib/releaseChannel' import { shouldHideGitignoredFiles } from '../lib/gitignoredVisibility' import { trackEvent } from '../lib/telemetry' +import { + resolveAllNotesFileVisibility, + settingsWithAllNotesFileVisibility, + type AllNotesFileVisibility, +} from '../utils/allNotesFileVisibility' import { Button } from './ui/button' import { Checkbox, type CheckedState } from './ui/checkbox' import { Input } from './ui/input' @@ -76,6 +82,7 @@ interface SettingsDraft { uiLanguage: UiLanguagePreference initialH1AutoRename: boolean hideGitignoredFiles: boolean + allNotesFileVisibility: AllNotesFileVisibility crashReporting: boolean analytics: boolean explicitOrganization: boolean @@ -110,6 +117,8 @@ interface SettingsBodyProps { setInitialH1AutoRename: (value: boolean) => void hideGitignoredFiles: boolean setHideGitignoredFiles: (value: boolean) => void + allNotesFileVisibility: AllNotesFileVisibility + setAllNotesFileVisibility: (value: AllNotesFileVisibility) => void explicitOrganization: boolean setExplicitOrganization: (value: boolean) => void crashReporting: boolean @@ -149,6 +158,7 @@ function createSettingsDraft( uiLanguage: settings.ui_language ?? SYSTEM_UI_LANGUAGE, initialH1AutoRename: settings.initial_h1_auto_rename_enabled ?? true, hideGitignoredFiles: shouldHideGitignoredFiles(settings), + allNotesFileVisibility: resolveAllNotesFileVisibility(settings), crashReporting: settings.crash_reporting_enabled ?? false, analytics: settings.analytics_enabled ?? false, explicitOrganization: explicitOrganizationEnabled, @@ -175,7 +185,7 @@ function resolveAnonymousId(settings: Settings, draft: SettingsDraft): string | } function buildSettingsFromDraft(settings: Settings, draft: SettingsDraft): Settings { - return { + const nextSettings = { auto_pull_interval_minutes: draft.pullInterval, autogit_enabled: draft.autoGitEnabled, autogit_idle_threshold_seconds: draft.autoGitIdleThresholdSeconds, @@ -192,6 +202,7 @@ function buildSettingsFromDraft(settings: Settings, draft: SettingsDraft): Setti default_ai_agent: draft.defaultAiAgent, hide_gitignored_files: draft.hideGitignoredFiles, } + return settingsWithAllNotesFileVisibility(nextSettings, draft.allNotesFileVisibility) } function trackTelemetryConsentChange(previousAnalytics: boolean, nextAnalytics: boolean): void { @@ -213,6 +224,16 @@ function applyThemeModeSelection(value: ThemeMode): void { if (typeof window !== 'undefined') writeStoredThemeMode(window.localStorage, value) } +function useSettingsPanelAutofocus(panelRef: RefObject): void { + useEffect(() => { + const timer = setTimeout(() => { + const focusTarget = panelRef.current?.querySelector('[data-settings-autofocus="true"]') + focusTarget?.focus() + }, 50) + return () => clearTimeout(timer) + }, [panelRef]) +} + export function SettingsPanel({ open, settings, @@ -272,13 +293,7 @@ function SettingsPanelInner({ setDraft(createSettingsDraft(settings, explicitOrganizationEnabled)) }, [explicitOrganizationEnabled, settings]) - useEffect(() => { - const timer = setTimeout(() => { - const focusTarget = panelRef.current?.querySelector('[data-settings-autofocus="true"]') - focusTarget?.focus() - }, 50) - return () => clearTimeout(timer) - }, []) + useSettingsPanelAutofocus(panelRef) const updateDraft = useCallback( (key: Key, value: SettingsDraft[Key]) => { @@ -292,6 +307,11 @@ function SettingsPanelInner({ onSave({ ...settings, hide_gitignored_files: value }) }, [onSave, settings, updateDraft]) + const handleAllNotesFileVisibilityChange = useCallback((value: AllNotesFileVisibility) => { + updateDraft('allNotesFileVisibility', value) + onSave(settingsWithAllNotesFileVisibility(settings, value)) + }, [onSave, settings, updateDraft]) + const handleThemeModeChange = useCallback((value: ThemeMode) => { updateDraft('themeMode', value) applyThemeModeSelection(value) @@ -368,6 +388,8 @@ function SettingsPanelInner({ setInitialH1AutoRename={(value) => updateDraft('initialH1AutoRename', value)} hideGitignoredFiles={draft.hideGitignoredFiles} setHideGitignoredFiles={handleGitignoredVisibilityChange} + allNotesFileVisibility={draft.allNotesFileVisibility} + setAllNotesFileVisibility={handleAllNotesFileVisibilityChange} explicitOrganization={draft.explicitOrganization} setExplicitOrganization={(value) => updateDraft('explicitOrganization', value)} crashReporting={draft.crashReporting} @@ -401,7 +423,17 @@ function SettingsHeader({ onClose, t }: { onClose: () => void; t: Translate }) { ) } -function SettingsBody({ +function SettingsBody(props: SettingsBodyProps) { + return ( +
+ + + +
+ ) +} + +function SettingsSyncAndAppearanceSections({ t, locale, systemLocale, @@ -414,31 +446,15 @@ function SettingsBody({ setAutoGitIdleThresholdSeconds, autoGitInactiveThresholdSeconds, setAutoGitInactiveThresholdSeconds, - autoAdvanceInboxAfterOrganize, - setAutoAdvanceInboxAfterOrganize, - aiAgentsStatus, - defaultAiAgent, - setDefaultAiAgent, - onCopyMcpConfig, releaseChannel, setReleaseChannel, themeMode, setThemeMode, uiLanguage, setUiLanguage, - initialH1AutoRename, - setInitialH1AutoRename, - hideGitignoredFiles, - setHideGitignoredFiles, - explicitOrganization, - setExplicitOrganization, - crashReporting, - setCrashReporting, - analytics, - setAnalytics, }: SettingsBodyProps) { return ( -
+ <> - + + ) +} +function SettingsContentSections({ + t, + initialH1AutoRename, + setInitialH1AutoRename, + hideGitignoredFiles, + setHideGitignoredFiles, + allNotesFileVisibility, + setAllNotesFileVisibility, +}: SettingsBodyProps) { + return ( + <> + + ) +} +function SettingsAgentWorkflowSections({ + t, + autoAdvanceInboxAfterOrganize, + setAutoAdvanceInboxAfterOrganize, + aiAgentsStatus, + defaultAiAgent, + setDefaultAiAgent, + onCopyMcpConfig, + explicitOrganization, + setExplicitOrganization, + crashReporting, + setCrashReporting, + analytics, + setAnalytics, +}: SettingsBodyProps) { + return ( + <> -
+ ) } @@ -779,7 +830,16 @@ function VaultContentSettingsSection({ t, hideGitignoredFiles, setHideGitignoredFiles, -}: Pick) { + allNotesFileVisibility, + setAllNotesFileVisibility, +}: Pick< + SettingsBodyProps, + 't' | 'hideGitignoredFiles' | 'setHideGitignoredFiles' | 'allNotesFileVisibility' | 'setAllNotesFileVisibility' +>) { + const updateAllNotesFileVisibility = (patch: Partial) => { + setAllNotesFileVisibility({ ...allNotesFileVisibility, ...patch }) + } + return ( <> + +
+ + + updateAllNotesFileVisibility({ pdfs: checked })} + testId="settings-all-notes-show-pdfs" + /> + updateAllNotesFileVisibility({ images: checked })} + testId="settings-all-notes-show-images" + /> + updateAllNotesFileVisibility({ unsupported: checked })} + testId="settings-all-notes-show-unsupported" + /> +
) } @@ -1084,6 +1173,40 @@ function SettingsSwitchRow({ ) } +function SettingsCheckboxRow({ + label, + description, + checked, + onChange, + testId, +}: { + label: string + description: string + checked: boolean + onChange: (value: boolean) => void + testId: string +}) { + return ( + + ) +} + function TelemetryToggle({ label, description, diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 7f14c478..da8871c3 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -29,6 +29,7 @@ import { import { useSidebarTypeInteractions } from './sidebar/useSidebarTypeInteractions' import type { AppLocale } from '../lib/i18n' import type { FolderFileActions } from '../hooks/useFileActions' +import type { AllNotesFileVisibility } from '../utils/allNotesFileVisibility' interface SidebarProps { entries: VaultEntry[] @@ -60,6 +61,7 @@ interface SidebarProps { vaultRootPath?: string showInbox?: boolean inboxCount?: number + allNotesFileVisibility?: AllNotesFileVisibility locale?: AppLocale onCollapse?: () => void loading?: boolean @@ -489,10 +491,11 @@ function useSidebarRuntime({ onReorderSections, onRenameSection, onToggleTypeVisibility, + allNotesFileVisibility, locale = 'en', }: SidebarProps) { const { typeEntryMap, allSectionGroups, visibleSections, sectionIds } = useSidebarSections(entries) - const { activeCount, archivedCount } = useEntryCounts(entries) + const { activeCount, archivedCount } = useEntryCounts(entries, allNotesFileVisibility) const { collapsed: groupCollapsed, toggle: toggleGroup } = useSidebarCollapsed() const typeInteractions = useSidebarTypeInteractions({ allSectionGroups, diff --git a/src/components/note-list/noteListHooks.ts b/src/components/note-list/noteListHooks.ts index 7aa50da5..db00895c 100644 --- a/src/components/note-list/noteListHooks.ts +++ b/src/components/note-list/noteListHooks.ts @@ -18,6 +18,7 @@ import { useMultiSelect, type MultiSelectState } from '../../hooks/useMultiSelec import { useNoteListKeyboard } from '../../hooks/useNoteListKeyboard' import { prefetchNoteContent } from '../../hooks/useTabManagement' import type { NoteListPropertiesScope } from './noteListPropertiesEvents' +import type { AllNotesFileVisibility } from '../../utils/allNotesFileVisibility' // --- useTypeEntryMap --- @@ -36,6 +37,7 @@ interface FilteredEntriesParams { subFilter?: NoteListFilter inboxPeriod?: InboxPeriod views?: ViewFile[] + allNotesFileVisibility?: AllNotesFileVisibility } function buildFilteredEntries({ @@ -50,6 +52,7 @@ function buildFilteredEntries({ subFilter, inboxPeriod, views, + allNotesFileVisibility, }: FilteredEntriesParams & { isEntityView: boolean isChangesView: boolean @@ -61,7 +64,11 @@ function buildFilteredEntries({ return entries.filter((entry) => isModifiedEntry(entry.path, modifiedPathSet, modifiedSuffixes)) } if (isInboxView) return filterInboxEntries(entries, inboxPeriod ?? 'month') - return filterEntries(entries, selection, subFilter, views) + return filterEntries(entries, selection, { + subFilter, + views, + allNotesFileVisibility, + }) } export function useFilteredEntries({ @@ -73,6 +80,7 @@ export function useFilteredEntries({ subFilter, inboxPeriod, views, + allNotesFileVisibility, }: FilteredEntriesParams) { const isEntityView = selection.kind === 'entity' const isChangesView = selection.kind === 'filter' && selection.filter === 'changes' @@ -90,8 +98,9 @@ export function useFilteredEntries({ subFilter, inboxPeriod, views, + allNotesFileVisibility, }) - }, [entries, inboxPeriod, isChangesView, isEntityView, isInboxView, modifiedFiles, modifiedPathSet, modifiedSuffixes, selection, subFilter, views]) + }, [allNotesFileVisibility, entries, inboxPeriod, isChangesView, isEntityView, isInboxView, modifiedFiles, modifiedPathSet, modifiedSuffixes, selection, subFilter, views]) } // --- useNoteListData --- @@ -104,9 +113,23 @@ interface NoteListDataParams { subFilter?: NoteListFilter inboxPeriod?: InboxPeriod views?: ViewFile[] + allNotesFileVisibility?: AllNotesFileVisibility } -export function useNoteListData({ entries, selection, query, listSort, listDirection, modifiedPathSet, modifiedSuffixes, modifiedFiles, subFilter, inboxPeriod, views }: NoteListDataParams) { +export function useNoteListData({ + entries, + selection, + query, + listSort, + listDirection, + modifiedPathSet, + modifiedSuffixes, + modifiedFiles, + subFilter, + inboxPeriod, + views, + allNotesFileVisibility, +}: NoteListDataParams) { const isEntityView = selection.kind === 'entity' const isArchivedView = (selection.kind === 'filter' && selection.filter === 'archived') || subFilter === 'archived' const entityEntry = useMemo(() => { @@ -123,6 +146,7 @@ export function useNoteListData({ entries, selection, query, listSort, listDirec subFilter, inboxPeriod, views, + allNotesFileVisibility, }) const searched = useMemo(() => { @@ -530,8 +554,8 @@ function useAllNotesPropertyPickerState( const allNotesEntries = useMemo( () => isAllNotesView ? [ - ...filterEntries(entries, selection, 'open'), - ...filterEntries(entries, selection, 'archived'), + ...filterEntries(entries, selection, { subFilter: 'open' }), + ...filterEntries(entries, selection, { subFilter: 'archived' }), ] : [], [entries, isAllNotesView, selection], @@ -588,7 +612,7 @@ function useViewPropertyPickerState( [selection, views], ) const viewEntries = useMemo( - () => selectedView ? filterEntries(entries, selection, undefined, views) : [], + () => selectedView ? filterEntries(entries, selection, { views }) : [], [entries, selection, selectedView, views], ) diff --git a/src/components/note-list/useNoteListModel.tsx b/src/components/note-list/useNoteListModel.tsx index 26b27876..5db96adf 100644 --- a/src/components/note-list/useNoteListModel.tsx +++ b/src/components/note-list/useNoteListModel.tsx @@ -11,6 +11,7 @@ import type { import type { AppLocale } from '../../lib/i18n' import type { NoteListFilter } from '../../utils/noteListHelpers' import { countByFilter, countAllByFilter, countAllNotesByFilter } from '../../utils/noteListHelpers' +import type { AllNotesFileVisibility } from '../../utils/allNotesFileVisibility' import { NoteItem } from '../NoteItem' import { prefetchNoteContent } from '../../hooks/useTabManagement' import type { MultiSelectState } from '../../hooks/useMultiSelect' @@ -108,13 +109,19 @@ function useBulkActions( } } -function useFilterCounts(entries: VaultEntry[], selection: SidebarSelection) { +function useFilterCounts( + entries: VaultEntry[], + selection: SidebarSelection, + allNotesFileVisibility?: AllNotesFileVisibility, +) { return useMemo(() => { if (selection.kind === 'sectionGroup') return countByFilter(entries, selection.type) if (selection.kind === 'folder') return countAllByFilter(entries) - if (selection.kind === 'filter' && selection.filter === 'all') return countAllNotesByFilter(entries) + if (selection.kind === 'filter' && selection.filter === 'all') { + return countAllNotesByFilter(entries, allNotesFileVisibility) + } return { open: 0, archived: 0 } - }, [entries, selection]) + }, [allNotesFileVisibility, entries, selection]) } interface UseNoteListContentParams { @@ -136,6 +143,7 @@ interface UseNoteListContentParams { updateEntry?: (path: string, patch: Partial) => void views?: ViewFile[] visibleNotesRef?: React.MutableRefObject + allNotesFileVisibility?: AllNotesFileVisibility } function useNoteListContent({ @@ -157,6 +165,7 @@ function useNoteListContent({ updateEntry, views, visibleNotesRef, + allNotesFileVisibility, }: UseNoteListContentParams) { const subFilter = (selection.kind === 'sectionGroup' || selection.kind === 'folder') ? noteListFilter @@ -217,6 +226,7 @@ function useNoteListContent({ subFilter, inboxPeriod: effectiveInboxPeriod, views, + allNotesFileVisibility, }) const searched = useMemo(() => filterEntriesByNoteListQuery(sortedEntries, query, { allEntries: entries, @@ -465,6 +475,7 @@ export interface NoteListProps { onUpdateViewDefinition?: (filename: string, patch: Partial) => void views?: ViewFile[] visibleNotesRef?: React.MutableRefObject + allNotesFileVisibility?: AllNotesFileVisibility locale?: AppLocale } @@ -574,12 +585,13 @@ export function useNoteListModel({ onUpdateViewDefinition, views, visibleNotesRef, + allNotesFileVisibility, locale = 'en', }: NoteListProps) { const selectedNotePath = selectedNote?.path ?? null const { modifiedPathSet, modifiedSuffixes, resolvedGetNoteStatus } = useModifiedFilesState(modifiedFiles, getNoteStatus) const { isInboxView } = useViewFlags(selection) - const filterCounts = useFilterCounts(entries, selection) + const filterCounts = useFilterCounts(entries, selection, allNotesFileVisibility) const content = useNoteListContent({ entries, selection, @@ -599,6 +611,7 @@ export function useNoteListModel({ updateEntry, views, visibleNotesRef, + allNotesFileVisibility, }) const interaction = useNoteListInteractionState({ searched: content.searched, diff --git a/src/components/sidebar/sidebarHooks.ts b/src/components/sidebar/sidebarHooks.ts index c210ef54..b55b6aca 100644 --- a/src/components/sidebar/sidebarHooks.ts +++ b/src/components/sidebar/sidebarHooks.ts @@ -4,6 +4,7 @@ import { APP_STORAGE_KEYS, LEGACY_APP_STORAGE_KEYS, getAppStorageItem } from '.. import { buildTypeEntryMap } from '../../utils/typeColors' import { countAllNotesByFilter } from '../../utils/noteListHelpers' import { buildDynamicSections, sortSections } from '../../utils/sidebarSections' +import type { AllNotesFileVisibility } from '../../utils/allNotesFileVisibility' export type SidebarGroupKey = 'favorites' | 'views' | 'sections' | 'folders' @@ -57,11 +58,14 @@ export function useSidebarCollapsed() { return { collapsed, toggle } } -export function useEntryCounts(entries: VaultEntry[]) { +export function useEntryCounts( + entries: VaultEntry[], + allNotesFileVisibility?: AllNotesFileVisibility, +) { return useMemo(() => { - const counts = countAllNotesByFilter(entries) + const counts = countAllNotesByFilter(entries, allNotesFileVisibility) return { activeCount: counts.open, archivedCount: counts.archived } - }, [entries]) + }, [allNotesFileVisibility, entries]) } export function computeReorder(sectionIds: string[], activeId: string, overId: string): string[] | null { diff --git a/src/hooks/useSettings.test.ts b/src/hooks/useSettings.test.ts index bf5f1d86..a22452ad 100644 --- a/src/hooks/useSettings.test.ts +++ b/src/hooks/useSettings.test.ts @@ -24,6 +24,9 @@ const defaultSettings: Settings = { note_width_mode: null, default_ai_agent: null, hide_gitignored_files: null, + all_notes_show_pdfs: null, + all_notes_show_images: null, + all_notes_show_unsupported: null, } const savedSettings: Settings = { @@ -42,6 +45,9 @@ const savedSettings: Settings = { note_width_mode: null, default_ai_agent: null, hide_gitignored_files: null, + all_notes_show_pdfs: null, + all_notes_show_images: null, + all_notes_show_unsupported: null, } let mockSettingsStore: Settings = { ...defaultSettings } @@ -93,6 +99,9 @@ function changedSettings(): Settings { note_width_mode: 'wide', default_ai_agent: null, hide_gitignored_files: false, + all_notes_show_pdfs: true, + all_notes_show_images: false, + all_notes_show_unsupported: true, } } @@ -191,6 +200,21 @@ describe('useSettings', () => { expect(settings.hide_gitignored_files).toBe(false) }) + it('preserves All Notes file visibility preferences', async () => { + mockSettingsStore = { + ...savedSettings, + all_notes_show_pdfs: true, + all_notes_show_images: false, + all_notes_show_unsupported: true, + } + + const settings = await renderLoadedSettings() + + expect(settings.all_notes_show_pdfs).toBe(true) + expect(settings.all_notes_show_images).toBe(false) + expect(settings.all_notes_show_unsupported).toBe(true) + }) + it('toggles Gitignored file visibility from the command event', async () => { const listener = vi.fn() window.addEventListener(GITIGNORED_VISIBILITY_CHANGED_EVENT, listener) diff --git a/src/hooks/useSettings.ts b/src/hooks/useSettings.ts index e334d58d..757c8603 100644 --- a/src/hooks/useSettings.ts +++ b/src/hooks/useSettings.ts @@ -47,6 +47,9 @@ const EMPTY_SETTINGS: Settings = { note_width_mode: null, default_ai_agent: null, hide_gitignored_files: null, + all_notes_show_pdfs: null, + all_notes_show_images: null, + all_notes_show_unsupported: null, } function normalizeSettings(settings: Settings): Settings { @@ -60,6 +63,9 @@ function normalizeSettings(settings: Settings): Settings { note_width_mode: normalizeNoteWidthMode(settings.note_width_mode), default_ai_agent: normalizeStoredAiAgent(settings.default_ai_agent), hide_gitignored_files: settings.hide_gitignored_files ?? null, + all_notes_show_pdfs: settings.all_notes_show_pdfs ?? null, + all_notes_show_images: settings.all_notes_show_images ?? null, + all_notes_show_unsupported: settings.all_notes_show_unsupported ?? null, } } diff --git a/src/lib/locales/de-DE.json b/src/lib/locales/de-DE.json index 38fc0afd..a4be4636 100644 --- a/src/lib/locales/de-DE.json +++ b/src/lib/locales/de-DE.json @@ -9,7 +9,7 @@ "command.openSettings": "Einstellungen öffnen", "command.openSettings.keywords": "Einstellungen Konfiguration", "command.openLanguageSettings": "Spracheinstellungen öffnen", - "command.openLanguageSettings.keywords": "Sprache Gebietsschema i18n Internationalisierung Lokalisierung Englisch Italienisch Französisch Deutsch Russisch Spanisch Portugiesisch Chinesisch Japanisch Koreanisch 中文", + "command.openLanguageSettings.keywords": "Sprache Gebietsschema i18n Internationalisierung Lokalisierung Englisch Italienisch Französisch Deutsch Russisch Spanisch Portugiesisch Chinesisch Vereinfacht Traditionell Japanisch Koreanisch 中文 繁體中文 zh-tw", "command.useSystemLanguage": "Systemsprache verwenden", "command.openH1Setting": "Einstellung für automatische H1-Umbenennung öffnen", "command.toggleGitignoredFilesVisibility": "Sichtbarkeit von Gitignored-Dateien umschalten", @@ -129,6 +129,14 @@ "settings.vaultContent.description": "Legen Sie fest, ob Dateien, die der .gitignore-Datei des Vaults entsprechen, in Tolaria angezeigt werden.", "settings.vaultContent.hideGitignored": "Von Git ignorierte Dateien und Ordner ausblenden", "settings.vaultContent.hideGitignoredDescription": "Hält generierte und rein lokale Vault-Dateien von Notizen, der Suche, dem schnellen Öffnen und Ordnern fern.", + "settings.allNotesVisibility.title": "Sichtbarkeit in „Alle Notizen“", + "settings.allNotesVisibility.description": "Wählen Sie aus, welche Kategorien von Nicht-Markdown-Dateien in „Alle Notizen“ angezeigt werden sollen. Beim Durchsuchen von Ordnern werden die Dateien weiterhin in ihren Ordnern angezeigt.", + "settings.allNotesVisibility.pdfs": "PDF-Dateien", + "settings.allNotesVisibility.pdfsDescription": "PDF-Dateien in „Alle Notizen“ anzeigen.", + "settings.allNotesVisibility.images": "Bilder", + "settings.allNotesVisibility.imagesDescription": "Gängige Bilddateien in „Alle Notizen“ anzeigen.", + "settings.allNotesVisibility.unsupported": "Nicht unterstützte Dateien", + "settings.allNotesVisibility.unsupportedDescription": "Andere Nicht-Markdown-Dateien anzeigen, für die es keine In-App-Vorschau gibt.", "settings.aiAgents.title": "KI-Agents", "settings.aiAgents.description": "Wählen Sie aus, welchen CLI-KI-Agenten Tolaria im KI-Panel und in der Befehlspalette verwendet.", "settings.aiAgents.default": "Standard-KI-Agent", @@ -485,6 +493,7 @@ "locale.ptPT": "葡萄牙语(葡萄牙)", "locale.es419": "西班牙语(拉丁美洲)", "locale.zhCN": "简体中文", + "locale.zhTW": "繁體中文", "locale.jaJP": "日本語", "locale.koKR": "Coreano", "locale.vi": "Vietnamesisch" diff --git a/src/lib/locales/en.json b/src/lib/locales/en.json index f245064f..34d2cacb 100644 --- a/src/lib/locales/en.json +++ b/src/lib/locales/en.json @@ -129,6 +129,14 @@ "settings.vaultContent.description": "Control whether files matched by the vault .gitignore appear in Tolaria.", "settings.vaultContent.hideGitignored": "Hide files and folders ignored by Git", "settings.vaultContent.hideGitignoredDescription": "Keeps generated and local-only vault files out of notes, search, quick open, and folders.", + "settings.allNotesVisibility.title": "All Notes visibility", + "settings.allNotesVisibility.description": "Choose which non-Markdown file categories appear in All Notes. Folder browsing still shows files in their folders.", + "settings.allNotesVisibility.pdfs": "PDFs", + "settings.allNotesVisibility.pdfsDescription": "Show PDF files in All Notes.", + "settings.allNotesVisibility.images": "Images", + "settings.allNotesVisibility.imagesDescription": "Show common image files in All Notes.", + "settings.allNotesVisibility.unsupported": "Unsupported files", + "settings.allNotesVisibility.unsupportedDescription": "Show other non-Markdown files that do not have an in-app preview.", "settings.aiAgents.title": "AI Agents", "settings.aiAgents.description": "Choose which CLI AI agent Tolaria uses in the AI panel and command palette.", "settings.aiAgents.default": "Default AI agent", diff --git a/src/lib/locales/es-419.json b/src/lib/locales/es-419.json index 7601e83a..94edad39 100644 --- a/src/lib/locales/es-419.json +++ b/src/lib/locales/es-419.json @@ -9,7 +9,7 @@ "command.openSettings": "Abrir Configuración", "command.openSettings.keywords": "configuración de preferencias", "command.openLanguageSettings": "Abrir la configuración de idioma", - "command.openLanguageSettings.keywords": "idioma configuración regional i18n internacionalización localización inglés italiano francés alemán ruso español portugués chino japonés coreano 中文", + "command.openLanguageSettings.keywords": "idioma configuración regional i18n internacionalización localización inglés italiano francés alemán ruso español portugués chino simplificado tradicional japonés coreano 中文 繁體中文 zh-tw", "command.useSystemLanguage": "Usar el idioma del sistema", "command.openH1Setting": "Abrir la configuración de renombrado automático de H1", "command.toggleGitignoredFilesVisibility": "Alternar la visibilidad de los archivos Gitignored", @@ -129,6 +129,14 @@ "settings.vaultContent.description": "Controle si los archivos que coinciden con el archivo .gitignore del repositorio aparecen en Tolaria.", "settings.vaultContent.hideGitignored": "Ocultar archivos y carpetas ignorados por Git", "settings.vaultContent.hideGitignoredDescription": "Mantiene los archivos de la caja fuerte generados y solo locales fuera de las notas, la búsqueda, la apertura rápida y las carpetas.", + "settings.allNotesVisibility.title": "Visibilidad de Todas las notas", + "settings.allNotesVisibility.description": "Elija qué categorías de archivos que no son Markdown aparecen en Todas las notas. Al explorar las carpetas, los archivos siguen mostrándose en sus carpetas.", + "settings.allNotesVisibility.pdfs": "PDF", + "settings.allNotesVisibility.pdfsDescription": "Mostrar archivos PDF en Todas las notas.", + "settings.allNotesVisibility.images": "Imágenes", + "settings.allNotesVisibility.imagesDescription": "Mostrar los archivos de imagen comunes en Todas las notas.", + "settings.allNotesVisibility.unsupported": "Archivos no compatibles", + "settings.allNotesVisibility.unsupportedDescription": "Mostrar otros archivos que no sean Markdown y que no tengan vista previa en la aplicación.", "settings.aiAgents.title": "Agentes de IA", "settings.aiAgents.description": "Elija qué agente de IA de CLI utiliza Tolaria en el panel de IA y en la paleta de comandos.", "settings.aiAgents.default": "Agente de IA predeterminado", @@ -485,6 +493,7 @@ "locale.ptPT": "Portugués (Portugal)", "locale.es419": "Español (Latinoamérica)", "locale.zhCN": "Chino simplificado", + "locale.zhTW": "Chino tradicional", "locale.jaJP": "Japonés", "locale.koKR": "Coreano", "locale.vi": "Vietnamita" diff --git a/src/lib/locales/es-ES.json b/src/lib/locales/es-ES.json index 94f64e5e..536fdf9f 100644 --- a/src/lib/locales/es-ES.json +++ b/src/lib/locales/es-ES.json @@ -9,7 +9,7 @@ "command.openSettings": "Abrir Ajustes", "command.openSettings.keywords": "preferencias config", "command.openLanguageSettings": "Abrir la configuración de idioma", - "command.openLanguageSettings.keywords": "idioma configuración regional i18n internacionalización localización inglés italiano francés alemán ruso español portugués chino japonés coreano 中文", + "command.openLanguageSettings.keywords": "idioma configuración regional i18n internacionalización localización inglés italiano francés alemán ruso español portugués chino simplificado tradicional japonés coreano 中文 繁體中文 zh-tw", "command.useSystemLanguage": "Usar el idioma del sistema", "command.openH1Setting": "Abrir la configuración de renombrado automático de H1", "command.toggleGitignoredFilesVisibility": "Activar/desactivar la visibilidad de los archivos Gitignored", @@ -129,6 +129,14 @@ "settings.vaultContent.description": "Controla si los archivos que coinciden con el .gitignore del repositorio aparecen en Tolaria.", "settings.vaultContent.hideGitignored": "Ocultar archivos y carpetas ignorados por Git", "settings.vaultContent.hideGitignoredDescription": "Evita que los archivos del almacén generados y solo locales aparezcan en las notas, la búsqueda, la apertura rápida y las carpetas.", + "settings.allNotesVisibility.title": "Visibilidad de Todas las notas", + "settings.allNotesVisibility.description": "Elija qué categorías de archivos que no son Markdown aparecen en Todas las notas. Al explorar las carpetas, los archivos siguen mostrándose en sus carpetas.", + "settings.allNotesVisibility.pdfs": "PDF", + "settings.allNotesVisibility.pdfsDescription": "Mostrar archivos PDF en Todas las notas.", + "settings.allNotesVisibility.images": "Imágenes", + "settings.allNotesVisibility.imagesDescription": "Mostrar los archivos de imagen habituales en Todas las notas.", + "settings.allNotesVisibility.unsupported": "Archivos no compatibles", + "settings.allNotesVisibility.unsupportedDescription": "Mostrar otros archivos que no sean Markdown y que no tengan vista previa en la aplicación.", "settings.aiAgents.title": "Agentes de IA", "settings.aiAgents.description": "Elija qué agente de IA de CLI utiliza Tolaria en el panel de IA y en la paleta de comandos.", "settings.aiAgents.default": "Agente de IA predeterminado", @@ -485,6 +493,7 @@ "locale.ptPT": "Portugués (Portugal)", "locale.es419": "Español (Latinoamérica)", "locale.zhCN": "中国简体", + "locale.zhTW": "Chino tradicional", "locale.jaJP": "Japonés", "locale.koKR": "Coreano", "locale.vi": "Vietnamita" diff --git a/src/lib/locales/fr-FR.json b/src/lib/locales/fr-FR.json index d482aa69..d9b46b59 100644 --- a/src/lib/locales/fr-FR.json +++ b/src/lib/locales/fr-FR.json @@ -9,7 +9,7 @@ "command.openSettings": "Ouvrir les paramètres", "command.openSettings.keywords": "préférences config", "command.openLanguageSettings": "Ouvrir les paramètres de langue", - "command.openLanguageSettings.keywords": "langue paramètres régionaux i18n internationalisation localisation anglais italien français allemand russe espagnol portugais chinois japonais coréen 中文", + "command.openLanguageSettings.keywords": "langue paramètres régionaux i18n internationalisation localisation anglais italien français allemand russe espagnol portugais chinois simplifié traditionnel japonais coréen 中文 繁體中文 zh-tw", "command.useSystemLanguage": "Utiliser la langue du système", "command.openH1Setting": "Ouvrir le paramètre de renommage automatique des titres H1", "command.toggleGitignoredFilesVisibility": "Activer/désactiver la visibilité des fichiers Gitignored", @@ -129,6 +129,14 @@ "settings.vaultContent.description": "Contrôler si les fichiers correspondants au fichier .gitignore du coffre-fort apparaissent dans Tolaria.", "settings.vaultContent.hideGitignored": "Masquer les fichiers et les dossiers ignorés par Git", "settings.vaultContent.hideGitignoredDescription": "Exclut les fichiers du coffre-fort générés et locaux des notes, de la recherche, de l'ouverture rapide et des dossiers.", + "settings.allNotesVisibility.title": "Visibilité de Toutes les notes", + "settings.allNotesVisibility.description": "Choisissez les catégories de fichiers non Markdown qui apparaissent dans Toutes les notes. Lors de la navigation dans les dossiers, les fichiers continuent d'être affichés dans leurs dossiers.", + "settings.allNotesVisibility.pdfs": "PDF", + "settings.allNotesVisibility.pdfsDescription": "Afficher les fichiers PDF dans Toutes les notes.", + "settings.allNotesVisibility.images": "Images", + "settings.allNotesVisibility.imagesDescription": "Afficher les fichiers image courants dans Toutes les notes.", + "settings.allNotesVisibility.unsupported": "Fichiers non pris en charge", + "settings.allNotesVisibility.unsupportedDescription": "Afficher les autres fichiers non Markdown qui ne disposent pas d'un aperçu dans l'application.", "settings.aiAgents.title": "Agents d'IA", "settings.aiAgents.description": "Choisissez l'agent d'IA CLI que Tolaria utilise dans le panneau d'IA et la palette de commandes.", "settings.aiAgents.default": "Agent d'IA par défaut", @@ -485,6 +493,7 @@ "locale.ptPT": "Portugais (Portugal)", "locale.es419": "Espagnol (Amérique latine)", "locale.zhCN": "Chinois simplifié", + "locale.zhTW": "Chinois traditionnel", "locale.jaJP": "Japonais", "locale.koKR": "Coréen", "locale.vi": "Vietnamien" diff --git a/src/lib/locales/it-IT.json b/src/lib/locales/it-IT.json index f6a51c46..0fc06943 100644 --- a/src/lib/locales/it-IT.json +++ b/src/lib/locales/it-IT.json @@ -9,7 +9,7 @@ "command.openSettings": "Apri le impostazioni", "command.openSettings.keywords": "preferences config", "command.openLanguageSettings": "Apri le impostazioni della lingua", - "command.openLanguageSettings.keywords": "lingua locale i18n internazionalizzazione localizzazione inglese italiano francese tedesco russo spagnolo portoghese cinese giapponese coreano 中文", + "command.openLanguageSettings.keywords": "lingua locale i18n internazionalizzazione localizzazione inglese italiano francese tedesco russo spagnolo portoghese cinese semplificato tradizionale giapponese coreano 中文 繁體中文 zh-tw", "command.useSystemLanguage": "Usa la lingua di sistema", "command.openH1Setting": "Apri l'impostazione di rinomina automatica H1", "command.toggleGitignoredFilesVisibility": "Attiva/disattiva la visibilità dei file Gitignored", @@ -129,6 +129,14 @@ "settings.vaultContent.description": "Controlla se i file corrispondenti al file .gitignore del vault vengono visualizzati in Tolaria.", "settings.vaultContent.hideGitignored": "Nascondi file e cartelle ignorati da Git", "settings.vaultContent.hideGitignoredDescription": "Esclude i file del vault generati e quelli solo locali dalle note, dalla ricerca, dall'apertura rapida e dalle cartelle.", + "settings.allNotesVisibility.title": "Visibilità di All Notes", + "settings.allNotesVisibility.description": "Scegli quali categorie di file non Markdown devono essere visualizzate in Tutte le note. Durante la navigazione tra le cartelle, i file continuano a essere visualizzati nelle rispettive cartelle.", + "settings.allNotesVisibility.pdfs": "PDF", + "settings.allNotesVisibility.pdfsDescription": "Mostra i file PDF in Tutte le note.", + "settings.allNotesVisibility.images": "Immagini", + "settings.allNotesVisibility.imagesDescription": "Mostra i file immagine comuni in Tutte le note.", + "settings.allNotesVisibility.unsupported": "檔案不受支援", + "settings.allNotesVisibility.unsupportedDescription": "Mostra altri file non Markdown che non dispongono di anteprima nell'app.", "settings.aiAgents.title": "Agenti IA", "settings.aiAgents.description": "Scegli quale agente IA CLI deve utilizzare Tolaria nel pannello IA e nella palette dei comandi.", "settings.aiAgents.default": "Agente IA predefinito", @@ -485,6 +493,7 @@ "locale.ptPT": "Português (Portugal)", "locale.es419": "Español (Latinoamérica)", "locale.zhCN": "中文简体", + "locale.zhTW": "繁體中文", "locale.jaJP": "Japonais", "locale.koKR": "Coreano", "locale.vi": "Vietnamita" diff --git a/src/lib/locales/ja-JP.json b/src/lib/locales/ja-JP.json index 244cad58..345fa9b4 100644 --- a/src/lib/locales/ja-JP.json +++ b/src/lib/locales/ja-JP.json @@ -9,7 +9,7 @@ "command.openSettings": "設定を開く", "command.openSettings.keywords": "preferences config", "command.openLanguageSettings": "言語設定を開く", - "command.openLanguageSettings.keywords": "言語 ロケール i18n 国際化 ローカリゼーション 英語 イタリア語 フランス語 ドイツ語 ロシア語 スペイン語 ポルトガル語 中国語 日本語 韓国語 中文", + "command.openLanguageSettings.keywords": "言語、ロケール、i18n、国際化、ローカライゼーション、英語、イタリア語、フランス語、ドイツ語、ロシア語、スペイン語、ポルトガル語、中国語(簡体)、中国語(繁体)、日本語、韓国語、中文(繁體)、zh-tw", "command.useSystemLanguage": "システム言語を使用", "command.openH1Setting": "H1 自動名前変更設定を開く", "command.toggleGitignoredFilesVisibility": "Gitignoredファイルの表示/非表示を切り替える", @@ -129,6 +129,14 @@ "settings.vaultContent.description": "Vaultの.gitignoreで一致したファイルをTolariaに表示するかどうかを制御します。", "settings.vaultContent.hideGitignored": "Gitによって無視されるファイルとフォルダーを非表示にする", "settings.vaultContent.hideGitignoredDescription": "生成されたVaultファイルとローカル専用のVaultファイルを、ノート、検索、クイックオープン、フォルダーから除外します。", + "settings.allNotesVisibility.title": "「すべてのノート」の表示設定", + "settings.allNotesVisibility.description": "「すべてのノート」に表示する非 Markdown ファイルのカテゴリを選択します。フォルダー参照では、引き続きファイルがそれぞれのフォルダー内に表示されます。", + "settings.allNotesVisibility.pdfs": "PDF", + "settings.allNotesVisibility.pdfsDescription": "PDFファイルを「すべてのノート」に表示する。", + "settings.allNotesVisibility.images": "画像", + "settings.allNotesVisibility.imagesDescription": "一般的な画像ファイルを「すべてのノート」に表示する。", + "settings.allNotesVisibility.unsupported": "サポートされていないファイル", + "settings.allNotesVisibility.unsupportedDescription": "アプリ内プレビューがない、Markdown 以外のその他のファイルを表示する。", "settings.aiAgents.title": "AIエージェント", "settings.aiAgents.description": "TolariaがAIパネルとコマンドパレットで使用するCLI AIエージェントを選択します。", "settings.aiAgents.default": "デフォルトのAIエージェント", @@ -485,6 +493,7 @@ "locale.ptPT": "葡萄牙語(ポルトガル)", "locale.es419": "西班牙语(拉丁美洲)", "locale.zhCN": "简体中文", + "locale.zhTW": "繁體中文", "locale.jaJP": "日本語", "locale.koKR": "韩国語", "locale.vi": "ベトナム語" diff --git a/src/lib/locales/ko-KR.json b/src/lib/locales/ko-KR.json index 77a0da43..0c6d4e53 100644 --- a/src/lib/locales/ko-KR.json +++ b/src/lib/locales/ko-KR.json @@ -9,7 +9,7 @@ "command.openSettings": "설정 열기", "command.openSettings.keywords": "preferences config", "command.openLanguageSettings": "언어 설정 열기", - "command.openLanguageSettings.keywords": "언어 로케일 i18n 국제화 현지화 영어 이탈리아어 프랑스어 독일어 러시아어 스페인어 포르투갈어 중국어 일본어 한국어 中文", + "command.openLanguageSettings.keywords": "언어 로케일 i18n 국제화 현지화 영어 이탈리아어 프랑스어 독일어 러시아어 스페인어 포르투갈어 중국어 간체 중국어 번체 일본어 한국어 中文 繁體中文 zh-tw", "command.useSystemLanguage": "시스템 언어 사용", "command.openH1Setting": "H1 자동 이름 변경 설정 열기", "command.toggleGitignoredFilesVisibility": "Gitignored 파일 표시/숨기기", @@ -129,6 +129,14 @@ "settings.vaultContent.description": "Vault .gitignore와 일치하는 파일이 Tolaria에 표시되는지 여부를 제어합니다.", "settings.vaultContent.hideGitignored": "Git에서 무시하는 파일 및 폴더 숨기기", "settings.vaultContent.hideGitignoredDescription": "생성된 Vault 파일과 로컬 전용 Vault 파일을 노트, 검색, 빠른 열기 기능, 폴더에서 제외합니다.", + "settings.allNotesVisibility.title": "모든 노트 표시 여부", + "settings.allNotesVisibility.description": "'모든 노트'에 표시할 비 Markdown 파일 카테고리를 선택하세요. 폴더 탐색 시에도 파일이 해당 폴더에 표시됩니다.", + "settings.allNotesVisibility.pdfs": "PDF", + "settings.allNotesVisibility.pdfsDescription": "PDF 파일을 '모든 노트'에 표시합니다.", + "settings.allNotesVisibility.images": "이미지", + "settings.allNotesVisibility.imagesDescription": "'모든 노트'에 일반적인 이미지 파일을 표시합니다.", + "settings.allNotesVisibility.unsupported": "지원되지 않는 파일", + "settings.allNotesVisibility.unsupportedDescription": "앱 내 미리 보기가 없는 그 외의 비 Markdown 파일 표시.", "settings.aiAgents.title": "AI 에이전트", "settings.aiAgents.description": "Tolaria가 AI 패널과 명령 팔레트에서 사용하는 CLI AI 에이전트를 선택하세요.", "settings.aiAgents.default": "기본 AI 에이전트", @@ -485,6 +493,7 @@ "locale.ptPT": "포르투갈어 (포르투갈)", "locale.es419": "스페인어(라틴 아메리카)", "locale.zhCN": "简体中文", + "locale.zhTW": "繁體中文", "locale.jaJP": "日本語", "locale.koKR": "한국어", "locale.vi": "베트남어" diff --git a/src/lib/locales/pt-BR.json b/src/lib/locales/pt-BR.json index 937bb680..ddb9a061 100644 --- a/src/lib/locales/pt-BR.json +++ b/src/lib/locales/pt-BR.json @@ -9,7 +9,7 @@ "command.openSettings": "Abrir configurações", "command.openSettings.keywords": "configuração de preferências", "command.openLanguageSettings": "Abrir configurações de idioma", - "command.openLanguageSettings.keywords": "idioma localidade i18n internacionalização localização inglês italiano francês alemão russo espanhol português chinês japonês coreano 中文", + "command.openLanguageSettings.keywords": "idioma localidade i18n internacionalização localização inglês italiano francês alemão russo espanhol português chinês simplificado tradicional japonês coreano 中文 繁體中文 zh-tw", "command.useSystemLanguage": "Usar o idioma do sistema", "command.openH1Setting": "Abrir configuração de renomeação automática de H1", "command.toggleGitignoredFilesVisibility": "Alternar visibilidade dos arquivos Gitignored", @@ -129,6 +129,14 @@ "settings.vaultContent.description": "Controle se os arquivos correspondentes ao .gitignore do cofre aparecem no Tolaria.", "settings.vaultContent.hideGitignored": "Ocultar arquivos e pastas ignorados pelo Git", "settings.vaultContent.hideGitignoredDescription": "Mantém os arquivos do cofre gerados e apenas locais fora das anotações, da pesquisa, da abertura rápida e das pastas.", + "settings.allNotesVisibility.title": "Visibilidade de Todas as anotações", + "settings.allNotesVisibility.description": "Escolha quais categorias de arquivos que não são Markdown aparecem em Todas as notas. Ao navegar pelas pastas, os arquivos ainda são exibidos em suas pastas.", + "settings.allNotesVisibility.pdfs": "PDFs", + "settings.allNotesVisibility.pdfsDescription": "Exibir arquivos PDF em Todas as anotações.", + "settings.allNotesVisibility.images": "Imagens", + "settings.allNotesVisibility.imagesDescription": "Exibir arquivos de imagem comuns em Todas as notas.", + "settings.allNotesVisibility.unsupported": "Arquivos não suportados", + "settings.allNotesVisibility.unsupportedDescription": "Exibir outros arquivos que não sejam Markdown e que não tenham visualização no aplicativo.", "settings.aiAgents.title": "Agentes de IA", "settings.aiAgents.description": "Escolha qual agente de IA de CLI o Tolaria usa no painel de IA e na paleta de comandos.", "settings.aiAgents.default": "Agente de IA padrão", @@ -485,6 +493,7 @@ "locale.ptPT": "Português (Portugal)", "locale.es419": "Espanhol (América Latina)", "locale.zhCN": "简体中文", + "locale.zhTW": "Chinês tradicional", "locale.jaJP": "Japonês", "locale.koKR": "Coreano", "locale.vi": "Vietnamita" diff --git a/src/lib/locales/pt-PT.json b/src/lib/locales/pt-PT.json index deb1f380..15098569 100644 --- a/src/lib/locales/pt-PT.json +++ b/src/lib/locales/pt-PT.json @@ -9,7 +9,7 @@ "command.openSettings": "Abrir Definições", "command.openSettings.keywords": "configuração de preferências", "command.openLanguageSettings": "Abrir definições de idioma", - "command.openLanguageSettings.keywords": "idioma localização i18n internacionalização localização inglês italiano francês alemão russo espanhol português chinês japonês coreano 中文", + "command.openLanguageSettings.keywords": "idioma localização i18n internacionalização localização inglês italiano francês alemão russo espanhol português chinês simplificado tradicional japonês coreano 中文 繁體中文 zh-tw", "command.useSystemLanguage": "Utilizar o idioma do sistema", "command.openH1Setting": "Abrir a definição de renomeação automática de H1", "command.toggleGitignoredFilesVisibility": "Alternar a visibilidade dos ficheiros Gitignored", @@ -129,6 +129,14 @@ "settings.vaultContent.description": "Controlar se os ficheiros correspondentes ao .gitignore do cofre aparecem na Tolaria.", "settings.vaultContent.hideGitignored": "Ocultar ficheiros e pastas ignorados pelo Git", "settings.vaultContent.hideGitignoredDescription": "Mantém os ficheiros do cofre gerados e apenas locais fora das notas, da pesquisa, da abertura rápida e das pastas.", + "settings.allNotesVisibility.title": "Visibilidade de Todas as notas", + "settings.allNotesVisibility.description": "Escolha as categorias de ficheiros não Markdown que aparecem em Todas as notas. A navegação por pastas continua a mostrar os ficheiros nas respetivas pastas.", + "settings.allNotesVisibility.pdfs": "PDF", + "settings.allNotesVisibility.pdfsDescription": "Mostrar ficheiros PDF em Todas as notas.", + "settings.allNotesVisibility.images": "Imagens", + "settings.allNotesVisibility.imagesDescription": "Mostrar ficheiros de imagem comuns em Todas as notas.", + "settings.allNotesVisibility.unsupported": "Ficheiros não suportados", + "settings.allNotesVisibility.unsupportedDescription": "Mostrar outros ficheiros não Markdown que não tenham pré-visualização na aplicação.", "settings.aiAgents.title": "Agentes de IA", "settings.aiAgents.description": "Escolha que agente de IA de CLI é utilizado pela Tolaria no painel de IA e na paleta de comandos.", "settings.aiAgents.default": "Agente de IA predefinido", @@ -485,6 +493,7 @@ "locale.ptPT": "Português (Portugal)", "locale.es419": "Espanhol (América Latina)", "locale.zhCN": "Chinês simplificado", + "locale.zhTW": "Chinês tradicional", "locale.jaJP": "Japonês", "locale.koKR": "Coreano", "locale.vi": "Vietnamita" diff --git a/src/lib/locales/ru-RU.json b/src/lib/locales/ru-RU.json index 332dc6df..73fbb913 100644 --- a/src/lib/locales/ru-RU.json +++ b/src/lib/locales/ru-RU.json @@ -9,7 +9,7 @@ "command.openSettings": "Открыть настройки", "command.openSettings.keywords": "Настройки конфигурации", "command.openLanguageSettings": "Открыть настройки языка", - "command.openLanguageSettings.keywords": "язык регион i18n интернационализация локализация английский итальянский французский немецкий русский испанский португальский китайский японский корейский 中文", + "command.openLanguageSettings.keywords": "Язык Регион i18n Интернационализация Локализация Английский Итальянский Французский Немецкий Русский Испанский Португальский Китайский (упрощенный) Китайский (традиционный) Японский Корейский 中文 繁體中文 zh-tw", "command.useSystemLanguage": "Использовать язык системы", "command.openH1Setting": "Открыть настройку автоматического переименования H1", "command.toggleGitignoredFilesVisibility": "Переключить отображение файлов Gitignored", @@ -129,6 +129,14 @@ "settings.vaultContent.description": "Управляйте тем, будут ли отображаться в Tolaria файлы, соответствующие списку .gitignore хранилища.", "settings.vaultContent.hideGitignored": "Скрыть файлы и папки, игнорируемые Git", "settings.vaultContent.hideGitignoredDescription": "Не допускает включения сгенерированных и только локальных файлов хранилища в заметки, поиск, быстрое открытие и папки.", + "settings.allNotesVisibility.title": "Видимость в разделе «Все заметки»", + "settings.allNotesVisibility.description": "Выберите, какие категории файлов, не относящихся к Markdown, будут отображаться в разделе «Все заметки». При просмотре папок файлы по-прежнему отображаются в своих папках.", + "settings.allNotesVisibility.pdfs": "PDF-файлы", + "settings.allNotesVisibility.pdfsDescription": "Показывать PDF-файлы в разделе «Все заметки».", + "settings.allNotesVisibility.images": "Изображения", + "settings.allNotesVisibility.imagesDescription": "Показывать распространенные файлы изображений в разделе «Все заметки».", + "settings.allNotesVisibility.unsupported": "Неподдерживаемые файлы", + "settings.allNotesVisibility.unsupportedDescription": "Показывать другие файлы, не относящиеся к Markdown, для которых нет предварительного просмотра в приложении.", "settings.aiAgents.title": "AI-агенты", "settings.aiAgents.description": "Выберите, какой CLI-агент ИИ Tolaria будет использовать на панели ИИ и в палитре команд.", "settings.aiAgents.default": "AI-агент по умолчанию", @@ -485,6 +493,7 @@ "locale.ptPT": "葡萄牙语(葡萄牙)", "locale.es419": "西班牙语(拉丁美洲)", "locale.zhCN": "简体中文", + "locale.zhTW": "繁體中文", "locale.jaJP": "日本語", "locale.koKR": "Coreano", "locale.vi": "Вьетнамский" diff --git a/src/lib/locales/zh-CN.json b/src/lib/locales/zh-CN.json index d52e7724..851e74f2 100644 --- a/src/lib/locales/zh-CN.json +++ b/src/lib/locales/zh-CN.json @@ -9,7 +9,7 @@ "command.openSettings": "打开设置", "command.openSettings.keywords": "设置 偏好 配置", "command.openLanguageSettings": "打开语言设置", - "command.openLanguageSettings.keywords": "语言 区域 i18n 国际化 本地化 中文 english italian french german russian spanish portuguese japanese korean", + "command.openLanguageSettings.keywords": "语言 区域设置 i18n 国际化 本地化 英语 意大利语 法语 德语 俄语 西班牙语 葡萄牙语 中文 简体中文 繁体中文 日语 韩语 中文 繁体中文 zh-tw", "command.useSystemLanguage": "使用系统语言", "command.openH1Setting": "打开 H1 自动重命名设置", "command.toggleGitignoredFilesVisibility": "切换 Gitignored 文件的可见性", @@ -129,6 +129,14 @@ "settings.vaultContent.description": "控制与 Vault .gitignore 文件匹配的文件是否显示在 Tolaria 中。", "settings.vaultContent.hideGitignored": "隐藏 Git 忽略的文件和文件夹", "settings.vaultContent.hideGitignoredDescription": "将生成的 Vault 文件和仅限本地的 Vault 文件排除在笔记、搜索、快速打开和文件夹之外。", + "settings.allNotesVisibility.title": "所有笔记的可见性", + "settings.allNotesVisibility.description": "选择要在“所有笔记”中显示的非 Markdown 文件类别。浏览文件夹时,仍会显示文件夹中的文件。", + "settings.allNotesVisibility.pdfs": "PDF 文件", + "settings.allNotesVisibility.pdfsDescription": "在“所有笔记”中显示 PDF 文件。", + "settings.allNotesVisibility.images": "图像", + "settings.allNotesVisibility.imagesDescription": "在“所有笔记”中显示常见图像文件。", + "settings.allNotesVisibility.unsupported": "不支持的文件", + "settings.allNotesVisibility.unsupportedDescription": "显示其他无法在应用内预览的非 Markdown 文件。", "settings.aiAgents.title": "AI 代理", "settings.aiAgents.description": "选择 Tolaria 在 AI 面板和命令面板中使用的 CLI AI 代理。", "settings.aiAgents.default": "默认 AI 代理", @@ -485,6 +493,7 @@ "locale.ptPT": "葡萄牙语(葡萄牙)", "locale.es419": "西班牙语(拉丁美洲)", "locale.zhCN": "简体中文", + "locale.zhTW": "繁体中文", "locale.jaJP": "日语", "locale.koKR": "韩语", "locale.vi": "越南语" diff --git a/src/lib/locales/zh-TW.json b/src/lib/locales/zh-TW.json index f277ec6f..53c93ad7 100644 --- a/src/lib/locales/zh-TW.json +++ b/src/lib/locales/zh-TW.json @@ -9,9 +9,10 @@ "command.openSettings": "開啟設定", "command.openSettings.keywords": "設定 偏好 配置", "command.openLanguageSettings": "開啟語言設定", - "command.openLanguageSettings.keywords": "語言 區域 i18n 國際化 本地化 中文 簡體中文 繁體中文 繁体中文 zh-cn zh-tw english italian french german russian spanish portuguese japanese korean", + "command.openLanguageSettings.keywords": "語言、地區設定、i18n、國際化、本地化、英語、義大利文、法文、德文、俄文、西班牙文、葡萄牙文、簡體中文、繁體中文、日文、韓文、中文 繁體中文、zh-tw", "command.useSystemLanguage": "使用系統語言", "command.openH1Setting": "開啟 H1 自動重新命名設定", + "command.toggleGitignoredFilesVisibility": "切換 Gitignored 檔案的顯示狀態", "command.contribute": "參與貢獻", "command.checkUpdates": "檢查更新", "command.group.navigation": "導航", @@ -63,11 +64,19 @@ "command.view.toggleProperties": "切換屬性面板", "command.view.toggleDiff": "切換差異模式", "command.view.toggleRaw": "切換原始碼編輯器", + "command.view.noteWidthNormal": "使用一般筆記寬度", + "command.view.noteWidthWide": "使用寬筆記寬度", + "command.view.defaultNoteWidthNormal": "預設使用一般筆記寬度", + "command.view.defaultNoteWidthWide": "預設使用寬筆記寬度", "command.view.leftLayout": "使用左對齊筆記佈局", "command.view.centerLayout": "使用居中筆記佈局", "command.view.toggleAiPanel": "切換 AI 面板", "command.view.newAiChat": "新建 AI 對話", "command.view.toggleBacklinks": "切換反向連結", + "command.view.moveViewUp": "向上移動檢視區", + "command.view.moveViewDown": "將檢視區向下移動", + "command.view.moveNamedViewUp": "向上移動 {name}", + "command.view.moveNamedViewDown": "向下移動 {name}", "command.view.zoomIn": "放大({zoom}%)", "command.view.zoomOut": "縮小({zoom}%)", "command.view.resetZoom": "重置縮放", @@ -81,6 +90,7 @@ "command.settings.repairVault": "修復倉庫", "command.settings.useLightMode": "使用淺色模式", "command.settings.useDarkMode": "使用深色模式", + "command.settings.toggleGitignoredFilesVisibility": "切換 Gitignored 檔案的顯示狀態", "command.ai.openAgents": "開啟 AI 代理設定", "command.ai.restoreGuidance": "恢復 Tolaria AI 指導檔案", "command.ai.switchToAgent": "將 AI 代理切換為 {agent}", @@ -115,6 +125,18 @@ "settings.titles.description": "選擇 Tolaria 是否根據第一個 H1 標題自動同步未命名筆記的檔名。", "settings.titles.autoRename": "根據第一個 H1 自動重新命名未命名筆記", "settings.titles.autoRenameDescription": "啟用後,只要第一個 H1 成為真實標題,Tolaria 就會重新命名 untitled-note 檔案。關閉後,檔名會保持不變,直到你從麵包屑欄手動重新命名。", + "settings.vaultContent.title": "保管庫內容", + "settings.vaultContent.description": "控制與 Vault .gitignore 相符的檔案是否顯示在 Tolaria 中。", + "settings.vaultContent.hideGitignored": "隱藏 Git 忽略的檔案和資料夾", + "settings.vaultContent.hideGitignoredDescription": "將已產生的 Vault 檔案和僅限本機的 Vault 檔案排除在筆記、搜尋、快速開啟和資料夾之外。", + "settings.allNotesVisibility.title": "「所有筆記」可見性", + "settings.allNotesVisibility.description": "選擇要在「所有筆記」中顯示哪些非 Markdown 檔案類別。瀏覽資料夾時,仍會顯示資料夾中的檔案。", + "settings.allNotesVisibility.pdfs": "PDF 檔案", + "settings.allNotesVisibility.pdfsDescription": "在「所有筆記」中顯示 PDF 檔案。", + "settings.allNotesVisibility.images": "圖片", + "settings.allNotesVisibility.imagesDescription": "在「所有筆記」中顯示常見的圖像檔案。", + "settings.allNotesVisibility.unsupported": "不支援的檔案", + "settings.allNotesVisibility.unsupportedDescription": "顯示其他無法在應用程式中預覽的非 Markdown 檔案。", "settings.aiAgents.title": "AI 代理", "settings.aiAgents.description": "選擇 Tolaria 在 AI 面板和命令面板中使用的 CLI AI 代理。", "settings.aiAgents.default": "預設 AI 代理", @@ -138,6 +160,68 @@ "settings.cancel": "取消", "settings.save": "儲存", "common.cancel": "取消", + "ai.permission.safe.short": "Safe", + "ai.permission.safe.control": "Vault Safe", + "ai.permission.safe.tooltip": "Vault Safe 讓客服人員的權限僅限於檔案、搜尋和編輯工具。", + "ai.permission.powerUser.short": "進階使用者", + "ai.permission.powerUser.control": "進階使用者", + "ai.permission.powerUser.tooltip": "Power User 還允許在此 Vault 中使用本機 Shell 命令。", + "ai.permission.modeAria": "AI 客服人員權限模式", + "ai.permission.changed": "AI 權限模式已變更為 {label}。此變更將套用至下一則訊息。", + "ai.panel.title": "AI 代理程式", + "ai.panel.status.checking": "正在檢查可用性", + "ai.panel.status.missing": "{agent} · 未安裝", + "ai.panel.status.ready": "{agent} · {mode}", + "ai.panel.copyMcpConfig": "複製 MCP 設定", + "ai.panel.mcpConfig": "MCP 設定", + "ai.panel.newChat": "新建 AI 聊天", + "ai.panel.close": "關閉 AI 面板", + "ai.panel.linkedCount": "+ {count} 個已連結", + "ai.panel.empty.checkingTitle": "正在檢查 AI 客服人員的空閒狀態", + "ai.panel.empty.checkingDescription": "當所選客服人員準備就緒時,即可傳送訊息", + "ai.panel.empty.missingTitle": "{agent} 在此電腦上無法使用", + "ai.panel.empty.missingDescription": "請安裝它,或在「設定」中切換預設的 AI 代理程式", + "ai.panel.empty.withContextTitle": "向 {agent} 詢問有關此筆記及其連結內容的問題", + "ai.panel.empty.noContextTitle": "開啟一則筆記,然後向 {agent} 詢問有關該筆記的問題", + "ai.panel.empty.withContextDescription": "進行總結、找出關聯、拓展想法", + "ai.panel.empty.noContextDescription": "人工智慧將使用目前啟用的筆記作為背景資訊", + "ai.panel.placeholder.checking": "正在檢查 AI 代理程式的可用性……", + "ai.panel.placeholder.missing": "未安裝 {agent}。在「設定」中開啟 AI 代理程式。", + "ai.panel.placeholder.ready": "詢問 {agent}", + "ai.panel.send": "傳送訊息", + "mcp.setup.manageTitle": "管理外部 AI 工具", + "mcp.setup.setupTitle": "設定外部 AI 工具", + "mcp.setup.connectedDescription": "Tolaria 已經連接到此 Vault 的外部 AI 工具。重新連線以重新載入設定,或中斷連線以從這些第三方設定檔案中移除 Tolaria。", + "mcp.setup.setupDescription": "Tolaria 可以將其 MCP 伺服器新增至此 Vault 的外部 AI 工具,但除非您在此處確認,否則 Tolaria 不會修改第三方設定檔案。", + "mcp.setup.reconnect": "重新連接外部 AI 工具", + "mcp.setup.connect": "連接外部 AI 工具", + "mcp.setup.disconnect": "中斷連線", + "mcp.setup.connecting": "正在連線…", + "mcp.setup.disconnecting": "正在中斷連線…", + "mcp.setup.nodeRequirement": "此設定需要在 PATH 中設定 Node.js 18 以上版本,並使用與 MCP 相容的桌面工具。Tolaria 會在寫入設定之前檢查 Node.js,以確保工具不會指向無效的命令。", + "mcp.setup.writeEntryDescription": "確認此操作將寫入或更新 Tolaria 在以下位置的單一 {entry} MCP 條目:", + "mcp.setup.clientPathsDescription": "Claude Code CLI 會讀取 ~/.claude.json,Gemini CLI 會讀取 ~/.gemini/settings.json,Cursor 會讀取 ~/.cursor/mcp.json,而其他與 MCP 相容的工具則會讀取通用的 ~/.config/mcp/mcp.json 路徑。關閉後,除非您連線或中斷連線,否則所有檔案都不會受到影響。重新連線是等同於初始狀態的操作,而中斷連線會再次移除 Tolaria 的條目。", + "mcp.setup.geminiGuidanceDescription": "Gemini CLI 需要單獨安裝並登入。當您希望有一個 Vault 根目錄的 GEMINI.md 相容性輔助層,能夠在不覆寫自訂指南的情況下將 Gemini 重新導向至共享的 AGENTS.md 指示時,請使用「Restore Tolaria AI Guidance」。", + "mcp.setup.manual.title": "手動 MCP 設定", + "mcp.setup.manual.copy": "複製 MCP 設定", + "mcp.setup.manual.loading": "正在載入確切的 MCP 設定……", + "mcp.setup.manual.unavailable": "開啟 Vault 後,即可取得確切的 MCP 設定。", + "mcp.toast.connected": "已成功連接 Tolaria 外部 AI 工具", + "mcp.toast.refreshed": "Tolaria 外部 AI 工具設定已成功重新整理", + "mcp.toast.disconnected": "已成功中斷 Tolaria 外部 AI 工具的連線", + "mcp.toast.alreadyDisconnected": "Tolaria 外部 AI 工具已經中斷連線", + "mcp.toast.configCopied": "Tolaria MCP 設定已複製到剪貼簿", + "mcp.toast.configCopyFailed": "複製 MCP 設定失敗:{error}", + "mcp.toast.setupFailed": "外部 AI 工具設定失敗:{error}", + "mcp.toast.disconnectFailed": "中斷外部 AI 工具連線失敗:{error}", + "mcp.error.clipboardUnavailable": "剪貼簿 API 無法使用", + "save.toast.saved": "已儲存", + "save.toast.nothingToSave": "沒有要儲存的內容", + "save.toast.missingActiveVault": "請在儲存前選擇或還原一個保管庫。", + "save.error.failed": "儲存失敗:{error}", + "save.error.autoFailed": "自動儲存失敗:{error}", + "save.error.invalidPath": "儲存失敗:筆記路徑在此平台上無效。請重新命名筆記或將其移動至有效的資料夾,然後再試一次。", + "savedViews.reordered": "已重新排序檢視", "locale.en": "英文", "sidebar.nav.inbox": "收件箱", "sidebar.nav.allNotes": "全部筆記", @@ -149,6 +233,9 @@ "sidebar.action.createView": "建立檢視", "sidebar.action.editView": "編輯檢視", "sidebar.action.deleteView": "刪除檢視", + "sidebar.action.reorderView": "重新排序檢視", + "sidebar.action.moveViewUp": "將檢視向上移動", + "sidebar.action.moveViewDown": "將檢視向下移動", "sidebar.action.customizeSections": "自定義分組", "sidebar.action.renameSection": "重新命名分組…", "sidebar.action.customizeIconColor": "自定義圖示和顏色…", @@ -239,6 +326,8 @@ "editor.find.replaceAll": "全部", "editor.toolbar.rawReturn": "返回編輯器", "editor.toolbar.rawOpen": "開啟原始碼編輯器", + "editor.toolbar.noteWidthNormal": "切換為一般筆記寬度", + "editor.toolbar.noteWidthWide": "切換為寬筆記寬度", "editor.toolbar.centerLayout": "切換到居中筆記佈局", "editor.toolbar.leftLayout": "切換到左對齊筆記佈局", "editor.toolbar.removeFavorite": "從收藏中移除", @@ -318,6 +407,8 @@ "status.vault.cloneGit": "克隆 Git 倉庫", "status.vault.cloneGettingStarted": "克隆入門倉庫", "status.vault.notFound": "未找到倉庫:{path}", + "status.vault.reloading": "正在重新載入 Vault……", + "status.vault.reloadingTooltip": "正在從磁碟重新載入 Vault", "status.vault.remove": "從列表移除 {label}", "status.remote.noneConfigured": "未配置遠端倉庫", "status.remote.inSync": "已與遠端同步", @@ -404,5 +495,6 @@ "locale.zhCN": "簡體中文", "locale.zhTW": "繁體中文", "locale.jaJP": "日語", - "locale.koKR": "韓語" + "locale.koKR": "韓語", + "locale.vi": "越南文" } diff --git a/src/types.ts b/src/types.ts index 1ba0c8e4..214c5d8f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -100,6 +100,9 @@ export interface Settings { initial_h1_auto_rename_enabled?: boolean | null default_ai_agent?: AiAgentId | null hide_gitignored_files?: boolean | null + all_notes_show_pdfs?: boolean | null + all_notes_show_images?: boolean | null + all_notes_show_unsupported?: boolean | null } export interface GitPullResult { diff --git a/src/utils/allNotesFileVisibility.ts b/src/utils/allNotesFileVisibility.ts new file mode 100644 index 00000000..1098cd59 --- /dev/null +++ b/src/utils/allNotesFileVisibility.ts @@ -0,0 +1,51 @@ +import type { Settings, VaultEntry } from '../types' +import { filePreviewKind } from './filePreview' + +export interface AllNotesFileVisibility { + pdfs: boolean + images: boolean + unsupported: boolean +} + +export const DEFAULT_ALL_NOTES_FILE_VISIBILITY: AllNotesFileVisibility = { + pdfs: false, + images: false, + unsupported: false, +} + +type AllNotesFileVisibilitySettings = Pick< + Settings, + 'all_notes_show_pdfs' | 'all_notes_show_images' | 'all_notes_show_unsupported' +> + +export function resolveAllNotesFileVisibility( + settings: AllNotesFileVisibilitySettings | null | undefined, +): AllNotesFileVisibility { + return { + pdfs: settings?.all_notes_show_pdfs === true, + images: settings?.all_notes_show_images === true, + unsupported: settings?.all_notes_show_unsupported === true, + } +} + +export function settingsWithAllNotesFileVisibility( + settings: Settings, + visibility: AllNotesFileVisibility, +): Settings { + return { + ...settings, + all_notes_show_pdfs: visibility.pdfs, + all_notes_show_images: visibility.images, + all_notes_show_unsupported: visibility.unsupported, + } +} + +export function isOptionalAllNotesFileVisible( + entry: Pick, + visibility: AllNotesFileVisibility, +): boolean { + const previewKind = filePreviewKind(entry) + if (previewKind === 'pdf') return visibility.pdfs + if (previewKind === 'image') return visibility.images + return visibility.unsupported +} diff --git a/src/utils/noteListHelpers.extra.test.ts b/src/utils/noteListHelpers.extra.test.ts index e6a05302..9f1f67af 100644 --- a/src/utils/noteListHelpers.extra.test.ts +++ b/src/utils/noteListHelpers.extra.test.ts @@ -183,7 +183,7 @@ describe('noteListHelpers extra coverage', () => { }, }] - expect(filterEntries(entries, { kind: 'view', filename: 'work.view' }, undefined, views).map((entry) => entry.title)).toEqual(['Alpha']) + expect(filterEntries(entries, { kind: 'view', filename: 'work.view' }, { views }).map((entry) => entry.title)).toEqual(['Alpha']) expect(filterEntries(entries, { kind: 'folder', path: 'projects' }).map((entry) => entry.title)).toEqual(['Beta']) expect(filterEntries(entries, { kind: 'filter', filter: 'favorites' }).map((entry) => entry.title)).toEqual(['Alpha']) expect(filterEntries(entries, { kind: 'filter', filter: 'pulse' })).toEqual([]) diff --git a/src/utils/noteListHelpers.test.ts b/src/utils/noteListHelpers.test.ts index 099a528f..4118bd48 100644 --- a/src/utils/noteListHelpers.test.ts +++ b/src/utils/noteListHelpers.test.ts @@ -15,7 +15,7 @@ describe('filterEntries', () => { makeEntry({ path: '/4.md', title: 'Other', isA: 'Note' }), ] - const result = filterEntries(entries, { kind: 'sectionGroup', type: 'Project' }, 'open') + const result = filterEntries(entries, { kind: 'sectionGroup', type: 'Project' }, { subFilter: 'open' }) expect(result.map((entry) => entry.title)).toEqual(['Active']) }) @@ -26,7 +26,7 @@ describe('filterEntries', () => { makeEntry({ path: '/4.md', title: 'Other', isA: 'Note' }), ] - const result = filterEntries(entries, { kind: 'sectionGroup', type: 'Project' }, 'archived') + const result = filterEntries(entries, { kind: 'sectionGroup', type: 'Project' }, { subFilter: 'archived' }) expect(result.map((entry) => entry.title)).toEqual(['Archived']) }) @@ -48,7 +48,7 @@ describe('filterEntries', () => { makeEntry({ path: '/4.md', title: 'Other', isA: 'Note' }), ] - const result = filterEntries(entries, allSelection, 'open') + const result = filterEntries(entries, allSelection, { subFilter: 'open' }) expect(result.map((entry) => entry.title)).toEqual(['Active', 'Other']) }) @@ -59,7 +59,7 @@ describe('filterEntries', () => { makeEntry({ path: '/4.md', title: 'Other', isA: 'Note' }), ] - const result = filterEntries(entries, allSelection, 'archived') + const result = filterEntries(entries, allSelection, { subFilter: 'archived' }) expect(result.map((entry) => entry.title)).toEqual(['Archived']) }) @@ -71,10 +71,65 @@ describe('filterEntries', () => { makeEntry({ path: 'C:\\Users\\luca\\Vault\\attachments\\windows.md', title: 'Windows Attachment Markdown', isA: 'Note' }), ] - const result = filterEntries(entries, allSelection, 'open') + const result = filterEntries(entries, allSelection, { subFilter: 'open' }) expect(result.map((entry) => entry.title)).toEqual(['Real Note']) }) + it('hides PDFs, images, and unsupported files from All Notes by default', () => { + const entries = [ + makeEntry({ path: '/vault/note.md', filename: 'note.md', title: 'Note', fileKind: 'markdown' }), + makeEntry({ path: '/vault/Guide.PDF', filename: 'Guide.PDF', title: 'PDF', fileKind: 'binary' }), + makeEntry({ path: '/vault/Cover.JpG', filename: 'Cover.JpG', title: 'Image', fileKind: 'binary' }), + makeEntry({ path: '/vault/config.yml', filename: 'config.yml', title: 'Text', fileKind: 'text' }), + makeEntry({ path: '/vault/archive.zip', filename: 'archive.zip', title: 'Archive', fileKind: 'binary' }), + ] + + const result = filterEntries(entries, allSelection, { subFilter: 'open' }) + + expect(result.map((entry) => entry.title)).toEqual(['Note']) + }) + + it('shows selected non-Markdown categories in All Notes without swallowing PDFs or images into unsupported files', () => { + const entries = [ + makeEntry({ path: '/vault/note.md', filename: 'note.md', title: 'Note', fileKind: 'markdown' }), + makeEntry({ path: '/vault/Guide.PDF', filename: 'Guide.PDF', title: 'PDF', fileKind: 'binary' }), + makeEntry({ path: '/vault/Cover.JpG', filename: 'Cover.JpG', title: 'Image', fileKind: 'binary' }), + makeEntry({ path: '/vault/config.yml', filename: 'config.yml', title: 'Text', fileKind: 'text' }), + makeEntry({ path: '/vault/archive.zip', filename: 'archive.zip', title: 'Archive', fileKind: 'binary' }), + ] + + expect( + filterEntries(entries, allSelection, { + subFilter: 'open', + allNotesFileVisibility: { + pdfs: true, + images: false, + unsupported: false, + }, + }).map((entry) => entry.title), + ).toEqual(['Note', 'PDF']) + expect( + filterEntries(entries, allSelection, { + subFilter: 'open', + allNotesFileVisibility: { + pdfs: false, + images: true, + unsupported: false, + }, + }).map((entry) => entry.title), + ).toEqual(['Note', 'Image']) + expect( + filterEntries(entries, allSelection, { + subFilter: 'open', + allNotesFileVisibility: { + pdfs: false, + images: false, + unsupported: true, + }, + }).map((entry) => entry.title), + ).toEqual(['Note', 'Text', 'Archive']) + }) + it('matches slash-based folder selections against Windows entry paths', () => { const entries = [ makeEntry({ path: 'C:\\Users\\luca\\Vault\\Client Work\\Alpha.md', title: 'Alpha' }), @@ -99,6 +154,18 @@ describe('filterEntries', () => { expect(result.map((entry) => entry.title)).toEqual(['Root Note', 'config.json']) }) + + it('keeps folder browsing independent from All Notes file visibility', () => { + const entries = [ + makeEntry({ path: '/vault/assets/spec.PDF', filename: 'spec.PDF', title: 'Spec', fileKind: 'binary' }), + makeEntry({ path: '/vault/assets/logo.PNG', filename: 'logo.PNG', title: 'Logo', fileKind: 'binary' }), + makeEntry({ path: '/vault/assets/data.sqlite', filename: 'data.sqlite', title: 'Data', fileKind: 'binary' }), + ] + + const result = filterEntries(entries, { kind: 'folder', path: 'assets' }) + + expect(result.map((entry) => entry.title)).toEqual(['Spec', 'Logo', 'Data']) + }) }) describe('countByFilter', () => { @@ -152,6 +219,21 @@ describe('countAllNotesByFilter', () => { expect(countAllNotesByFilter(entries)).toEqual({ open: 1, archived: 1 }) }) + + it('counts enabled All Notes file categories by archive status', () => { + const entries = [ + makeEntry({ path: '/vault/note.md', filename: 'note.md', fileKind: 'markdown' }), + makeEntry({ path: '/vault/spec.pdf', filename: 'spec.pdf', fileKind: 'binary' }), + makeEntry({ path: '/vault/photo.PNG', filename: 'photo.PNG', fileKind: 'binary', archived: true }), + makeEntry({ path: '/vault/data.bin', filename: 'data.bin', fileKind: 'binary', archived: true }), + ] + + expect(countAllNotesByFilter(entries, { + pdfs: true, + images: true, + unsupported: false, + })).toEqual({ open: 2, archived: 1 }) + }) }) describe('buildRelationshipGroups', () => { diff --git a/src/utils/noteListHelpers.ts b/src/utils/noteListHelpers.ts index b706bcff..7e0d18a4 100644 --- a/src/utils/noteListHelpers.ts +++ b/src/utils/noteListHelpers.ts @@ -4,11 +4,22 @@ import { orderInverseRelationshipLabels as sortInverseRelationshipLabels, resolveInverseRelationshipLabel, } from './inverseRelationshipLabels' +import { + DEFAULT_ALL_NOTES_FILE_VISIBILITY, + isOptionalAllNotesFileVisible, + type AllNotesFileVisibility, +} from './allNotesFileVisibility' import { evaluateView } from './viewFilters' import { wikilinkTarget, resolveEntry } from './wikilink' export type NoteListFilter = 'open' | 'archived' +export interface FilterEntriesOptions { + subFilter?: NoteListFilter + views?: ViewFile[] + allNotesFileVisibility?: AllNotesFileVisibility +} + export interface RelationshipGroup { label: string entries: VaultEntry[] @@ -407,8 +418,12 @@ function normalizeFolderPath(path: string): string { return path.replace(/\\/g, '/').replace(/^\/+|\/+$/g, '') } -export function isAllNotesEntry(entry: VaultEntry): boolean { - return isMarkdown(entry) && !isInFolder(entry.path, ATTACHMENTS_FOLDER) +export function isAllNotesEntry( + entry: VaultEntry, + allNotesFileVisibility: AllNotesFileVisibility = DEFAULT_ALL_NOTES_FILE_VISIBILITY, +): boolean { + if (isMarkdown(entry)) return !isInFolder(entry.path, ATTACHMENTS_FOLDER) + return isOptionalAllNotesFileVisible(entry, allNotesFileVisibility) } function filterViewEntries(entries: VaultEntry[], filename: string, views?: ViewFile[]): VaultEntry[] { @@ -446,21 +461,25 @@ function filterSectionGroupEntries(entries: VaultEntry[], type: string, subFilte function filterTopLevelEntries( entries: VaultEntry[], selection: Extract, - subFilter?: NoteListFilter, + options: FilterEntriesOptions, ): VaultEntry[] { const filterableEntries = selection.filter === 'all' - ? entries.filter(isAllNotesEntry) + ? entries.filter((entry) => isAllNotesEntry(entry, options.allNotesFileVisibility)) : entries.filter(isMarkdown) - if (selection.filter === 'all' && subFilter) return applySubFilter(filterableEntries, subFilter) + if (selection.filter === 'all' && options.subFilter) return applySubFilter(filterableEntries, options.subFilter) return filterByFilterType(filterableEntries, selection.filter) } -function filterByKind(entries: VaultEntry[], selection: SidebarSelection, subFilter?: NoteListFilter, views?: ViewFile[]): VaultEntry[] { +function filterByKind( + entries: VaultEntry[], + selection: SidebarSelection, + options: FilterEntriesOptions, +): VaultEntry[] { if (selection.kind === 'entity') return [] - if (selection.kind === 'view') return filterViewEntries(entries, selection.filename, views) - if (selection.kind === 'folder') return filterFolderEntries(entries, selection, subFilter) - if (selection.kind === 'sectionGroup') return filterSectionGroupEntries(entries, selection.type, subFilter) - if (selection.kind === 'filter') return filterTopLevelEntries(entries, selection, subFilter) + if (selection.kind === 'view') return filterViewEntries(entries, selection.filename, options.views) + if (selection.kind === 'folder') return filterFolderEntries(entries, selection, options.subFilter) + if (selection.kind === 'sectionGroup') return filterSectionGroupEntries(entries, selection.type, options.subFilter) + if (selection.kind === 'filter') return filterTopLevelEntries(entries, selection, options) return [] } @@ -472,8 +491,12 @@ function filterByFilterType(entries: VaultEntry[], filter: string): VaultEntry[] return [] } -export function filterEntries(entries: VaultEntry[], selection: SidebarSelection, subFilter?: NoteListFilter, views?: ViewFile[]): VaultEntry[] { - return filterByKind(entries, selection, subFilter, views) +export function filterEntries( + entries: VaultEntry[], + selection: SidebarSelection, + options: FilterEntriesOptions = {}, +): VaultEntry[] { + return filterByKind(entries, selection, options) } /** Count notes per sub-filter for a given type. */ @@ -501,9 +524,14 @@ export function countAllByFilter(entries: VaultEntry[]): Record { - return countEntriesByArchiveStatus(entries.filter(isAllNotesEntry)) +/** Count All Notes-eligible documents per sub-filter using the current file visibility policy. */ +export function countAllNotesByFilter( + entries: VaultEntry[], + allNotesFileVisibility?: AllNotesFileVisibility, +): Record { + return countEntriesByArchiveStatus( + entries.filter((entry) => isAllNotesEntry(entry, allNotesFileVisibility)), + ) } // --- Inbox ---