Skip to content

Commit 488a7e5

Browse files
author
ComputelessComputer
committed
show city on all note headers; record travel transitions (Seoul → SF)
1 parent 269accb commit 488a7e5

1 file changed

Lines changed: 51 additions & 9 deletions

File tree

src/components/layout/AppLayout.tsx

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import Placeholder from "@tiptap/extension-placeholder";
55
import TaskItem from "@tiptap/extension-task-item";
66
import TaskList from "@tiptap/extension-task-list";
77
import { Markdown, } from "@tiptap/markdown";
8-
import { AllSelection, } from "@tiptap/pm/state";
8+
import { TextSelection, } from "@tiptap/pm/state";
99
import type { EditorView, } from "@tiptap/pm/view";
1010
import { EditorContent, useEditor, } from "@tiptap/react";
1111
import StarterKit from "@tiptap/starter-kit";
@@ -29,6 +29,12 @@ import { LibraryDrawer, } from "../library/LibraryDrawer";
2929
import { SettingsModal, } from "../settings/SettingsModal";
3030
import { UpdateBanner, } from "../UpdateBanner";
3131

32+
function applyCity(savedCity: string | null | undefined, newCity: string,): string {
33+
if (!savedCity || savedCity === newCity) return newCity;
34+
const from = savedCity.includes(" → ",) ? savedCity.split(" → ",)[0] : savedCity;
35+
return `${from}${newCity}`;
36+
}
37+
3238
function insertImageViaView(file: File, view: EditorView,) {
3339
saveImage(file,).then(async (relativePath,) => {
3440
const assetUrl = await resolveAssetUrl(relativePath,);
@@ -40,9 +46,8 @@ function insertImageViaView(file: File, view: EditorView,) {
4046
},);
4147
}
4248

43-
function DateHeader({ date, }: { date: string; },) {
49+
function DateHeader({ date, city, }: { date: string; city?: string | null; },) {
4450
const showToday = isToday(date,);
45-
const city = useTimezoneCity();
4651

4752
return (
4853
<div className="flex items-center gap-4">
@@ -60,7 +65,7 @@ function DateHeader({ date, }: { date: string; },) {
6065
today
6166
</span>
6267
)}
63-
{showToday && city && (
68+
{city && (
6469
<span className="text-sm text-gray-400 dark:text-gray-500 font-sans">
6570
{city}
6671
</span>
@@ -71,13 +76,20 @@ function DateHeader({ date, }: { date: string; },) {
7176

7277
export default function AppLayout() {
7378
const today = useCurrentDate();
79+
const currentCity = useTimezoneCity();
7480
const [todayNote, setTodayNote,] = useState<DailyNote | null>(null,);
7581
const [pastNotes, setPastNotes,] = useState<DailyNote[]>([],);
7682
const [settingsOpen, setSettingsOpen,] = useState(false,);
7783
const [libraryOpen, setLibraryOpen,] = useState(false,);
7884
const [updateInfo, setUpdateInfo,] = useState<UpdateInfo | null>(null,);
7985
const [isPinned, setIsPinned,] = useState(false,);
8086
const [opacity, setOpacity,] = useState(1,);
87+
const cityRef = useRef(currentCity,);
88+
const prevCityRef = useRef(currentCity,);
89+
const todayNoteRef = useRef<DailyNote | null>(null,);
90+
useEffect(() => {
91+
todayNoteRef.current = todayNote;
92+
}, [todayNote,],);
8193

8294
// Extend FS scope for custom journal dir on mount
8395
useEffect(() => {
@@ -117,8 +129,17 @@ export default function AppLayout() {
117129
getOrCreateDailyNote(today,),
118130
loadPastNotes(30,),
119131
],);
120-
setTodayNote(note,);
132+
133+
// Apply current city: if the note's saved city differs, record the transition
134+
const effectiveCity = currentCity ? applyCity(note.city, currentCity,) : note.city;
135+
const todayWithCity = { ...note, city: effectiveCity, };
136+
cityRef.current = effectiveCity ?? currentCity ?? "";
137+
setTodayNote(todayWithCity,);
121138
setPastNotes(past,);
139+
if (effectiveCity !== note.city) {
140+
selfWriteTimer.current = Date.now();
141+
saveDailyNote(todayWithCity,).catch(console.error,);
142+
}
122143

123144
// Build path → date map so the file watcher can identify changed notes
124145
const pastDates = Array.from({ length: 30, }, (_, i,) => getDaysAgo(i + 1,),);
@@ -134,6 +155,25 @@ export default function AppLayout() {
134155
load();
135156
}, [today,],);
136157

158+
// Detect same-day timezone change (travel): update today's note with transition city.
159+
// Guard (note.date === today) prevents this from running when both today and currentCity
160+
// change simultaneously (cross-date-line travel) — the [today] load effect handles that.
161+
useEffect(() => {
162+
const prevCity = prevCityRef.current;
163+
prevCityRef.current = currentCity;
164+
if (prevCity === currentCity) return;
165+
166+
const note = todayNoteRef.current;
167+
if (!note || note.date !== today) return;
168+
169+
const transition = applyCity(note.city ?? prevCity, currentCity,);
170+
cityRef.current = transition;
171+
const updated = { ...note, city: transition, };
172+
setTodayNote(updated,);
173+
selfWriteTimer.current = Date.now();
174+
saveDailyNote(updated,).catch(console.error,);
175+
}, [currentCity,],);
176+
137177
// Watch the journal directory for external changes
138178
useEffect(() => {
139179
let unwatch: (() => void) | null = null;
@@ -240,7 +280,9 @@ export default function AppLayout() {
240280
handleKeyDown: (view, event,) => {
241281
if ((event.metaKey || event.ctrlKey) && event.key === "a") {
242282
event.preventDefault();
243-
view.dispatch(view.state.tr.setSelection(new AllSelection(view.state.doc,),),);
283+
view.dispatch(
284+
view.state.tr.setSelection(TextSelection.create(view.state.doc, 0, view.state.doc.content.size,),),
285+
);
244286
return true;
245287
}
246288
if ((event.metaKey || event.ctrlKey) && event.key === "l") {
@@ -278,7 +320,7 @@ export default function AppLayout() {
278320
},
279321
onUpdate: ({ editor, },) => {
280322
if (!todayNote) return;
281-
handleTodaySave({ ...todayNote, content: editor.getMarkdown(), },);
323+
handleTodaySave({ ...todayNote, content: editor.getMarkdown(), city: cityRef.current, },);
282324
},
283325
},);
284326

@@ -399,7 +441,7 @@ export default function AppLayout() {
399441
onClick={() => editor?.commands.focus()}
400442
>
401443
<div className="px-6 pt-6 pb-4">
402-
<DateHeader date={today} />
444+
<DateHeader date={today} city={currentCity} />
403445
</div>
404446
{editor && <EditorBubbleMenu editor={editor} />}
405447
<EditorContent editor={editor} />
@@ -411,7 +453,7 @@ export default function AppLayout() {
411453
<div className="mx-6 border-t border-gray-200 dark:border-gray-700" />
412454
<div className="min-h-[400px]">
413455
<div className="px-6 pt-12 pb-4">
414-
<DateHeader date={note.date} />
456+
<DateHeader date={note.date} city={note.city} />
415457
</div>
416458
<EditableNote note={note} />
417459
</div>

0 commit comments

Comments
 (0)