feat(sync): serve web highlight colors to KOReader (mapped to its palette)

Reverses the earlier "no colors to the device" decision now that the
echo machinery makes it safe: GetMetadata maps the stored web hex to
KOReader's fixed color names (#ce93d8→purple, #90caf9→blue,
#a5d6a7→green, #ffd54f→yellow; pink maps to purple as the closest —
round-trip drift is prevented on the device by echo suppression, and
a device edit still wins). mapColorToKOReader restored for serving;
ingest (name→hex, preserve-on-echo) unchanged.
This commit is contained in:
2026-08-20 08:43:21 -04:00
parent dafcadd211
commit 178fb2eb37
+25 -4
View File
@@ -993,10 +993,12 @@ func (h *KOReaderHandler) GetMetadata(c *echo.Context) error {
Text: ann.SelectionText,
Pos0: pos0,
Pos1: pos1,
// No color served: devices render their own default and
// cannot round-trip web colors — the web color only changes
// when the highlight is edited on the device (push carries
// the device color, ingested with the name→hex map).
// Web colors flow to the device, mapped to KOReader's named
// palette. Round-trip safety: the device suppresses the color
// when echoing un-edited applied entries (a pink→purple
// palette mismatch must not rewrite the stored hex), and an
// actual device edit pushes its color, which wins.
Color: mapColorToKOReader(ann.Color.String),
Datetime: ann.CreatedAt.Time.Format(time.RFC3339),
DedupKey: ann.DedupKey.String,
}
@@ -1196,6 +1198,25 @@ func mapColorFromKOReader(name string) string {
return "#ffd54f"
}
var koreaderColorFromHex = map[string]string{
"#ffd54f": "yellow",
"#a5d6a7": "green",
"#90caf9": "blue",
"#ce93d8": "purple",
"#f48fb1": "purple",
}
// mapColorToKOReader normalizes a web hex swatch to the nearest KOReader
// color name (default yellow) when serving to devices. Pink maps to purple
// (the palette's closest); round-trip drift is prevented on the device by
// suppressing echo colors for un-edited applied entries.
func mapColorToKOReader(hex string) string {
if name, ok := koreaderColorFromHex[strings.ToLower(strings.TrimSpace(hex))]; ok {
return name
}
return "yellow"
}
// 1. A device-native CRE xpointer ("/body/...") in startPosition wins —
// round-trip identical for KOReader-pushed annotations (converting the
// stored CFI instead could drift and duplicate on the device).