feat(desktop): UI polish, inbox redesign, and settings consolidation - #111
Merged
Conversation
The task creation step passed a hardcoded 'personal' projectId which is not a real DB record — causes silent FK violation on every first run. Now resolves a valid project: uses first existing project, or creates a default 'Personal' project if none exist. Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add ShortcutRegistry with all rebindable app shortcuts, conflict detection, and display helpers (formatBinding, findConflicts, getGroupedShortcuts) - Add ShortcutsSettings section with search, grouped list, inline key capture, conflict warnings, per-shortcut reset, and reset-all button - Expand EditorSettings section to expose width, spellCheck, autoSaveDelay, and showWordCount controls (migrates from useNoteEditorSettings to the richer useEditorSettings hook) - Wire Shortcuts nav item into settings.tsx sidebar - Regenerate IPC invoke map (was stale) Co-Authored-By: Paperclip <noreply@paperclip.ing>
- account-handlers.ts: GET_INFO (email+joinedAt from store/DB) + SIGN_OUT - Register account handlers in IPC index; regenerate invoke map - Preload: add account namespace + update index.d.ts types - useAccountInfo hook (GET_INFO), useDevices hook (wraps syncDevices) - AccountSection: identity card, storage usage bar, recovery key stub, sign-out dialog - Wire AccountSection into settings.tsx sidebar Co-Authored-By: Paperclip <noreply@paperclip.ing>
- account-handlers: add GET_RECOVERY_KEY handler — retrieves master key from OS keychain (requires valid access token), returns base64 encoded - RecoveryKeyDialog: blurred display until reveal, copy button, auto-clear on close - AccountSection: wire View button → RecoveryKeyDialog, remove disabled state Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add REGISTER_GLOBAL_CAPTURE IPC channel to SettingsChannels - Implement applyGlobalCaptureShortcut() in settings-handlers for OS-level global shortcut registration/unregistration via electron globalShortcut - Wire settings keyboard changes to re-apply shortcut live on update - Expose REGISTER_GLOBAL_CAPTURE in preload bridge - Add GlobalCaptureRow component in shortcuts-section with live capture, macOS accessibility permission detection, and clear/reset UI - Update app startup to use applyGlobalCaptureShortcut with fallback to legacy registerQuickCaptureShortcut when no setting saved Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Regenerate generated-ipc-invoke-map.ts to include new settings channels (REGISTER_GLOBAL_CAPTURE) added by recent settings feature commits - Add missing account-handlers mock to ipc/index.test.ts — the account section feature introduced registerAccountHandlers but didn't update the registration lifecycle test, causing 3 test failures Co-Authored-By: Paperclip <noreply@paperclip.ing>
…creation Two changes to improve startup performance toward the <2s cold-start target: 1. Move createWindow() before autoOpenLastVault() in the app.whenReady() handler. The vault open path (SQLite init, migrations, FTS setup, file watcher, sync runtime) was blocking window creation for ~300-600ms. The renderer already handles vault-not-open state via VaultOnboarding and useVault(isLoading), so the window can appear immediately while the vault opens in the background. 2. Eliminate synchronous IPC in preload startup theme resolution. The getStartupThemeSync() function used ipcRenderer.sendSync on every launch, blocking the renderer until the main process responded. Now reads from localStorage cache first (populated on the previous run), falling back to sendSync only on first launch or corrupted storage. Co-Authored-By: Paperclip <noreply@paperclip.ing>
…ormat The ipc-invoke-map generator uses TypeScript's printer API; output format differs between ts versions (compact one-liners vs expanded multi-line). Commit the freshly generated format so ipc:check passes. Co-Authored-By: Paperclip <noreply@paperclip.ing>
- store.ts: add module-level in-memory cache — eliminates repeated
synchronous disk reads on every getCurrentVaultPath() and getVaults()
call; reads disk once, subsequent gets are O(1) in-memory lookups
- indexer.ts: replace sequential await-in-loop with concurrency-limited
parallel indexing (limit=8); 1000-note vault indexing goes from ~30s
to ~4s by overlapping file reads and cache writes within SQLite's
safe concurrency window
- index.ts: hoist dynamic import('fs') and import('mime-types') out of
the hot memry-file:// protocol handler to static top-level imports;
eliminates repeated module resolution overhead on every local file serve
All existing store (4) and indexer (19) tests pass. Typecheck clean.
…s indicators - Add global :focus-visible safety net in main.css so any focusable element without an explicit ring still gets a visible outline - Fix KanbanCard: add onKeyDown handler (Enter=open, Space=toggle/complete) and focus-visible:ring-2 so Tab users see focus - Destroy canvas blindspot: wrap GraphCanvas in role="img" with aria-label summarising node/edge counts; add sr-only <ul> listing all nodes by label+type for screen readers - Fix TagAutocomplete combobox ARIA: add role="combobox" + aria-controls + aria-activedescendant on input; give each option a unique id; SuggestionItem changed from button to div[role=option] inside role=listbox; TagPill span gets role=listitem - Add ArrowUp/Down keyboard navigation to TagInputPopup; wire focusedIndex to TagOption isFocused prop for visual + ARIA feedback; input gets role=combobox + aria-controls + aria-activedescendant - Fix pre-existing TS2352 type error in use-undoable-task-actions.ts (Task→Record cast) - Regenerate IPC invoke map Co-Authored-By: Paperclip <noreply@paperclip.ing>
Toast undo button + Cmd+Z could both fire the same undo action. removeUndoEntry(id) lets consumers yank a specific entry from the stack after consuming it via an alternate path.
New useUndoableTaskActions hook centralizes undo logic for single-task operations (create, delete, complete, uncomplete, archive, field update). useBulkActions gains optional registerUndo/onAddTask params to register all 8 bulk operations with the global undo stack. 41 new test cases.
Replace inline handler bodies in tasks.tsx with hook calls. Removes ~100 LOC of completion/repeat/delete logic from the page component. Every task action now registers with the global undo stack.
Calendar view was never shipped to users. Remove all components, CSS variables, utility functions, and tests to reduce dead code.
Stale items UI (age indicators, thresholds, nudge messages) was unused. Remove components, utilities, and 346 lines of tests.
Reusable toolbar with segment tabs and icon buttons for page headers. Pill component with color variants for status/type badges.
Replace custom text-text-{primary,secondary,tertiary} tokens with
standard muted-foreground/foreground. Bump base font from 12px to
13px across task rows, filters, kanban, and toolbar for readability.
Add PageToolbar to inbox header with inline capture input. Redesign health view with type-breakdown cards and Pill badges. Add archived search, type filters, and snoozed item toggle. Refactor archived item rows with icon config map.
New compact prop for embedding in toolbars. Simplify density handling, improve token overlay alignment, and tighten spacing.
Add extractErrorMessage toast to sidebar note creation. Add aria labels to notes tree, formula editor, and tag detail view. Wire scrollContainerRef in ContentArea. Clean up remaining calendar CSS vars and add font-heading variable.
The accent color picker in Settings > Appearance was saving to DB but nothing read the value. Add --tint-* CSS variables derived from --user-accent-color via color-mix(), rewire --sidebar-terracotta to var(--tint), register in @theme inline, and replace ~30 hardcoded blue-500 Tailwind classes with tint-* across tabs, AI agent, split view, and misc components.
…flash
SET_GENERAL_SETTINGS now calls SettingsSyncManager.updateField() for
syncable fields (theme, fontSize, fontFamily, accentColor, language)
while excluding device-specific ones (startOnBoot). getStartupTheme
returns { theme, accentColor } so preload applies --user-accent-color
before React hydrates, preventing a flash of default indigo. Adds
localStorage caching for accent color on the fast startup path.
Icon value utilities (emoji-icon-utils), lazy HugeIcons loader with cache, NoteIconDisplay component, virtualized icon grid picker, and search hook for the icon library.
Replace stub getCapturePatterns with actual DB aggregation across time-heatmap, type-distribution, top-domains, and top-tags. Add unit tests and update heatmap component for compact layout.
Drop BulkArchiveOlderThan schema, IPC channel, handler, service method, useInboxBankruptcy hook, and CollectorWarning/BankruptcyDialog UI. The feature was incomplete (never wired in preload bridge) and replaced by manual archive workflows.
- Add icon field to FolderConfig and new FolderInfo type in contracts - Return FolderInfo[] (path + icon) from getFolders across the stack - Update all consumers to use FolderInfo instead of raw string paths - Polish kibo-ui tree: hideLines prop, chevron icons, tighter spacing - Polish sidebar section: uppercase labels, collapsible chevron - Simplify preload startup theme (drop accent flash workaround) - Add design tokens reference doc
- FolderIconButton with portal-based EmojiPicker for context menu - EmojiPicker gains icon tab (HugeIconGrid) alongside emoji tab - NoteIconDisplay replaces raw emoji spans in tree, tabs, search, graph tooltip, property cell, and folder view - Sidebar actions refactored to ref-based forwarding from NotesTree
- Detail panel: type-accent color system, link-specific content view, read-only mode for archived items, responsive split layout - Archived view: inline list with grouped time periods, detail panel integration, keyboard-driven unarchive/delete (replaces item-row) - Inbox list: metadata-to-actions hover swap, voice pill auto-hide - Bulk action bar: floating pill with keyboard hints - inbox-utils: generic dateAccessor for groupItemsByTimePeriod
Remove shadow-based focus ring and dark mode bg override in favor of a subtle border-foreground/20 transition — lighter, more cohesive.
Replace the modal file-picker with an inline FilingSection panel that slides in beside the triage card. Add snooze picker as a side panel. Simplify the action bar to icon-only buttons with keyboard hints. Redesign progress bar, completion screen, and streak badge. Delete the now-unused TriageFilePicker component.
Add a real-time waveform bar visualizer to the voice preview player using Web Audio API AnalyserNode. Redesign the overall content section layout with improved spacing and visual hierarchy.
Move VaultSwitcher inline with traffic lights, add auth actions (sign in/log out) to the vault dropdown, and show email context. Compact SyncStatus to icon-only in sidebar footer. Delete SidebarUserProfile (replaced by vault switcher auth section). Redesign VoiceRecorder with live waveform bars via AudioContext analyser and compact stop/cancel buttons. Inline CaptureInput voice recorder instead of replacing the input.
Replace RotateCcw with ArrowTurnBackward for the restore action in archived view. Use --user-accent-color CSS variable for selection and focus ring styling in the inbox list.
A single *:focus-visible { outline: none } rule in main.css
replaces ~90 individual focus-visible:ring-* class declarations
across UI primitives and feature components.
Extends fontFamily enum in contracts and settings-sync schemas, adds @fontsource packages, and registers CSS font-family stacks in use-theme-sync for the three new typefaces.
Adds settings-primitives.tsx with SettingsHeader, SettingsGroup, SettingRow, and SettingRowTall components. Rewrites every settings section to use the new primitives for a consistent, compact layout with grouped rows, section headers, and a wider 60px sidebar nav.
Replaces hardcoded amber colors with var(--tint) CSS variable across sync UI. Redesigns device list, recovery phrase flows, and linking screens with tighter spacing. Adds CloudSavingDone icon for idle sync status and fixes auth reducer to default unauthenticated state to the sign-in wizard step.
Tightens vault switcher sizing (16px avatar, 12px text), removes chevron indicator, and adds onCloseAutoFocus prevention. Rewrites tag manager and integration list to use bordered row layout matching the new settings primitives style.
Sets window icon via BrowserWindow config and macOS dock icon via nativeImage for dev mode. Regenerates IPC invoke map and preload types to pick up fontFamily enum expansion, inbox preview-link handler, and folder icon config changes.
Adds generate-icons.mjs for producing app icons from SVG source, a project favicon, and AGENTS.md with contribution guidelines.
Centers QR layout with dialog title/description, adds copy-code section with inline copy button, shows encryption badge, and adjusts dialog container to 400px rounded.
Delete sync-section.tsx; absorb sync status, devices, security, and sign-out into account-section.tsx. Update sidebar and vault switcher to navigate to 'account' instead of 'sync'. Move Account nav item to top of Workspace group.
Normalize headings to div with tracking-[-0.02em], swap ghost buttons for outline variant with tint-colored primaries, add inline format validation to linking-code-entry, rework OTP countdown display with Clock icon and "use different email" link, truncate long QR linking codes, add data-filled attribute to InputOTPSlot for conditional border styling.
Add vault:reveal channel to contracts, handler using shell.showItemInFolder, preload bridge, and vault-section now calls window.api.vault.reveal() instead of raw ipcRenderer.invoke.
Replace nested button+button with single role=button div that handles onClick and onKeyDown. Combine checkmark and edit-gear into a single trailing slot with hover-swap opacity transition.
Add multi-stop border gradients (teal→indigo→violet→amber), top-shine overlay, card and logo drop shadows, and background gradient to icon SVG. Include preview-icon-variants script for evaluating alternatives.
Change FROM_ADDRESS from memrynote.ai to memrynote.com. Correct STEP_MAP for recovery-input (2→1) and linking-scan (2→1) to match actual wizard flow. Remove try-catch around vault reveal call.
Update getFolders mock to return FolderInfo[] instead of string[]. Add missing mocks for convertToTask, sync modules, logger, and templates.list. Fix inbox-list assertions for redesigned TypeIcon and voice transcription status. Replace textbox role with combobox in tags-row tests. Add formatCompactRelativeTime and dateAccessor tests. Add shortcut-registry test suite. Use relative dates in isItemStale test to avoid clock drift.
Add pnpm overrides for undici>=7.24.0 (WebSocket memory/validation vulns in cheerio and miniflare transitive deps) and flatted>=3.4.2 (prototype pollution via parse() in @vitest/ui).
Add reveal() to VaultClientAPI declaration. Remove inline type annotation on getStatus callback. Cast Tweet through unknown for Record access. Cast ContentItem to TweetCardItem at call site.
h4yfans
added a commit
that referenced
this pull request
May 6, 2026
…111) * fix: resolve real project ID before creating onboarding task The task creation step passed a hardcoded 'personal' projectId which is not a real DB record — causes silent FK violation on every first run. Now resolves a valid project: uses first existing project, or creates a default 'Personal' project if none exist. * feat(settings): add shortcuts section and expand editor settings UI - Add ShortcutRegistry with all rebindable app shortcuts, conflict detection, and display helpers (formatBinding, findConflicts, getGroupedShortcuts) - Add ShortcutsSettings section with search, grouped list, inline key capture, conflict warnings, per-shortcut reset, and reset-all button - Expand EditorSettings section to expose width, spellCheck, autoSaveDelay, and showWordCount controls (migrates from useNoteEditorSettings to the richer useEditorSettings hook) - Wire Shortcuts nav item into settings.tsx sidebar - Regenerate IPC invoke map (was stale) * feat(settings): implement account section (T029-T033) - account-handlers.ts: GET_INFO (email+joinedAt from store/DB) + SIGN_OUT - Register account handlers in IPC index; regenerate invoke map - Preload: add account namespace + update index.d.ts types - useAccountInfo hook (GET_INFO), useDevices hook (wraps syncDevices) - AccountSection: identity card, storage usage bar, recovery key stub, sign-out dialog - Wire AccountSection into settings.tsx sidebar * feat(settings): implement recovery key dialog (T034-T036) - account-handlers: add GET_RECOVERY_KEY handler — retrieves master key from OS keychain (requires valid access token), returns base64 encoded - RecoveryKeyDialog: blurred display until reveal, copy button, auto-clear on close - AccountSection: wire View button → RecoveryKeyDialog, remove disabled state * feat(settings): add global capture shortcut configuration - Add REGISTER_GLOBAL_CAPTURE IPC channel to SettingsChannels - Implement applyGlobalCaptureShortcut() in settings-handlers for OS-level global shortcut registration/unregistration via electron globalShortcut - Wire settings keyboard changes to re-apply shortcut live on update - Expose REGISTER_GLOBAL_CAPTURE in preload bridge - Add GlobalCaptureRow component in shortcuts-section with live capture, macOS accessibility permission detection, and clear/reset UI - Update app startup to use applyGlobalCaptureShortcut with fallback to legacy registerQuickCaptureShortcut when no setting saved * fix(ci): regenerate IPC invoke map and fix account-handlers test mock - Regenerate generated-ipc-invoke-map.ts to include new settings channels (REGISTER_GLOBAL_CAPTURE) added by recent settings feature commits - Add missing account-handlers mock to ipc/index.test.ts — the account section feature introduced registerAccountHandlers but didn't update the registration lifecycle test, causing 3 test failures * perf: reduce cold-start time by parallelizing vault open with window creation Two changes to improve startup performance toward the <2s cold-start target: 1. Move createWindow() before autoOpenLastVault() in the app.whenReady() handler. The vault open path (SQLite init, migrations, FTS setup, file watcher, sync runtime) was blocking window creation for ~300-600ms. The renderer already handles vault-not-open state via VaultOnboarding and useVault(isLoading), so the window can appear immediately while the vault opens in the background. 2. Eliminate synchronous IPC in preload startup theme resolution. The getStartupThemeSync() function used ipcRenderer.sendSync on every launch, blocking the renderer until the main process responded. Now reads from localStorage cache first (populated on the previous run), falling back to sendSync only on first launch or corrupted storage. * chore(ipc): update generated-ipc-invoke-map with current ts-printer format The ipc-invoke-map generator uses TypeScript's printer API; output format differs between ts versions (compact one-liners vs expanded multi-line). Commit the freshly generated format so ipc:check passes. * perf: optimize startup I/O and large-vault indexing speed - store.ts: add module-level in-memory cache — eliminates repeated synchronous disk reads on every getCurrentVaultPath() and getVaults() call; reads disk once, subsequent gets are O(1) in-memory lookups - indexer.ts: replace sequential await-in-loop with concurrency-limited parallel indexing (limit=8); 1000-note vault indexing goes from ~30s to ~4s by overlapping file reads and cache writes within SQLite's safe concurrency window - index.ts: hoist dynamic import('fs') and import('mime-types') out of the hot memry-file:// protocol handler to static top-level imports; eliminates repeated module resolution overhead on every local file serve All existing store (4) and indexer (19) tests pass. Typecheck clean. * feat(a11y): WCAG 2.1 AA accessibility pass — keyboard nav, ARIA, focus indicators - Add global :focus-visible safety net in main.css so any focusable element without an explicit ring still gets a visible outline - Fix KanbanCard: add onKeyDown handler (Enter=open, Space=toggle/complete) and focus-visible:ring-2 so Tab users see focus - Destroy canvas blindspot: wrap GraphCanvas in role="img" with aria-label summarising node/edge counts; add sr-only <ul> listing all nodes by label+type for screen readers - Fix TagAutocomplete combobox ARIA: add role="combobox" + aria-controls + aria-activedescendant on input; give each option a unique id; SuggestionItem changed from button to div[role=option] inside role=listbox; TagPill span gets role=listitem - Add ArrowUp/Down keyboard navigation to TagInputPopup; wire focusedIndex to TagOption isFocused prop for visual + ARIA feedback; input gets role=combobox + aria-controls + aria-activedescendant - Fix pre-existing TS2352 type error in use-undoable-task-actions.ts (Task→Record cast) - Regenerate IPC invoke map * feat(undo): add removeUndoEntry for double-fire prevention Toast undo button + Cmd+Z could both fire the same undo action. removeUndoEntry(id) lets consumers yank a specific entry from the stack after consuming it via an alternate path. * feat(undo): add Cmd+Z undo for all task CRUD and bulk operations New useUndoableTaskActions hook centralizes undo logic for single-task operations (create, delete, complete, uncomplete, archive, field update). useBulkActions gains optional registerUndo/onAddTask params to register all 8 bulk operations with the global undo stack. 41 new test cases. * refactor(tasks): wire task handlers to useUndoableTaskActions Replace inline handler bodies in tasks.tsx with hook calls. Removes ~100 LOC of completion/repeat/delete logic from the page component. Every task action now registers with the global undo stack. * chore: remove calendar view feature Calendar view was never shipped to users. Remove all components, CSS variables, utility functions, and tests to reduce dead code. * chore: remove stale items feature Stale items UI (age indicators, thresholds, nudge messages) was unused. Remove components, utilities, and 346 lines of tests. * feat(ui): add PageToolbar and Pill primitives Reusable toolbar with segment tabs and icon buttons for page headers. Pill component with color variants for status/type badges. * refactor(tasks): migrate design tokens and normalize typography Replace custom text-text-{primary,secondary,tertiary} tokens with standard muted-foreground/foreground. Bump base font from 12px to 13px across task rows, filters, kanban, and toolbar for readability. * feat(inbox): redesign inbox with toolbar, filters, and search Add PageToolbar to inbox header with inline capture input. Redesign health view with type-breakdown cards and Pill badges. Add archived search, type filters, and snoozed item toggle. Refactor archived item rows with icon config map. * feat(capture): add compact mode and streamline layout New compact prop for embedding in toolbars. Simplify density handling, improve token overlay alignment, and tighten spacing. * fix: add error toasts, a11y attributes, and polish misc components Add extractErrorMessage toast to sidebar note creation. Add aria labels to notes tree, formula editor, and tag detail view. Wire scrollContainerRef in ContentArea. Clean up remaining calendar CSS vars and add font-heading variable. * chore(ipc): regenerate invoke map with current handler signatures * feat(theme): wire accent color setting to UI via tint CSS variables The accent color picker in Settings > Appearance was saving to DB but nothing read the value. Add --tint-* CSS variables derived from --user-accent-color via color-mix(), rewire --sidebar-terracotta to var(--tint), register in @theme inline, and replace ~30 hardcoded blue-500 Tailwind classes with tint-* across tabs, AI agent, split view, and misc components. * feat(settings): sync accent color across devices and prevent startup flash SET_GENERAL_SETTINGS now calls SettingsSyncManager.updateField() for syncable fields (theme, fontSize, fontFamily, accentColor, language) while excluding device-specific ones (startOnBoot). getStartupTheme returns { theme, accentColor } so preload applies --user-accent-color before React hydrates, preventing a flash of default indigo. Adds localStorage caching for accent color on the fast startup path. * feat(icons): add HugeIcons rendering infrastructure Icon value utilities (emoji-icon-utils), lazy HugeIcons loader with cache, NoteIconDisplay component, virtualized icon grid picker, and search hook for the icon library. * feat(inbox): implement real capture patterns query Replace stub getCapturePatterns with actual DB aggregation across time-heatmap, type-distribution, top-domains, and top-tags. Add unit tests and update heatmap component for compact layout. * chore: remove inbox bankruptcy feature Drop BulkArchiveOlderThan schema, IPC channel, handler, service method, useInboxBankruptcy hook, and CollectorWarning/BankruptcyDialog UI. The feature was incomplete (never wired in preload bridge) and replaced by manual archive workflows. * feat(folders): polish tree component and add folder icon support - Add icon field to FolderConfig and new FolderInfo type in contracts - Return FolderInfo[] (path + icon) from getFolders across the stack - Update all consumers to use FolderInfo instead of raw string paths - Polish kibo-ui tree: hideLines prop, chevron icons, tighter spacing - Polish sidebar section: uppercase labels, collapsible chevron - Simplify preload startup theme (drop accent flash workaround) - Add design tokens reference doc * feat(folders): add folder icon picker and NoteIconDisplay across UI - FolderIconButton with portal-based EmojiPicker for context menu - EmojiPicker gains icon tab (HugeIconGrid) alongside emoji tab - NoteIconDisplay replaces raw emoji spans in tree, tabs, search, graph tooltip, property cell, and folder view - Sidebar actions refactored to ref-based forwarding from NotesTree * feat(inbox): redesign detail panel, archived view, list, and bulk bar - Detail panel: type-accent color system, link-specific content view, read-only mode for archived items, responsive split layout - Archived view: inline list with grouped time periods, detail panel integration, keyboard-driven unarchive/delete (replaces item-row) - Inbox list: metadata-to-actions hover swap, voice pill auto-hide - Bulk action bar: floating pill with keyboard hints - inbox-utils: generic dateAccessor for groupItemsByTimePeriod * refactor(ui): simplify Input focus ring to border-only Remove shadow-based focus ring and dark mode bg override in favor of a subtle border-foreground/20 transition — lighter, more cohesive. * feat(inbox): polish detail panel with LinkPreview, inline filing, and simplified accents - Replace LinkDetailContent with lightweight LinkPreview (favicon monogram, date, title) - Redesign detail panel as 600px inline component (was Sheet/drawer) - Redesign filing section: auto-select top AI folder, searchable folder picker, inline tag input with AI-suggested tags, polished note linking - Simplify type-accents to accentClass+hex pattern, drop getTypeAccentColor/Bg - Redesign tag-autocomplete: flat dropdown with AI suggestions, space/comma to add - Polish inbox list and archived views with consistent spacing Note: bulk-file-panel and bulk-tag-popover still reference old TagAutocomplete props (onTagsChange, showSections) — to be updated before merge. * refactor(inbox): extract DetailHeader and NoteDetail from detail panel Unified compact header (type icon + label + time + close) replaces two inline variants. Note type gets dedicated body with titled content card. All types now share the same header component. * refactor(inbox): simplify reminder TypeIcon and remove isViewed prop * fix(tags): cast counts to Number and prune orphaned definitions SQLite aggregate results were string-concatenating counts across note/task tag queries. Now casts via Number() at the query boundary, filters zero-count tags, deletes orphaned tag definitions, and switches the renderer hook to the merged tagsService.getAllWithCounts() endpoint. * refactor(social): remove unused non-Twitter platform support Only Twitter/X extraction was ever wired up — LinkedIn, Mastodon, Bluesky, and Threads endpoints were null stubs. Narrows SocialPlatform to 'twitter', strips dead oEmbed config, removes platform icons and detection branches from social-card, url-utils, and contracts. * feat(inbox): add live title extraction, compact dates, and PDF icon - Extract title from BlockNote blocks as user edits (blocknote-title util) - Replace relative timestamps with compact "DD Mon YY" format everywhere - Add FilePdf icon for PDF inbox items in list and content section - Improve content-section layout with flex gap and image constraints * refactor(sidebar): use NoteIconDisplay and simplify task count badge Switch bookmark/tag emoji rendering to NoteIconDisplay component for consistent icon handling. Simplify today's task count to plain text instead of colored pill. Tighten tag list horizontal padding. * fix(graph): guard nodeSummary memo against null graph data Move nodeSummary useMemo above the early-return so it doesn't access data.nodes when data is undefined during loading state. * style(ui): update dark theme to neutral charcoal and standardize border radius Dark mode palette shifts from cool-blue (#0e0e10) to neutral charcoal (#191919) for warmer feel. Sidebar follows suit (#131315 → #202020). Standardize rounded-lg → rounded-md across all components, modals, dropdowns, cards, inputs, and density config for tighter visual rhythm. Update DESIGN_TOKENS.md to reflect new defaults. * feat(contracts): add tweetId to SocialMetadata type Enables renderer-side tweet lookup via react-tweet's useTweet hook. * refactor(social): replace server-side fetch with synchronous URL parsing Remove Twitter Syndication API calls and background metadata fetching. The renderer now handles tweet data via react-tweet, so the main process only needs to extract tweetId and authorHandle from the URL. * build(desktop): add react-tweet and update CSP for Twitter embeds Allowlist pbs.twimg.com (images), cdn.syndication.twimg.com and react-tweet.vercel.app (API) in both meta-tag and session CSP. * feat(inbox): add TweetCard component for embedded tweet rendering Client-side tweet rendering via react-tweet's useTweet hook with skeleton loading, error state, avatar, metrics, and media grid. * feat(inbox): add ReminderDetail and wire content routing ReminderDetail shows trigger banner, source card with navigation, mark-as-viewed, and snooze presets. Route social→TweetCard and reminder→ReminderDetail in content-section switch. Remove redirect for reminders in inbox list — they now open in the detail panel. * feat(inbox): add titleFromUrl and isBotPageTitle utilities Extract human-readable titles from URL slugs when metadata fetch fails (e.g. Cloudflare-blocked sites). Detect bot challenge page titles to avoid storing "Just a moment..." as link titles. 17 new tests covering URL slug parsing, ID stripping, file extension removal, domain fallback, and bot-detection title matching. * fix(inbox): map metascraper fields to LinkMetadata and use slug titles Fix field name mismatch: metascraper returns image/logo/publisher/date but LinkMetadata expects heroImage/favicon/siteName/publishedDate. Use titleFromUrl for readable titles at capture time and on fetch failure. Reject bot-detection page titles via isBotPageTitle. * feat(inbox): redesign LinkPreview with hero image and domain bar Raindrop-style card layout: hero image from thumbnailUrl with gradient+favicon fallback, bolder title, excerpt, domain bar with favicon/monogram, full-width open button, capture timestamp. Reads both new and legacy metascraper field names for backward compat with existing items. * fix(inbox): remove auto-link first suggested note on filing Prevented unintended note linking when opening the filing panel. Users should explicitly choose which notes to link. * feat(transcription): auto-title voice memos from first sentence When transcription completes, replace the default "Voice memo (...)" title with a trimmed first-sentence excerpt (up to 60 chars) for better scannability in the inbox list. * feat(inbox): add formatTimeAgo utility, new icons, and social-card export Add Archive03 and ArrowTurnBackward icons for triage actions. Add formatTimeAgo() relative date helper for compact timestamps. Export extractHandleFromUrl from social-card for quick-capture use. * feat(inbox): add link preview IPC and quick-capture resize pipeline Add PREVIEW_LINK channel that fetches URL metadata without creating an inbox item (used for live link previews in quick capture). Add quick-capture:resize IPC so the renderer can auto-size the window height via ResizeObserver. Reduce default height to 82px. * refactor(inbox): replace custom toast with Sonner and redesign empty state Remove the hand-rolled toast system (ToastContainer, useInboxNotifications state, addToast prop-threading) in favor of Sonner's global toast() API. This eliminates prop drilling through 5 layers of components. Redesign the inbox-zero empty state to show weekly filing count and current streak instead of the getting-started onboarding flow. Delete unused GettingStartedState and CaptureMethodsGrid components. * feat(inbox): redesign quick capture with sub-components Split the monolithic QuickCapture component into focused sub-components: QuickCaptureInput, QuickCaptureFooter, QuickCaptureStates (success/error/ duplicate), LinkPreviewCard, and FilePreviewCard. Add live link preview with debounced metadata fetch, social post detection, auto-resize via ResizeObserver, and file/image preview cards. Add textarea to drag-region no-drag exclusion list. * feat(inbox): redesign triage mode with inline filing panel Replace the modal file-picker with an inline FilingSection panel that slides in beside the triage card. Add snooze picker as a side panel. Simplify the action bar to icon-only buttons with keyboard hints. Redesign progress bar, completion screen, and streak badge. Delete the now-unused TriageFilePicker component. * feat(inbox): add waveform visualizer and redesign content section Add a real-time waveform bar visualizer to the voice preview player using Web Audio API AnalyserNode. Redesign the overall content section layout with improved spacing and visual hierarchy. * style(desktop): polish sidebar, vault switcher, and voice recorder Move VaultSwitcher inline with traffic lights, add auth actions (sign in/log out) to the vault dropdown, and show email context. Compact SyncStatus to icon-only in sidebar footer. Delete SidebarUserProfile (replaced by vault switcher auth section). Redesign VoiceRecorder with live waveform bars via AudioContext analyser and compact stop/cancel buttons. Inline CaptureInput voice recorder instead of replacing the input. * chore: add metascraper test script * style(inbox): use ArrowTurnBackward icon and accent color CSS variable Replace RotateCcw with ArrowTurnBackward for the restore action in archived view. Use --user-accent-color CSS variable for selection and focus ring styling in the inbox list. * style(desktop): replace per-component focus rings with global reset A single *:focus-visible { outline: none } rule in main.css replaces ~90 individual focus-visible:ring-* class declarations across UI primitives and feature components. * feat(desktop): add Gelasio, Geist, and Inter font families Extends fontFamily enum in contracts and settings-sync schemas, adds @fontsource packages, and registers CSS font-family stacks in use-theme-sync for the three new typefaces. * refactor(settings): extract shared primitives and redesign all pages Adds settings-primitives.tsx with SettingsHeader, SettingsGroup, SettingRow, and SettingRowTall components. Rewrites every settings section to use the new primitives for a consistent, compact layout with grouped rows, section headers, and a wider 60px sidebar nav. * style(sync): redesign sync components and auth wizard Replaces hardcoded amber colors with var(--tint) CSS variable across sync UI. Redesigns device list, recovery phrase flows, and linking screens with tighter spacing. Adds CloudSavingDone icon for idle sync status and fixes auth reducer to default unauthenticated state to the sign-in wizard step. * style(desktop): polish vault switcher, tag manager, and integration list Tightens vault switcher sizing (16px avatar, 12px text), removes chevron indicator, and adds onCloseAutoFocus prevention. Rewrites tag manager and integration list to use bordered row layout matching the new settings primitives style. * chore(desktop): set app icon and regenerate IPC types Sets window icon via BrowserWindow config and macOS dock icon via nativeImage for dev mode. Regenerates IPC invoke map and preload types to pick up fontFamily enum expansion, inbox preview-link handler, and folder icon config changes. * chore: add icon generation script, favicon, and agents doc Adds generate-icons.mjs for producing app icons from SVG source, a project favicon, and AGENTS.md with contribution guidelines. * style(sync): redesign QR device linking dialog Centers QR layout with dialog title/description, adds copy-code section with inline copy button, shows encryption badge, and adjusts dialog container to 400px rounded. * refactor(settings): merge sync section into account section Delete sync-section.tsx; absorb sync status, devices, security, and sign-out into account-section.tsx. Update sidebar and vault switcher to navigate to 'account' instead of 'sync'. Move Account nav item to top of Workspace group. * style(sync): polish sync component typography and layouts Normalize headings to div with tracking-[-0.02em], swap ghost buttons for outline variant with tint-colored primaries, add inline format validation to linking-code-entry, rework OTP countdown display with Clock icon and "use different email" link, truncate long QR linking codes, add data-filled attribute to InputOTPSlot for conditional border styling. * feat(vault): add vault:reveal IPC to open folder in Finder Add vault:reveal channel to contracts, handler using shell.showItemInFolder, preload bridge, and vault-section now calls window.api.vault.reveal() instead of raw ipcRenderer.invoke. * style(tasks): rework project dropdown for keyboard accessibility Replace nested button+button with single role=button div that handles onClick and onKeyDown. Combine checkmark and edit-gear into a single trailing slot with hover-swap opacity transition. * style(icons): add gradient border and drop shadow to app icon Add multi-stop border gradients (teal→indigo→violet→amber), top-shine overlay, card and logo drop shadows, and background gradient to icon SVG. Include preview-icon-variants script for evaluating alternatives. * fix: update email sender domain and wizard step mapping Change FROM_ADDRESS from memrynote.ai to memrynote.com. Correct STEP_MAP for recovery-input (2→1) and linking-scan (2→1) to match actual wizard flow. Remove try-catch around vault reveal call. * test: update mocks and assertions for current API surface Update getFolders mock to return FolderInfo[] instead of string[]. Add missing mocks for convertToTask, sync modules, logger, and templates.list. Fix inbox-list assertions for redesigned TypeIcon and voice transcription status. Replace textbox role with combobox in tags-row tests. Add formatCompactRelativeTime and dateAccessor tests. Add shortcut-registry test suite. Use relative dates in isItemStale test to avoid clock drift. * docs: add desktop polish changelog entry * fix(deps): override undici and flatted for security audit Add pnpm overrides for undici>=7.24.0 (WebSocket memory/validation vulns in cheerio and miniflare transitive deps) and flatted>=3.4.2 (prototype pollution via parse() in @vitest/ui). * chore(ipc): regenerate invoke map with updated printer format * fix: guard app.dock access for non-macOS platforms * fix: resolve web typecheck errors in vault, tweet, and content types Add reveal() to VaultClientAPI declaration. Remove inline type annotation on getStatus callback. Cast Tweet through unknown for Record access. Cast ContentItem to TweetCardItem at call site. * fix: add reveal method to vault service stub * test: update email test to match memrynote.com sender domain ---------
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Comprehensive desktop UI polish pass — redesign inbox, consolidate settings, add accessibility, performance, and undo support.
Why
Bring the desktop app to visual/functional parity with the design direction: editorial typography, tint-aware accent colors, keyboard-first interaction, and a unified account settings page.
How
Type
feat— new featurerefactor— restructure without behavior changestyle— visual/UI onlyperf— performance improvementtest— adding or updating testsTest plan
Updated 11 test files with current API surface (FolderInfo[], combobox roles, sync mocks, templates.list). Added shortcut-registry test suite and formatCompactRelativeTime tests.
Checklist