Fix crash on pull: AnnotationsModified payload must be a table
Event:new("AnnotationsModified", nil) delivered a nil payload to
every handler; ReaderThumbnail:resetCachedPagesForBookmarks does
#annotations on it and crashed KOReader the moment a pull applied
annotations (native KOReader always dispatches this event with a
table payload).
applyServerAnnotations now collects per-changed-item payloads and
dispatches them after applying, mirroring the native add/update/
remove dispatch shapes exactly: {entry, index_modified=index} for
adds (index from annotation:addItem), {bm} for content updates, and
{removed, index_modified=-index} for tombstone removals. This keeps
ReaderView's page-level highlight-box cache invalidation AND its
cached box-index shifting consistent, so mid-session pulls both
paint immediately and keep tap-to-edit associations correct.
Harness-verified: every dispatched payload is a table (explicit
crash-regression assertion simulating ReaderThumbnail's handler),
per-item index_modified values are correct, and all prior behaviors
(color flow, echo suppression, dedup round-trip) still hold.
This commit is contained in:
@@ -1232,6 +1232,10 @@ function Bookhoard:applyServerAnnotations(annotations)
|
|||||||
if not model then return end
|
if not model then return end
|
||||||
|
|
||||||
local changed = false
|
local changed = false
|
||||||
|
local notify_events = {}
|
||||||
|
local function notify(ev)
|
||||||
|
notify_events[#notify_events + 1] = ev
|
||||||
|
end
|
||||||
local has_pages = self.ui.document.info.has_pages
|
local has_pages = self.ui.document.info.has_pages
|
||||||
|
|
||||||
local function findLocal(server_entry)
|
local function findLocal(server_entry)
|
||||||
@@ -1321,6 +1325,7 @@ function Bookhoard:applyServerAnnotations(annotations)
|
|||||||
if cur_text ~= srv_text or cur_note ~= srv_notes then
|
if cur_text ~= srv_text or cur_note ~= srv_notes then
|
||||||
setFields(bm, srv_text, srv_notes)
|
setFields(bm, srv_text, srv_notes)
|
||||||
if server_entry.color and server_entry.color ~= "" then bm.color = server_entry.color end
|
if server_entry.color and server_entry.color ~= "" then bm.color = server_entry.color end
|
||||||
|
notify({ bm })
|
||||||
changed = true
|
changed = true
|
||||||
end
|
end
|
||||||
elseif model == "v2" then
|
elseif model == "v2" then
|
||||||
@@ -1359,7 +1364,8 @@ function Bookhoard:applyServerAnnotations(annotations)
|
|||||||
else
|
else
|
||||||
if srv_text ~= "" then entry.note = srv_text end -- bookmark label
|
if srv_text ~= "" then entry.note = srv_text end -- bookmark label
|
||||||
end
|
end
|
||||||
self.ui.annotation:addItem(entry)
|
local index = self.ui.annotation:addItem(entry)
|
||||||
|
notify({ entry, index_modified = index })
|
||||||
changed = true
|
changed = true
|
||||||
else
|
else
|
||||||
local entry = {
|
local entry = {
|
||||||
@@ -1435,6 +1441,7 @@ function Bookhoard:applyServerAnnotations(annotations)
|
|||||||
local cur_text = bm and (getFields(bm)) or ""
|
local cur_text = bm and (getFields(bm)) or ""
|
||||||
if idx and cur_text ~= "" then
|
if idx and cur_text ~= "" then
|
||||||
table.remove(entries, idx)
|
table.remove(entries, idx)
|
||||||
|
notify({ bm, index_modified = -idx })
|
||||||
changed = true
|
changed = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1444,7 +1451,9 @@ function Bookhoard:applyServerAnnotations(annotations)
|
|||||||
for _, del in ipairs(annotations.deleted_bookmarks) do
|
for _, del in ipairs(annotations.deleted_bookmarks) do
|
||||||
local idx = findLocalByTombstone(del, false)
|
local idx = findLocalByTombstone(del, false)
|
||||||
if idx then
|
if idx then
|
||||||
|
local removed = entries[idx]
|
||||||
table.remove(entries, idx)
|
table.remove(entries, idx)
|
||||||
|
notify({ removed, index_modified = -idx })
|
||||||
changed = true
|
changed = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1462,9 +1471,14 @@ function Bookhoard:applyServerAnnotations(annotations)
|
|||||||
-- ReaderView caches each rendered page's highlight boxes and only
|
-- ReaderView caches each rendered page's highlight boxes and only
|
||||||
-- invalidates them on AnnotationsModified — without this, applied
|
-- invalidates them on AnnotationsModified — without this, applied
|
||||||
-- annotations don't paint until restart despite the repaint.
|
-- annotations don't paint until restart despite the repaint.
|
||||||
-- A non-table payload clears the whole cache (per-item payloads
|
-- Payloads MUST be tables: ReaderThumbnail iterates them, and a
|
||||||
-- only remove the pages of the listed items).
|
-- nil payload crashed KOReader (#nil) on pull. Per-item payloads
|
||||||
self.ui:handleEvent(Event:new("AnnotationsModified", nil))
|
-- with index_modified mirror the native add/update/remove
|
||||||
|
-- dispatches exactly (page-level cache invalidation + cached box
|
||||||
|
-- index shifting).
|
||||||
|
for _, ev in ipairs(notify_events) do
|
||||||
|
self.ui:handleEvent(Event:new("AnnotationsModified", ev))
|
||||||
|
end
|
||||||
if self.ui.dialog then
|
if self.ui.dialog then
|
||||||
UIManager:setDirty(self.ui.dialog, "ui")
|
UIManager:setDirty(self.ui.dialog, "ui")
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user