feat: configure all notes file visibility
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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 |
|
||||
|
||||
|
||||
12
lara.lock
12
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
|
||||
|
||||
@@ -26,6 +26,9 @@ pub struct Settings {
|
||||
pub initial_h1_auto_rename_enabled: Option<bool>,
|
||||
pub default_ai_agent: Option<String>,
|
||||
pub hide_gitignored_files: Option<bool>,
|
||||
pub all_notes_show_pdfs: Option<bool>,
|
||||
pub all_notes_show_images: Option<bool>,
|
||||
pub all_notes_show_unsupported: Option<bool>,
|
||||
}
|
||||
|
||||
fn normalize_optional_string(value: Option<String>) -> Option<String> {
|
||||
@@ -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]
|
||||
|
||||
18
src/App.tsx
18
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<NoteListItem[]>(() => {
|
||||
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 && (
|
||||
<>
|
||||
<div className="app__sidebar" style={{ width: layout.sidebarWidth }}>
|
||||
<Sidebar entries={vault.entries} folders={vault.folders} views={vault.views} selection={effectiveSelection} onSelect={handleSetSelection} onSelectNote={notes.handleSelectNote} onSelectFavorite={handleOpenFavorite} onReorderFavorites={entryActions.handleReorderFavorites} onCreateType={notes.handleCreateNoteImmediate} onCreateNewType={dialogs.openCreateType} onCustomizeType={entryActions.handleCustomizeType} onUpdateTypeTemplate={entryActions.handleUpdateTypeTemplate} onReorderSections={entryActions.handleReorderSections} onRenameSection={entryActions.handleRenameSection} onToggleTypeVisibility={entryActions.handleToggleTypeVisibility} onCreateFolder={handleCreateFolder} onRenameFolder={folderActions.renameFolder} onDeleteFolder={folderActions.requestDeleteFolder} folderFileActions={fileActions.folderActions} renamingFolderPath={folderActions.renamingFolderPath} onStartRenameFolder={folderActions.startFolderRename} onCancelRenameFolder={folderActions.cancelFolderRename} onCreateView={dialogs.openCreateView} onEditView={handleEditView} onDeleteView={handleDeleteView} onReorderViews={viewOrdering.onReorderViews} showInbox={explicitOrganizationEnabled} inboxCount={inboxCount} locale={appLocale} loading={isVaultContentLoading} vaultRootPath={resolvedPath} />
|
||||
<Sidebar entries={vault.entries} folders={vault.folders} views={vault.views} selection={effectiveSelection} onSelect={handleSetSelection} onSelectNote={notes.handleSelectNote} onSelectFavorite={handleOpenFavorite} onReorderFavorites={entryActions.handleReorderFavorites} onCreateType={notes.handleCreateNoteImmediate} onCreateNewType={dialogs.openCreateType} onCustomizeType={entryActions.handleCustomizeType} onUpdateTypeTemplate={entryActions.handleUpdateTypeTemplate} onReorderSections={entryActions.handleReorderSections} onRenameSection={entryActions.handleRenameSection} onToggleTypeVisibility={entryActions.handleToggleTypeVisibility} onCreateFolder={handleCreateFolder} onRenameFolder={folderActions.renameFolder} onDeleteFolder={folderActions.requestDeleteFolder} folderFileActions={fileActions.folderActions} renamingFolderPath={folderActions.renamingFolderPath} onStartRenameFolder={folderActions.startFolderRename} onCancelRenameFolder={folderActions.cancelFolderRename} onCreateView={dialogs.openCreateView} onEditView={handleEditView} onDeleteView={handleDeleteView} onReorderViews={viewOrdering.onReorderViews} showInbox={explicitOrganizationEnabled} inboxCount={inboxCount} allNotesFileVisibility={allNotesFileVisibility} locale={appLocale} loading={isVaultContentLoading} vaultRootPath={resolvedPath} />
|
||||
</div>
|
||||
<ResizeHandle onResize={layout.handleSidebarResize} />
|
||||
</>
|
||||
@@ -1633,7 +1643,7 @@ function App() {
|
||||
{effectiveSelection.kind === 'filter' && effectiveSelection.filter === 'pulse' ? (
|
||||
<PulseView vaultPath={resolvedPath} onOpenNote={handlePulseOpenNote} sidebarCollapsed={!sidebarVisible} onExpandSidebar={() => handleSetViewMode('all')} locale={appLocale} />
|
||||
) : (
|
||||
<NoteList entries={vault.entries} selection={effectiveSelection} selectedNote={activeTab?.entry ?? null} loading={isVaultContentLoading} noteListFilter={noteListFilter} onNoteListFilterChange={setNoteListFilter} inboxPeriod={inboxPeriod} modifiedFiles={vault.modifiedFiles} modifiedFilesError={vault.modifiedFilesError} getNoteStatus={vault.getNoteStatus} sidebarCollapsed={!sidebarVisible} onSelectNote={notes.handleSelectNote} onReplaceActiveTab={handleReplaceActiveTabWithQueuedDiff} onEnterNeighborhood={handleEnterNeighborhood} onCreateNote={notes.handleCreateNoteImmediate} onBulkOrganize={explicitOrganizationEnabled ? bulkActions.handleBulkOrganize : undefined} onBulkArchive={bulkActions.handleBulkArchive} onBulkDeletePermanently={deleteActions.handleBulkDeletePermanently} onUpdateTypeSort={notes.handleUpdateFrontmatter} onUpdateViewDefinition={handleUpdateViewDefinition} updateEntry={vault.updateEntry} onOpenInNewWindow={handleOpenEntryInNewWindow} onDiscardFile={handleDiscardFile} onOpenDeletedNote={handleOpenDeletedNote} allNotesNoteListProperties={vaultConfig.allNotes?.noteListProperties ?? null} onUpdateAllNotesNoteListProperties={handleUpdateAllNotesNoteListProperties} inboxNoteListProperties={vaultConfig.inbox?.noteListProperties ?? null} onUpdateInboxNoteListProperties={handleUpdateInboxNoteListProperties} views={vault.views} visibleNotesRef={visibleNotesRef} multiSelectionCommandRef={multiSelectionCommandRef} locale={appLocale} />
|
||||
<NoteList entries={vault.entries} selection={effectiveSelection} selectedNote={activeTab?.entry ?? null} loading={isVaultContentLoading} noteListFilter={noteListFilter} onNoteListFilterChange={setNoteListFilter} inboxPeriod={inboxPeriod} modifiedFiles={vault.modifiedFiles} modifiedFilesError={vault.modifiedFilesError} getNoteStatus={vault.getNoteStatus} sidebarCollapsed={!sidebarVisible} onSelectNote={notes.handleSelectNote} onReplaceActiveTab={handleReplaceActiveTabWithQueuedDiff} onEnterNeighborhood={handleEnterNeighborhood} onCreateNote={notes.handleCreateNoteImmediate} onBulkOrganize={explicitOrganizationEnabled ? bulkActions.handleBulkOrganize : undefined} onBulkArchive={bulkActions.handleBulkArchive} onBulkDeletePermanently={deleteActions.handleBulkDeletePermanently} onUpdateTypeSort={notes.handleUpdateFrontmatter} onUpdateViewDefinition={handleUpdateViewDefinition} updateEntry={vault.updateEntry} onOpenInNewWindow={handleOpenEntryInNewWindow} onDiscardFile={handleDiscardFile} onOpenDeletedNote={handleOpenDeletedNote} allNotesNoteListProperties={vaultConfig.allNotes?.noteListProperties ?? null} onUpdateAllNotesNoteListProperties={handleUpdateAllNotesNoteListProperties} inboxNoteListProperties={vaultConfig.inbox?.noteListProperties ?? null} onUpdateInboxNoteListProperties={handleUpdateInboxNoteListProperties} views={vault.views} visibleNotesRef={visibleNotesRef} allNotesFileVisibility={allNotesFileVisibility} multiSelectionCommandRef={multiSelectionCommandRef} locale={appLocale} />
|
||||
)}
|
||||
</div>
|
||||
<ResizeHandle onResize={layout.handleNoteListResize} />
|
||||
|
||||
@@ -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(
|
||||
<SettingsPanel open={true} settings={emptySettings} onSave={onSave} onClose={onClose} />
|
||||
)
|
||||
|
||||
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(
|
||||
<SettingsPanel
|
||||
open={true}
|
||||
settings={{
|
||||
...emptySettings,
|
||||
all_notes_show_pdfs: true,
|
||||
all_notes_show_images: true,
|
||||
all_notes_show_unsupported: false,
|
||||
}}
|
||||
onSave={onSave}
|
||||
onClose={onClose}
|
||||
/>
|
||||
)
|
||||
|
||||
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(
|
||||
<SettingsPanel open={true} settings={emptySettings} onSave={onSave} onClose={onClose} />
|
||||
)
|
||||
|
||||
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(
|
||||
<SettingsPanel open={true} settings={emptySettings} onSave={onSave} onClose={onClose} />
|
||||
|
||||
@@ -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<HTMLDivElement | null>): void {
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
const focusTarget = panelRef.current?.querySelector<HTMLElement>('[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<HTMLElement>('[data-settings-autofocus="true"]')
|
||||
focusTarget?.focus()
|
||||
}, 50)
|
||||
return () => clearTimeout(timer)
|
||||
}, [])
|
||||
useSettingsPanelAutofocus(panelRef)
|
||||
|
||||
const updateDraft = useCallback(
|
||||
<Key extends keyof SettingsDraft>(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 (
|
||||
<div style={{ padding: 24, display: 'flex', flexDirection: 'column', gap: 0, overflow: 'auto' }}>
|
||||
<SettingsSyncAndAppearanceSections {...props} />
|
||||
<SettingsContentSections {...props} />
|
||||
<SettingsAgentWorkflowSections {...props} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
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 (
|
||||
<div style={{ padding: 24, display: 'flex', flexDirection: 'column', gap: 0, overflow: 'auto' }}>
|
||||
<>
|
||||
<SettingsSection showDivider={false}>
|
||||
<SyncAndUpdatesSection
|
||||
t={t}
|
||||
@@ -448,7 +464,6 @@ function SettingsBody({
|
||||
setReleaseChannel={setReleaseChannel}
|
||||
/>
|
||||
</SettingsSection>
|
||||
|
||||
<SettingsSection>
|
||||
<AutoGitSettingsSection
|
||||
t={t}
|
||||
@@ -479,7 +494,21 @@ function SettingsBody({
|
||||
setUiLanguage={setUiLanguage}
|
||||
/>
|
||||
</SettingsSection>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function SettingsContentSections({
|
||||
t,
|
||||
initialH1AutoRename,
|
||||
setInitialH1AutoRename,
|
||||
hideGitignoredFiles,
|
||||
setHideGitignoredFiles,
|
||||
allNotesFileVisibility,
|
||||
setAllNotesFileVisibility,
|
||||
}: SettingsBodyProps) {
|
||||
return (
|
||||
<>
|
||||
<SettingsSection>
|
||||
<TitleSettingsSection
|
||||
t={t}
|
||||
@@ -493,9 +522,31 @@ function SettingsBody({
|
||||
t={t}
|
||||
hideGitignoredFiles={hideGitignoredFiles}
|
||||
setHideGitignoredFiles={setHideGitignoredFiles}
|
||||
allNotesFileVisibility={allNotesFileVisibility}
|
||||
setAllNotesFileVisibility={setAllNotesFileVisibility}
|
||||
/>
|
||||
</SettingsSection>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function SettingsAgentWorkflowSections({
|
||||
t,
|
||||
autoAdvanceInboxAfterOrganize,
|
||||
setAutoAdvanceInboxAfterOrganize,
|
||||
aiAgentsStatus,
|
||||
defaultAiAgent,
|
||||
setDefaultAiAgent,
|
||||
onCopyMcpConfig,
|
||||
explicitOrganization,
|
||||
setExplicitOrganization,
|
||||
crashReporting,
|
||||
setCrashReporting,
|
||||
analytics,
|
||||
setAnalytics,
|
||||
}: SettingsBodyProps) {
|
||||
return (
|
||||
<>
|
||||
<SettingsSection>
|
||||
<AiAgentSettingsSection
|
||||
t={t}
|
||||
@@ -525,7 +576,7 @@ function SettingsBody({
|
||||
setAnalytics={setAnalytics}
|
||||
/>
|
||||
</SettingsSection>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -779,7 +830,16 @@ function VaultContentSettingsSection({
|
||||
t,
|
||||
hideGitignoredFiles,
|
||||
setHideGitignoredFiles,
|
||||
}: Pick<SettingsBodyProps, 't' | 'hideGitignoredFiles' | 'setHideGitignoredFiles'>) {
|
||||
allNotesFileVisibility,
|
||||
setAllNotesFileVisibility,
|
||||
}: Pick<
|
||||
SettingsBodyProps,
|
||||
't' | 'hideGitignoredFiles' | 'setHideGitignoredFiles' | 'allNotesFileVisibility' | 'setAllNotesFileVisibility'
|
||||
>) {
|
||||
const updateAllNotesFileVisibility = (patch: Partial<AllNotesFileVisibility>) => {
|
||||
setAllNotesFileVisibility({ ...allNotesFileVisibility, ...patch })
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<SectionHeading
|
||||
@@ -794,6 +854,35 @@ function VaultContentSettingsSection({
|
||||
onChange={setHideGitignoredFiles}
|
||||
testId="settings-hide-gitignored-files"
|
||||
/>
|
||||
|
||||
<div className="space-y-3 pt-1">
|
||||
<SectionHeading
|
||||
title={t('settings.allNotesVisibility.title')}
|
||||
description={t('settings.allNotesVisibility.description')}
|
||||
/>
|
||||
|
||||
<SettingsCheckboxRow
|
||||
label={t('settings.allNotesVisibility.pdfs')}
|
||||
description={t('settings.allNotesVisibility.pdfsDescription')}
|
||||
checked={allNotesFileVisibility.pdfs}
|
||||
onChange={(checked) => updateAllNotesFileVisibility({ pdfs: checked })}
|
||||
testId="settings-all-notes-show-pdfs"
|
||||
/>
|
||||
<SettingsCheckboxRow
|
||||
label={t('settings.allNotesVisibility.images')}
|
||||
description={t('settings.allNotesVisibility.imagesDescription')}
|
||||
checked={allNotesFileVisibility.images}
|
||||
onChange={(checked) => updateAllNotesFileVisibility({ images: checked })}
|
||||
testId="settings-all-notes-show-images"
|
||||
/>
|
||||
<SettingsCheckboxRow
|
||||
label={t('settings.allNotesVisibility.unsupported')}
|
||||
description={t('settings.allNotesVisibility.unsupportedDescription')}
|
||||
checked={allNotesFileVisibility.unsupported}
|
||||
onChange={(checked) => updateAllNotesFileVisibility({ unsupported: checked })}
|
||||
testId="settings-all-notes-show-unsupported"
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -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 (
|
||||
<label className="flex items-start gap-3" style={{ cursor: 'pointer' }} data-testid={testId}>
|
||||
<Checkbox
|
||||
checked={checked}
|
||||
onCheckedChange={(value) => onChange(isChecked(value))}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key !== ' ' && event.key !== 'Spacebar') return
|
||||
event.preventDefault()
|
||||
onChange(!checked)
|
||||
}}
|
||||
aria-label={label}
|
||||
className="mt-0.5"
|
||||
/>
|
||||
<span className="space-y-1">
|
||||
<span className="block" style={{ fontSize: 13, fontWeight: 500, color: 'var(--foreground)' }}>{label}</span>
|
||||
<span className="block" style={{ fontSize: 11, color: 'var(--muted-foreground)' }}>{description}</span>
|
||||
</span>
|
||||
</label>
|
||||
)
|
||||
}
|
||||
|
||||
function TelemetryToggle({
|
||||
label,
|
||||
description,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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],
|
||||
)
|
||||
|
||||
|
||||
@@ -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<VaultEntry>) => void
|
||||
views?: ViewFile[]
|
||||
visibleNotesRef?: React.MutableRefObject<VaultEntry[]>
|
||||
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<ViewDefinition>) => void
|
||||
views?: ViewFile[]
|
||||
visibleNotesRef?: React.MutableRefObject<VaultEntry[]>
|
||||
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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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": "ベトナム語"
|
||||
|
||||
@@ -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": "베트남어"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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": "Вьетнамский"
|
||||
|
||||
@@ -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": "越南语"
|
||||
|
||||
@@ -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": "越南文"
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
51
src/utils/allNotesFileVisibility.ts
Normal file
51
src/utils/allNotesFileVisibility.ts
Normal file
@@ -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<VaultEntry, 'fileKind' | 'filename' | 'path'>,
|
||||
visibility: AllNotesFileVisibility,
|
||||
): boolean {
|
||||
const previewKind = filePreviewKind(entry)
|
||||
if (previewKind === 'pdf') return visibility.pdfs
|
||||
if (previewKind === 'image') return visibility.images
|
||||
return visibility.unsupported
|
||||
}
|
||||
@@ -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([])
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -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<SidebarSelection, { kind: 'filter' }>,
|
||||
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<NoteListFilter,
|
||||
return countEntriesByArchiveStatus(entries.filter(isMarkdown))
|
||||
}
|
||||
|
||||
/** Count All Notes-eligible documents per sub-filter, excluding files under attachments/. */
|
||||
export function countAllNotesByFilter(entries: VaultEntry[]): Record<NoteListFilter, number> {
|
||||
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<NoteListFilter, number> {
|
||||
return countEntriesByArchiveStatus(
|
||||
entries.filter((entry) => isAllNotesEntry(entry, allNotesFileVisibility)),
|
||||
)
|
||||
}
|
||||
|
||||
// --- Inbox ---
|
||||
|
||||
Reference in New Issue
Block a user