@@ -11,14 +11,15 @@ import StarterKit from "@tiptap/starter-kit";
1111import { useCallback , useEffect , useRef , useState , } from "react" ;
1212import "../editor/Editor.css" ;
1313import { listen , } from "@tauri-apps/api/event" ;
14+ import { watch , } from "@tauri-apps/plugin-fs" ;
1415import { useCurrentDate , } from "../../hooks/useCurrentDate" ;
1516import { resolveAssetUrl , saveImage , } from "../../services/images" ;
1617import type { LibraryItem , } from "../../services/library" ;
17- import { initJournalScope , } from "../../services/paths" ;
18- import { getOrCreateDailyNote , loadPastNotes , saveDailyNote , } from "../../services/storage" ;
18+ import { getJournalDir , getNotePath , initJournalScope , } from "../../services/paths" ;
19+ import { getOrCreateDailyNote , loadDailyNote , loadPastNotes , saveDailyNote , } from "../../services/storage" ;
1920import { rolloverTasks , } from "../../services/tasks" ;
2021import { checkForUpdate , type UpdateInfo , } from "../../services/updater" ;
21- import { DailyNote , formatDate , isToday , } from "../../types/note" ;
22+ import { DailyNote , formatDate , getDaysAgo , isToday , } from "../../types/note" ;
2223import { EditorBubbleMenu , } from "../editor/EditorBubbleMenu" ;
2324import { WidgetExtension , } from "../editor/extensions/widget/WidgetExtension" ;
2425import EditableNote from "../journal/EditableNote" ;
@@ -110,12 +111,68 @@ export default function AppLayout() {
110111 ] , ) ;
111112 setTodayNote ( note , ) ;
112113 setPastNotes ( past , ) ;
114+
115+ // Build path → date map so the file watcher can identify changed notes
116+ const pastDates = Array . from ( { length : 30 , } , ( _ , i , ) => getDaysAgo ( i + 1 , ) , ) ;
117+ const [ todayPath , ...pastPaths ] = await Promise . all ( [
118+ getNotePath ( today , ) ,
119+ ...pastDates . map ( ( d , ) => getNotePath ( d , ) ) ,
120+ ] , ) ;
121+ const pathMap = new Map < string , string > ( ) ;
122+ pathMap . set ( todayPath , today , ) ;
123+ pastDates . forEach ( ( d , i , ) => pathMap . set ( pastPaths [ i ] , d , ) ) ;
124+ notePathsRef . current = pathMap ;
113125 }
114126 load ( ) ;
115127 } , [ today , ] , ) ;
116128
129+ // Watch the journal directory for external changes
130+ useEffect ( ( ) => {
131+ let unwatch : ( ( ) => void ) | null = null ;
132+
133+ getJournalDir ( ) . then ( async ( dir , ) => {
134+ unwatch = await watch (
135+ dir ,
136+ ( event , ) => {
137+ // Ignore events triggered by our own saves
138+ if ( Date . now ( ) - selfWriteTimer . current < 3000 ) return ;
139+
140+ const mdPaths = event . paths . filter ( ( p , ) => p . endsWith ( ".md" , ) ) ;
141+ if ( mdPaths . length === 0 ) return ;
142+
143+ for ( const changedPath of mdPaths ) {
144+ const date = notePathsRef . current . get ( changedPath , ) ;
145+ if ( ! date ) continue ;
146+
147+ if ( date === today ) {
148+ loadDailyNote ( today , )
149+ . then ( ( reloaded , ) => {
150+ if ( reloaded ) setTodayNote ( reloaded , ) ;
151+ } , )
152+ . catch ( console . error , ) ;
153+ } else {
154+ loadDailyNote ( date , )
155+ . then ( ( reloaded , ) => {
156+ if ( reloaded ) {
157+ setPastNotes ( ( prev , ) => prev . map ( ( n , ) => n . date === date ? reloaded : n ) ) ;
158+ }
159+ } , )
160+ . catch ( console . error , ) ;
161+ }
162+ }
163+ } ,
164+ { recursive : true , } ,
165+ ) ;
166+ } , ) . catch ( console . error , ) ;
167+
168+ return ( ) => {
169+ unwatch ?.( ) ;
170+ } ;
171+ } , [ today , ] , ) ;
172+
117173 const handleTodaySave = useCallback (
118174 ( note : DailyNote , ) => {
175+ selfWriteTimer . current = Date . now ( ) ;
119176 saveDailyNote ( note , ) . catch ( console . error , ) ;
120177 setTodayNote ( note , ) ;
121178 } ,
@@ -227,6 +284,8 @@ export default function AppLayout() {
227284
228285 const todayRef = useRef < HTMLDivElement > ( null , ) ;
229286 const scrollRef = useRef < HTMLDivElement > ( null , ) ;
287+ const selfWriteTimer = useRef ( 0 , ) ;
288+ const notePathsRef = useRef < Map < string , string > > ( new Map ( ) , ) ;
230289
231290 // "Go to Today" badge when scrolled away
232291 const [ todayDirection , setTodayDirection , ] = useState < "above" | "below" | null > ( null , ) ;
0 commit comments