fix: dynamic note restore without page reload + fix note list sync bugs
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 44s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 44s
- NoteHistoryModal: remove window.location.reload(), use onRestored(restored) callback - NotesTabsView: revert sync derivation to useEffect, add prevNotesRef to detect server-side content changes (restore) vs local edits — fixes note disappear bug and cross-notebook notes appearing after refresh - NoteInlineEditor key: include updatedAt so restoration remounts editor with fresh content - note-card: render title/content/labels from note prop directly, not optimisticNote
This commit is contained in:
@@ -643,46 +643,50 @@ export function NotesTabsView({
|
|||||||
|
|
||||||
const prevNotesRef = useRef<Note[]>(notes)
|
const prevNotesRef = useRef<Note[]>(notes)
|
||||||
|
|
||||||
if (notes !== prevNotesRef.current) {
|
useEffect(() => {
|
||||||
const prevIds = items.map((n) => n.id).join(',')
|
setItems((prev) => {
|
||||||
const incomingIds = notes.map((n) => n.id).join(',')
|
const prevIds = prev.map((n) => n.id).join(',')
|
||||||
|
const incomingIds = notes.map((n) => n.id).join(',')
|
||||||
const merge = (fresh: Note, local: Note, oldFresh?: Note) => {
|
|
||||||
const labelsChanged = JSON.stringify(fresh.labels?.sort()) !== JSON.stringify(local.labels?.sort())
|
|
||||||
|
|
||||||
const contentChangedOnServer = oldFresh && oldFresh.content !== fresh.content
|
|
||||||
const titleChangedOnServer = oldFresh && oldFresh.title !== fresh.title
|
|
||||||
const checkItemsChangedOnServer = oldFresh && JSON.stringify(oldFresh.checkItems) !== JSON.stringify(fresh.checkItems)
|
|
||||||
|
|
||||||
return {
|
const merge = (fresh: Note, local: Note) => {
|
||||||
...fresh,
|
// Detect if the server explicitly changed content since last sync
|
||||||
title: titleChangedOnServer ? fresh.title : (local.title || fresh.title),
|
const prevServer = prevNotesRef.current.find((n) => n.id === fresh.id)
|
||||||
content: contentChangedOnServer ? fresh.content : local.content,
|
const serverContentChanged = prevServer ? prevServer.content !== fresh.content : false
|
||||||
checkItems: checkItemsChangedOnServer ? fresh.checkItems : local.checkItems,
|
const serverTitleChanged = prevServer ? prevServer.title !== fresh.title : false
|
||||||
labels: labelsChanged ? fresh.labels : local.labels
|
const serverCheckItemsChanged = prevServer
|
||||||
|
? JSON.stringify(prevServer.checkItems) !== JSON.stringify(fresh.checkItems)
|
||||||
|
: false
|
||||||
|
const labelsChanged =
|
||||||
|
JSON.stringify(fresh.labels?.slice().sort()) !==
|
||||||
|
JSON.stringify(local.labels?.slice().sort())
|
||||||
|
|
||||||
|
return {
|
||||||
|
...fresh,
|
||||||
|
title: serverTitleChanged ? fresh.title : local.title || fresh.title,
|
||||||
|
content: serverContentChanged ? fresh.content : local.content,
|
||||||
|
checkItems: serverCheckItemsChanged ? fresh.checkItems : local.checkItems,
|
||||||
|
labels: labelsChanged ? fresh.labels : local.labels,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
let result: Note[]
|
||||||
let newItems: Note[]
|
if (prevIds === incomingIds) {
|
||||||
if (prevIds === incomingIds) {
|
result = prev.map((local) => {
|
||||||
newItems = items.map((local) => {
|
const fresh = notes.find((n) => n.id === local.id)
|
||||||
const fresh = notes.find((n) => n.id === local.id)
|
return fresh ? merge(fresh, local) : local
|
||||||
if (!fresh) return local
|
})
|
||||||
const oldFresh = prevNotesRef.current.find((n) => n.id === local.id)
|
} else {
|
||||||
return merge(fresh, local, oldFresh)
|
result = notes.map((fresh) => {
|
||||||
})
|
const local = prev.find((p) => p.id === fresh.id)
|
||||||
} else {
|
return local ? merge(fresh, local) : fresh
|
||||||
newItems = notes.map((fresh) => {
|
})
|
||||||
const local = items.find((p) => p.id === fresh.id)
|
}
|
||||||
if (!local) return fresh
|
|
||||||
const oldFresh = prevNotesRef.current.find((n) => n.id === fresh.id)
|
return result
|
||||||
return merge(fresh, local, oldFresh)
|
})
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
setItems(newItems)
|
|
||||||
prevNotesRef.current = notes
|
prevNotesRef.current = notes
|
||||||
}
|
}, [notes])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (items.length === 0) {
|
if (items.length === 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user