Paint applied highlights natively (yellow) and immediately; suppress echo color

Two rendering observations from live use:

- Synced highlights rendered grey while device-native ones are yellow:
  KOReader natively stamps view.highlight.saved_color ("yellow" on
  color screens) onto every new highlight; a nil color takes the
  darkenRect path (grey). Applied entries now carry the device's own
  saved_color, so they look exactly like native ones.

- They only appeared after a restart: ReaderView caches each rendered
  page's highlight boxes and only invalidates the cache on
  AnnotationsModified — a plain setDirty repaints from the stale
  cache. applyServerAnnotations now dispatches AnnotationsModified
  with a non-table payload (clears the whole cache) before setDirty.

Echo safety for the new default color: an applied entry's yellow is
the device default, not user intent — pushing it back would clobber
the web color. collectAnnotations suppresses the color for entries we
applied (bookhoard_dedup_key set) that the user has not modified
since (datetime_updated, which KOReader sets on any edit); edited
entries push their color and the server lets the edit win. Verified
in the harness: applied entry gets color=yellow; un-edited echo
carries no color; an edited (datetime_updated + green) echo sends
green and the web row updates; dedup keys round-trip throughout.
This commit is contained in:
2026-08-19 20:25:10 -04:00
parent fa48615e65
commit a0ab354763
+32 -8
View File
@@ -876,6 +876,20 @@ function Bookhoard:collectAnnotations()
return p or ""
end
local function echoColor(bm)
-- Color the device can vouch for as user intent:
-- - entries we applied ourselves carry the device DEFAULT color
-- (set at apply time); pushing it back would clobber the web
-- color. Suppress it unless the user has edited the entry since
-- (datetime_updated — set by KOReader on any modification).
-- - device-native entries carry a user-chosen (or default) color;
-- those push their color as before.
if bm.bookhoard_dedup_key and not bm.datetime_updated then
return nil
end
return bm.color
end
for _, bm in ipairs(entries) do
local sel_text, user_note
if model == "v2" then
@@ -936,8 +950,9 @@ function Bookhoard:collectAnnotations()
table.insert(notes, entry)
elseif has_text then
entry.type = "highlight"
if bm.color then
entry.color = bm.color
local ec = echoColor(bm)
if ec then
entry.color = ec
end
table.insert(highlights, entry)
else
@@ -1325,10 +1340,15 @@ function Bookhoard:applyServerAnnotations(annotations)
entry.drawer = "lighten"
entry.text = srv_text
if srv_notes ~= "" then entry.note = srv_notes end
-- No color imposed: devices render their own default and
-- cannot round-trip web colors; the web color only changes
-- when the highlight is edited here (the edit sets a device
-- color, which syncs back by name).
-- Match the device's native highlight look exactly: native
-- highlights carry view.highlight.saved_color ("yellow" on
-- color screens); a nil color renders grey (darkenRect).
-- Synced entries still never push this color back (see
-- collectAnnotations) — the web color only changes when the
-- highlight is edited here.
local default_color = (self.ui.view and self.ui.view.highlight
and self.ui.view.highlight.saved_color) or "yellow"
entry.color = default_color
else
if srv_text ~= "" then entry.note = srv_text end -- bookmark label
end
@@ -1426,8 +1446,12 @@ function Bookhoard:applyServerAnnotations(annotations)
if self.ui.saveSettings then
self.ui:saveSettings()
end
-- ReaderView paints annotations from the model on each repaint;
-- request one so applied highlights appear immediately.
-- ReaderView caches each rendered page's highlight boxes and only
-- invalidates them on AnnotationsModified — without this, applied
-- annotations don't paint until restart despite the repaint.
-- A non-table payload clears the whole cache (per-item payloads
-- only remove the pages of the listed items).
self.ui:handleEvent(Event:new("AnnotationsModified", nil))
if self.ui.dialog then
UIManager:setDirty(self.ui.dialog, "ui")
end