11import { memo , useCallback , useContext , useEffect , useRef } from "react" ;
22import "./NoteManager.css" ;
33import type { ISynctexBlockId } from "@fluffylabs/links-metadata" ;
4- import { cn } from "@fluffylabs/shared-ui" ;
4+ import { Alert , Button , cn } from "@fluffylabs/shared-ui" ;
55import { twMerge } from "tailwind-merge" ;
66import { useLatestCallback } from "../../hooks/useLatestCallback" ;
77import { type ILocationContext , LocationContext } from "../LocationProvider/LocationProvider" ;
@@ -12,6 +12,7 @@ import { type ISelectionContext, SelectionContext } from "../SelectionProvider/S
1212import { InactiveNoteSkeleton } from "./components/InactiveNoteSkeleton" ;
1313import { NewNote } from "./components/NewNote" ;
1414import { NotesList } from "./components/NotesList" ;
15+ import { useFilteredNoteAlert } from "./hooks/useFilteredNoteAlert" ;
1516import { useNoteManagerNotes } from "./useNoteManagerNotes" ;
1617
1718const DEFAULT_AUTHOR = "" ;
@@ -31,7 +32,7 @@ function Notes() {
3132 const {
3233 notesManagerNotes : notes ,
3334 activeNotes,
34- latestHandleAddNote ,
35+ addNote ,
3536 sectionTitlesLoaded,
3637 notesReady,
3738 deleteNote,
@@ -40,6 +41,7 @@ function Notes() {
4041 const { selectedBlocks, pageNumber, handleClearSelection } = useContext ( SelectionContext ) as ISelectionContext ;
4142 const keepShowingNewNote = useRef < { selectionEnd : ISynctexBlockId ; selectionStart : ISynctexBlockId } > ( undefined ) ;
4243 const latestHandleClearSelection = useLatestCallback ( handleClearSelection ) ;
44+ const { noteAlertVisibilityState, triggerFilteredNoteAlert, closeNoteAlert } = useFilteredNoteAlert ( ) ;
4345
4446 const memoizedHandleDeleteNote = useCallback (
4547 ( note : IDecoratedNote ) => {
@@ -53,9 +55,14 @@ function Notes() {
5355 ( note : IDecoratedNote , newNote : IStorageNote ) => {
5456 // NOTE(optimistic): intentional mutation for immediate UI feedback; be aware this bypasses immutability
5557 note . original . content = newNote . content ;
56- updateNote ( note , newNote ) ;
58+ note . original . labels = newNote . labels ;
59+ const { isVisible } = updateNote ( note , newNote ) ;
60+ if ( ! isVisible ) {
61+ handleClearSelection ( ) ;
62+ triggerFilteredNoteAlert ( "visibleForUpdated" ) ;
63+ }
5764 } ,
58- [ updateNote ] ,
65+ [ updateNote , handleClearSelection , triggerFilteredNoteAlert ] ,
5966 ) ;
6067
6168 const handleNewNoteCancel = useCallback ( ( ) => {
@@ -84,13 +91,19 @@ function Notes() {
8491 labels,
8592 } ;
8693
87- latestHandleAddNote . current ( newNote ) ;
94+ const { isVisible } = addNote ( newNote ) ;
95+
96+ if ( ! isVisible ) {
97+ triggerFilteredNoteAlert ( "visibleForCreated" ) ;
98+ handleClearSelection ( ) ;
99+ }
100+
88101 keepShowingNewNote . current = {
89102 selectionStart : locationParams . selectionStart ,
90103 selectionEnd : locationParams . selectionEnd ,
91104 } ;
92105 } ,
93- [ pageNumber , selectedBlocks , locationParams , latestHandleAddNote ] ,
106+ [ pageNumber , selectedBlocks , locationParams , addNote , handleClearSelection , triggerFilteredNoteAlert ] ,
94107 ) ;
95108
96109 const locationRef = useRef ( { locationParams, setLocationParams } ) ;
@@ -133,44 +146,65 @@ function Notes() {
133146 } , [ readyAndLoaded ] ) ;
134147
135148 return (
136- < div className = { cn ( "note-manager flex flex-col gap-2.5" , ! readyAndLoaded && "opacity-30 pointer-events-none" ) } >
137- { locationParams . selectionEnd &&
138- locationParams . selectionStart &&
139- pageNumber !== null &&
140- selectedBlocks . length > 0 &&
141- ! isActiveNotes &&
142- ( readyAndLoaded || areSelectionsEqual ( locationParams , keepShowingNewNote . current ) ) && (
143- < NewNote
144- selectionStart = { locationParams . selectionStart }
145- selectionEnd = { locationParams . selectionEnd }
146- version = { locationParams . version }
147- onCancel = { handleNewNoteCancel }
148- onSave = { handleAddNoteClick }
149- />
150- ) }
151-
152- { ! readyAndLoaded && notes . length === 0 && (
153- < >
154- < InactiveNoteSkeleton />
155- < InactiveNoteSkeleton />
156- < InactiveNoteSkeleton />
157- < InactiveNoteSkeleton />
158- </ >
149+ < >
150+ { noteAlertVisibilityState !== "hidden" && (
151+ < Alert intent = "warning" >
152+ < Alert . Title >
153+ { noteAlertVisibilityState === "visibleForUpdated"
154+ ? "Note hidden after update"
155+ : "Note hidden by label filter" }
156+ </ Alert . Title >
157+ < div className = "flex gap-4" >
158+ < Alert . Text >
159+ { noteAlertVisibilityState === "visibleForUpdated"
160+ ? "Updated note doesn't match active labels."
161+ : "Created note doesn't match active labels." }
162+ </ Alert . Text >
163+ < Button variant = "secondary" intent = "warning" size = "sm" className = "self-end" onClick = { closeNoteAlert } >
164+ Close
165+ </ Button >
166+ </ div >
167+ </ Alert >
159168 ) }
169+ < div className = { cn ( "note-manager flex flex-col gap-2.5" , ! readyAndLoaded && "opacity-30 pointer-events-none" ) } >
170+ { locationParams . selectionEnd &&
171+ locationParams . selectionStart &&
172+ pageNumber !== null &&
173+ selectedBlocks . length > 0 &&
174+ ! isActiveNotes &&
175+ ( readyAndLoaded || areSelectionsEqual ( locationParams , keepShowingNewNote . current ) ) && (
176+ < NewNote
177+ selectionStart = { locationParams . selectionStart }
178+ selectionEnd = { locationParams . selectionEnd }
179+ version = { locationParams . version }
180+ onCancel = { handleNewNoteCancel }
181+ onSave = { handleAddNoteClick }
182+ />
183+ ) }
184+
185+ { ! readyAndLoaded && notes . length === 0 && (
186+ < >
187+ < InactiveNoteSkeleton />
188+ < InactiveNoteSkeleton />
189+ < InactiveNoteSkeleton />
190+ < InactiveNoteSkeleton />
191+ </ >
192+ ) }
160193
161- { readyAndLoaded && notes . length === 0 && (
162- < div className = "no-notes text-sidebar-foreground" > No notes available</ div >
163- ) }
194+ { readyAndLoaded && notes . length === 0 && (
195+ < div className = "no-notes text-sidebar-foreground" > No notes available</ div >
196+ ) }
164197
165- { notes . length > 0 && (
166- < MemoizedNotesList
167- activeNotes = { activeNotes }
168- notes = { notes }
169- onEditNote = { memoizedHandleUpdateNote }
170- onDeleteNote = { memoizedHandleDeleteNote }
171- onSelectNote = { memoizedHandleSelectNote }
172- />
173- ) }
174- </ div >
198+ { notes . length > 0 && (
199+ < MemoizedNotesList
200+ activeNotes = { activeNotes }
201+ notes = { notes }
202+ onEditNote = { memoizedHandleUpdateNote }
203+ onDeleteNote = { memoizedHandleDeleteNote }
204+ onSelectNote = { memoizedHandleSelectNote }
205+ />
206+ ) }
207+ </ div >
208+ </ >
175209 ) ;
176210}
0 commit comments