From 80096f26b6f0957b865ceb8d34670750e2f3783d Mon Sep 17 00:00:00 2001 From: lucaronin Date: Mon, 23 Feb 2026 21:13:25 +0100 Subject: [PATCH 1/6] feat: add modified note indicators in NoteList, TabBar, and StatusBar - NoteItem: orange dot before title for uncommitted modified notes - TabBar: orange dot on tabs with uncommitted changes - StatusBar: "N pending" counter with CircleDot icon when modified files exist - useEditorSave: onAfterSave callback to refresh modified files after save - mock-tauri: track dynamically saved files as modified, clear on commit Co-Authored-By: Claude Opus 4.6 --- src/App.tsx | 3 ++- src/components/Editor.tsx | 1 + src/components/NoteItem.tsx | 11 ++++++++++- src/components/NoteList.tsx | 9 +++++++-- src/components/StatusBar.tsx | 11 +++++++++-- src/components/TabBar.tsx | 15 +++++++++++++-- src/hooks/useEditorSave.ts | 6 ++++-- src/mock-tauri.ts | 18 ++++++++++++++---- 8 files changed, 60 insertions(+), 14 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index a558637f..5ff6c969 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -91,6 +91,7 @@ function App() { updateVaultContent: vault.updateContent, setTabs: notes.setTabs, setToastMessage, + onAfterSave: vault.loadModifiedFiles, }) const entryActions = useEntryActions({ @@ -271,7 +272,7 @@ function App() { /> - setShowSettings(true)} onOpenLocalFolder={handleOpenLocalFolder} onCreateNewVault={handleCreateNewVault} onConnectGitHub={() => setShowGitHubVault(true)} hasGitHub={!!settings.github_token} /> + setShowSettings(true)} onOpenLocalFolder={handleOpenLocalFolder} onCreateNewVault={handleCreateNewVault} onConnectGitHub={() => setShowGitHubVault(true)} hasGitHub={!!settings.github_token} /> setToastMessage(null)} /> setShowQuickOpen(false)} /> setShowCreateTypeDialog(false)} onCreate={handleCreateType} /> diff --git a/src/components/Editor.tsx b/src/components/Editor.tsx index afb4e0dd..bd8ad4ea 100644 --- a/src/components/Editor.tsx +++ b/src/components/Editor.tsx @@ -439,6 +439,7 @@ export const Editor = memo(function Editor({ onClickNote: (entry: VaultEntry, e: React.MouseEvent) => void }) { @@ -74,6 +75,14 @@ export function NoteItem({ entry, isSelected, typeEntryMap, onClickNote }: {
+ {isModified && ( + + )} {entry.title} {entry.archived && ( diff --git a/src/components/NoteList.tsx b/src/components/NoteList.tsx index c1d8e161..8f3ccd5f 100644 --- a/src/components/NoteList.tsx +++ b/src/components/NoteList.tsx @@ -247,6 +247,11 @@ function NoteListInner({ entries, selection, selectedNote, allContent, modifiedF const [collapsedGroups, setCollapsedGroups] = useState>(new Set()) const [sortPrefs, setSortPrefs] = useState>(loadSortPreferences) + const modifiedPathSet = useMemo( + () => new Set((modifiedFiles ?? []).map((f) => f.path)), + [modifiedFiles], + ) + const handleSortChange = useCallback((groupLabel: string, option: SortOption, direction: SortDirection) => { setSortPrefs((prev) => { const next = { ...prev, [groupLabel]: { option, direction } }; saveSortPreferences(next); return next }) }, []) @@ -267,8 +272,8 @@ function NoteListInner({ entries, selection, selectedNote, allContent, modifiedF }, [onSelectNote, onReplaceActiveTab]) const renderItem = useCallback((entry: VaultEntry) => ( - - ), [selectedNote?.path, handleClickNote, typeEntryMap]) + + ), [selectedNote?.path, handleClickNote, typeEntryMap, modifiedPathSet]) return (
diff --git a/src/components/StatusBar.tsx b/src/components/StatusBar.tsx index 5a49aaa1..c64aaffd 100644 --- a/src/components/StatusBar.tsx +++ b/src/components/StatusBar.tsx @@ -1,5 +1,5 @@ import { useState, useRef, useEffect } from 'react' -import { Package, GitBranch, RefreshCw, Sparkles, FileText, Bell, Settings, FolderOpen, Check, Github, FolderPlus } from 'lucide-react' +import { Package, GitBranch, RefreshCw, Sparkles, FileText, Bell, Settings, FolderOpen, Check, Github, FolderPlus, CircleDot } from 'lucide-react' export interface VaultOption { label: string @@ -8,6 +8,7 @@ export interface VaultOption { interface StatusBarProps { noteCount: number + modifiedCount?: number vaultPath: string vaults: VaultOption[] onSwitchVault: (path: string) => void @@ -121,7 +122,7 @@ const ICON_STYLE = { display: 'flex', alignItems: 'center', gap: 4 } as const const DISABLED_STYLE = { display: 'flex', alignItems: 'center', opacity: 0.4, cursor: 'not-allowed' } as const const SEP_STYLE = { color: 'var(--border)' } as const -export function StatusBar({ noteCount, vaultPath, vaults, onSwitchVault, onOpenSettings, onOpenLocalFolder, onCreateNewVault, onConnectGitHub, hasGitHub }: StatusBarProps) { +export function StatusBar({ noteCount, modifiedCount = 0, vaultPath, vaults, onSwitchVault, onOpenSettings, onOpenLocalFolder, onCreateNewVault, onConnectGitHub, hasGitHub }: StatusBarProps) { return (