@@ -39,6 +39,14 @@ import { useAppearanceSettings } from './hooks/useAppearanceSettings';
3939import { useOfficialThemes } from './hooks/useOfficialThemes' ;
4040import { useResizableLayout } from './hooks/useResizableLayout' ;
4141import { useSyncStore } from './stores/syncStore' ;
42+ import {
43+ canGoBack ,
44+ canGoForward ,
45+ emptyNoteHistory ,
46+ historyBack ,
47+ historyForward ,
48+ visitNote ,
49+ } from './utils/noteHistory' ;
4250import { useDeepLinks } from './hooks/useDeepLinks' ;
4351import { useAutoSave } from './hooks/useAutoSave' ;
4452import { useNoteActions } from './hooks/useNoteActions' ;
@@ -75,19 +83,24 @@ function NotesApp() {
7583 sidebarWidth,
7684 notelistWidth,
7785 sidebarCollapsed,
86+ distractionFree,
7887 toggleSidebar,
88+ toggleDistractionFree,
7989 startResizeSidebar,
8090 startResizeNotelist,
8191 } = useResizableLayout ( ) ;
8292
93+ const hideSidebar = sidebarCollapsed || distractionFree ;
94+ const hideNoteList = distractionFree ;
95+
8396 useEffect ( ( ) => {
8497 const setVisibility = window . dripnex . windows . setButtonVisibility ;
8598 if ( typeof setVisibility !== 'function' ) return ;
86- void setVisibility ( ! sidebarCollapsed ) ;
99+ void setVisibility ( ! hideSidebar ) ;
87100 return ( ) => {
88101 void setVisibility ( true ) ;
89102 } ;
90- } , [ sidebarCollapsed ] ) ;
103+ } , [ hideSidebar ] ) ;
91104
92105 // Navigation state from Zustand
93106 const navigation = useNavigation ( ) ;
@@ -129,6 +142,11 @@ function NotesApp() {
129142 const [ selectedNote , setSelectedNote ] = useState < NoteSnapshot | null > ( null ) ;
130143 const selectedNoteRef = useRef < NoteSnapshot | null > ( null ) ;
131144 selectedNoteRef . current = selectedNote ;
145+ const [ noteHistory , setNoteHistory ] = useState ( emptyNoteHistory ) ;
146+ const setSelectedNoteAndVisit = useCallback ( ( note : NoteSnapshot | null ) => {
147+ setSelectedNote ( note ) ;
148+ if ( note ) setNoteHistory ( prev => visitNote ( prev , note . id ) ) ;
149+ } , [ ] ) ;
132150 const { appAPI, dataAPI, pluginSlot } = usePluginRuntime ( selectedNoteRef ) ;
133151 const { searchQuery, debouncedSearch, handleSearch, clearSearch } = useDebouncedSearch ( 300 ) ;
134152 const [ isGraphOpen , setIsGraphOpen ] = useState ( false ) ;
@@ -250,7 +268,7 @@ function NotesApp() {
250268 handleStatusChange,
251269 } = useNoteActions ( {
252270 selectedNote,
253- setSelectedNote,
271+ setSelectedNote : setSelectedNoteAndVisit ,
254272 selectedNotebookId,
255273 clearSearch,
256274 appAPI,
@@ -292,9 +310,31 @@ function NotesApp() {
292310 setIsGraphOpen,
293311 searchQuery,
294312 clearSearch,
295- setSelectedNote,
313+ setSelectedNote : setSelectedNoteAndVisit ,
296314 displayedNotes,
297315 onSelectNote : handleSelectNote ,
316+ onNoteBack : ( ) => {
317+ const { state, id } = historyBack ( noteHistory ) ;
318+ if ( ! id ) return ;
319+ setNoteHistory ( state ) ;
320+ void window . dripnex . notes . get ( id ) . then ( result => {
321+ if ( result . ok ) setSelectedNote ( result . data ) ;
322+ } ) ;
323+ } ,
324+ onNoteForward : ( ) => {
325+ const { state, id } = historyForward ( noteHistory ) ;
326+ if ( ! id ) return ;
327+ setNoteHistory ( state ) ;
328+ void window . dripnex . notes . get ( id ) . then ( result => {
329+ if ( result . ok ) setSelectedNote ( result . data ) ;
330+ } ) ;
331+ } ,
332+ onToggleZen : toggleDistractionFree ,
333+ onOpenInWindow : ( ) => {
334+ const note = selectedNoteRef . current ;
335+ if ( ! note ) return ;
336+ void window . dripnex . windows . openNote ( note . id , note . title || 'Note' ) ;
337+ } ,
298338 } ) ;
299339
300340 // Determine selected quick filter for NoteList header
@@ -371,14 +411,14 @@ function NotesApp() {
371411 < div className = "app__layout" >
372412 < aside
373413 className = "app__sidebar"
374- data-collapsed = { sidebarCollapsed ? 'true' : 'false' }
414+ data-collapsed = { hideSidebar ? 'true' : 'false' }
375415 style = { { width : sidebarWidth } }
376- aria-hidden = { sidebarCollapsed }
377- inert = { sidebarCollapsed || undefined }
416+ aria-hidden = { hideSidebar }
417+ inert = { hideSidebar || undefined }
378418 >
379419 < Sidebar onOpenGraph = { ( ) => setIsGraphOpen ( true ) } />
380420 </ aside >
381- { ! sidebarCollapsed ? (
421+ { ! hideSidebar ? (
382422 < div
383423 className = "resize-handle"
384424 onMouseDown = { startResizeSidebar }
@@ -387,7 +427,13 @@ function NotesApp() {
387427 />
388428 ) : null }
389429
390- < section className = "app__notelist" style = { { width : notelistWidth } } >
430+ < section
431+ className = "app__notelist"
432+ data-collapsed = { hideNoteList ? 'true' : 'false' }
433+ style = { { width : notelistWidth } }
434+ aria-hidden = { hideNoteList }
435+ inert = { hideNoteList || undefined }
436+ >
391437 < NoteList
392438 notes = { displayedNotes }
393439 selectedId = { selectedNote ?. id ?? null }
@@ -415,12 +461,14 @@ function NotesApp() {
415461 isLoading = { isLoading }
416462 />
417463 </ section >
418- < div
419- className = "resize-handle"
420- onMouseDown = { startResizeNotelist }
421- role = "separator"
422- aria-orientation = "vertical"
423- />
464+ { ! hideNoteList ? (
465+ < div
466+ className = "resize-handle"
467+ onMouseDown = { startResizeNotelist }
468+ role = "separator"
469+ aria-orientation = "vertical"
470+ />
471+ ) : null }
424472
425473 < main className = "app__editor" >
426474 { isGraphOpen ? (
@@ -462,6 +510,33 @@ function NotesApp() {
462510 onWikilinkClick = { handleWikilinkClick }
463511 onNavigateToNote = { handleSelectNote }
464512 onNoteUpdate = { setSelectedNote }
513+ canBack = { canGoBack ( noteHistory ) }
514+ canForward = { canGoForward ( noteHistory ) }
515+ distractionFree = { distractionFree }
516+ onBack = { ( ) => {
517+ const { state, id } = historyBack ( noteHistory ) ;
518+ if ( ! id ) return ;
519+ setNoteHistory ( state ) ;
520+ void window . dripnex . notes . get ( id ) . then ( result => {
521+ if ( result . ok ) setSelectedNote ( result . data ) ;
522+ } ) ;
523+ } }
524+ onForward = { ( ) => {
525+ const { state, id } = historyForward ( noteHistory ) ;
526+ if ( ! id ) return ;
527+ setNoteHistory ( state ) ;
528+ void window . dripnex . notes . get ( id ) . then ( result => {
529+ if ( result . ok ) setSelectedNote ( result . data ) ;
530+ } ) ;
531+ } }
532+ onToggleZen = { toggleDistractionFree }
533+ onOpenWindow = { ( ) => {
534+ if ( ! selectedNote ) return ;
535+ void window . dripnex . windows . openNote (
536+ selectedNote . id ,
537+ selectedNote . title || 'Note'
538+ ) ;
539+ } }
465540 />
466541 ) }
467542 </ main >
0 commit comments