From 79d3a924f0a4d6bd1d4147d788037aa82f5e154d Mon Sep 17 00:00:00 2001 From: lucaronin Date: Tue, 12 May 2026 06:57:42 +0200 Subject: [PATCH] refactor: consolidate date display preference flow --- docs/ABSTRACTIONS.md | 2 +- docs/ARCHITECTURE.md | 2 +- src/App.tsx | 13 ++-- src/components/AddPropertyForm.tsx | 15 ++--- src/components/DynamicPropertiesPanel.tsx | 25 +------- src/components/Editor.tsx | 5 -- src/components/EditorRightPanel.tsx | 5 -- src/components/Inspector.tsx | 12 +--- src/components/NoteItem.tsx | 24 ++----- src/components/NoteList.rendering.test.tsx | 9 ++- src/components/PropertyValueCells.test.tsx | 26 ++++---- src/components/PropertyValueCells.tsx | 8 +-- src/components/SearchPanel.tsx | 22 +++++-- src/components/TableOfContentsPanel.tsx | 5 +- .../dateDisplayPreferenceFlow.test.tsx | 64 +++++++++++++++++++ src/components/inspector/NoteInfoPanel.tsx | 5 +- src/components/note-item/PropertyChips.tsx | 5 +- src/components/note-list/useNoteListModel.tsx | 14 +--- src/hooks/useAppPreferences.ts | 29 ++++++++- 19 files changed, 162 insertions(+), 128 deletions(-) create mode 100644 src/components/dateDisplayPreferenceFlow.test.tsx diff --git a/docs/ABSTRACTIONS.md b/docs/ABSTRACTIONS.md index c05cff34..2df689a4 100644 --- a/docs/ABSTRACTIONS.md +++ b/docs/ABSTRACTIONS.md @@ -852,7 +852,7 @@ interface Settings { } ``` -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/System actions both update that same value. `system` remains a stored preference, while the runtime resolves it to `light` or `dark` for `data-theme` and app consumers. `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. `date_display_format` is installation-local and controls rendered dates in note rows, property chips/cells, note info, table-of-contents metadata, and search result subtitles; date picker text input remains ISO for predictable manual entry and storage. `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. `sidebar_type_pluralization_enabled` is installation-local and defaults to `true`; when false, type rows use exact type names unless the type document defines an explicit `sidebar_label` override. `default_ai_agent` remains the legacy installation-local CLI fallback. `default_ai_target` is the active AI target used by the AI panel and status bar; it can point at a coding agent or a configured direct model. `ai_model_providers` stores non-secret provider metadata for local/API model targets, while hosted API keys live in Tolaria's local app-data secrets file or user-managed environment variables instead of being persisted in app settings. Provider defaults and local/API grouping come from the shared `src/shared/aiModelProviderCatalog.json` catalog used by both renderer settings and the Tauri direct-model runtime. `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. +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/System actions both update that same value. `system` remains a stored preference, while the runtime resolves it to `light` or `dark` for `data-theme` and app consumers. `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. `date_display_format` is installation-local and controls rendered dates in note rows, property chips/cells, note info, table-of-contents metadata, and search result subtitles; `AppPreferencesProvider` owns the UI-level value so rendering surfaces can consume it without prop forwarding, while date picker text input remains ISO for predictable manual entry and storage. `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. `sidebar_type_pluralization_enabled` is installation-local and defaults to `true`; when false, type rows use exact type names unless the type document defines an explicit `sidebar_label` override. `default_ai_agent` remains the legacy installation-local CLI fallback. `default_ai_target` is the active AI target used by the AI panel and status bar; it can point at a coding agent or a configured direct model. `ai_model_providers` stores non-secret provider metadata for local/API model targets, while hosted API keys live in Tolaria's local app-data secrets file or user-managed environment variables instead of being persisted in app settings. Provider defaults and local/API grouping come from the shared `src/shared/aiModelProviderCatalog.json` catalog used by both renderer settings and the Tauri direct-model runtime. `hide_gitignored_files` is also installation-local and defaults to `true`; changing it reloads entries, search, saved views, and folders without restarting. The `all_notes_show_pdfs`, `all_notes_show_images`, and `all_notes_show_unsupported` flags are installation-local All Notes category toggles that default off and update the list/counts without changing vault files. The AutoGit fields are also installation-local: `useAutoGit` consumes them to schedule automatic checkpoints, while `useCommitFlow` and the status bar quick action reuse the same checkpoint runner and deterministic automatic commit message generation. ## Telemetry diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 51165de8..5b506263 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -478,7 +478,7 @@ Tolaria's app chrome uses an app-owned localization runtime in `src/lib/i18n.ts` `App.tsx` derives the effective locale from settings and browser/system language hints, then passes it down to localized surfaces. Settings exposes a keyboard-accessible shadcn `Select`, and the command palette includes actions to open language settings or switch directly to a supported language. -`App.tsx` also resolves the installation-local date display format from `settings.date_display_format`. Note rows, note-list property chips, inspector property cells, note info, table-of-contents metadata, and search result subtitles render dates through the same `src/utils/dateDisplay.ts` formatter so the visible style stays consistent. Date picker text entry remains ISO (`YYYY-MM-DD`) to preserve predictable manual input and frontmatter storage. +`App.tsx` also resolves the installation-local date display format from `settings.date_display_format` and publishes it through `AppPreferencesProvider` in `src/hooks/useAppPreferences.ts`. Note rows, note-list property chips, inspector property cells, note info, table-of-contents metadata, and search result subtitles read that shared preference and render dates through `src/utils/dateDisplay.ts` so the visible style stays consistent. Date picker text entry remains ISO (`YYYY-MM-DD`) to preserve predictable manual input and frontmatter storage. ## Vault Management diff --git a/src/App.tsx b/src/App.tsx index a23e94a1..a176493a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -119,7 +119,7 @@ import { import { activeGitRepositories } from './utils/gitRepositories' import { useVisibleWorkspaceEntries, useWorkspaceGraphState } from './hooks/useWorkspaceGraphState' import { useGitSetupState } from './hooks/useGitSetupState' -import { useAppPreferences } from './hooks/useAppPreferences' +import { AppPreferencesProvider, useAppPreferences } from './hooks/useAppPreferences' import { useInboxOrganizeAdvance } from './hooks/useInboxOrganizeAdvance' import { syncVaultAssetScope, useNoteWindowLifecycle } from './hooks/useNoteWindowLifecycle' import { useVaultRenameDetection } from './hooks/useVaultRenameDetection' @@ -1589,7 +1589,8 @@ function App() { const noteListModifiedFilesError = isChangesSelection ? gitSurfaces.changesModifiedFilesError : null return ( -
+ +
{sidebarVisible && ( <> @@ -1605,7 +1606,7 @@ function App() { {effectiveSelection.kind === 'filter' && effectiveSelection.filter === 'pulse' ? ( handleSetViewMode('all')} repositories={gitRepositories} selectedRepositoryPath={gitSurfaces.historyRepositoryPath} onRepositoryChange={gitSurfaces.setHistoryRepositoryPath} locale={appLocale} /> ) : ( - + )}
@@ -1682,7 +1683,6 @@ function App() { flushPendingEditorContentRef={flushPendingEditorContentRef} flushPendingRawContentRef={flushPendingRawContentRef} locale={appLocale} - dateDisplayFormat={dateDisplayFormat} />
@@ -1702,7 +1702,7 @@ function App() { locale={appLocale} onClose={dialogs.closeCommandPalette} /> - + )} - + + ) } diff --git a/src/components/AddPropertyForm.tsx b/src/components/AddPropertyForm.tsx index 0eb8a6f2..677e4d7d 100644 --- a/src/components/AddPropertyForm.tsx +++ b/src/components/AddPropertyForm.tsx @@ -10,10 +10,10 @@ import { formatDateValue, toISODate, } from '../utils/propertyTypes' -import { DEFAULT_DATE_DISPLAY_FORMAT, type DateDisplayFormat } from '../utils/dateDisplay' import { StatusPill, StatusDropdown } from './StatusDropdown' import { DISPLAY_MODE_OPTIONS, DISPLAY_MODE_ICONS } from '../utils/propertyTypes' import { translate, type AppLocale } from '../lib/i18n' +import { useDateDisplayFormat } from '../hooks/useAppPreferences' function parseDateValue(value: string): Date | undefined { const iso = toISODate(value) @@ -57,14 +57,13 @@ function AddBooleanInput({ value, locale, onChange }: { value: string; locale: A function AddDateInput({ value, locale, - dateDisplayFormat, onChange, }: { value: string locale: AppLocale - dateDisplayFormat: DateDisplayFormat onChange: (v: string) => void }) { + const dateDisplayFormat = useDateDisplayFormat() const selectedDate = value ? parseDateValue(value) : undefined const formatted = value ? formatDateValue(value, dateDisplayFormat) : '' return ( @@ -134,17 +133,16 @@ function AddNumberInput({ value, onChange, onKeyDown }: { ) } -function AddPropertyValueInput({ displayMode, value, onChange, onKeyDown, vaultStatuses, locale, dateDisplayFormat }: { +function AddPropertyValueInput({ displayMode, value, onChange, onKeyDown, vaultStatuses, locale }: { displayMode: PropertyDisplayMode; value: string; onChange: (v: string) => void onKeyDown: (e: React.KeyboardEvent) => void; vaultStatuses: string[] locale: AppLocale - dateDisplayFormat: DateDisplayFormat }) { switch (displayMode) { case 'number': return case 'boolean': return - case 'date': return + case 'date': return case 'status': return case 'tags': return ( void; onCancel: () => void vaultStatuses: string[] locale?: AppLocale - dateDisplayFormat?: DateDisplayFormat }) { const [newKey, setNewKey] = useState('') const [newValue, setNewValue] = useState('') @@ -209,7 +206,7 @@ export function AddPropertyForm({ onAdd, onCancel, vaultStatuses, locale = 'en', })} - +