Skip to content

Commit 2eb8bb1

Browse files
author
ComputelessComputer
committed
watch journal dir for external file changes
1 parent fd80da2 commit 2eb8bb1

1 file changed

Lines changed: 62 additions & 3 deletions

File tree

src/components/layout/AppLayout.tsx

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@ import StarterKit from "@tiptap/starter-kit";
1111
import { useCallback, useEffect, useRef, useState, } from "react";
1212
import "../editor/Editor.css";
1313
import { listen, } from "@tauri-apps/api/event";
14+
import { watch, } from "@tauri-apps/plugin-fs";
1415
import { useCurrentDate, } from "../../hooks/useCurrentDate";
1516
import { resolveAssetUrl, saveImage, } from "../../services/images";
1617
import 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";
1920
import { rolloverTasks, } from "../../services/tasks";
2021
import { checkForUpdate, type UpdateInfo, } from "../../services/updater";
21-
import { DailyNote, formatDate, isToday, } from "../../types/note";
22+
import { DailyNote, formatDate, getDaysAgo, isToday, } from "../../types/note";
2223
import { EditorBubbleMenu, } from "../editor/EditorBubbleMenu";
2324
import { WidgetExtension, } from "../editor/extensions/widget/WidgetExtension";
2425
import 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

Comments
 (0)