"Word Wise" is a Kindle trademark, so rename the inline-gloss feature to
"Word Lens" throughout the product.
- User-facing strings → "Word Lens" across all 34 locales; brand translated
for Chinese (zh-CN 单词透镜, zh-TW 單詞透鏡) and German (Word-Lens-Daten).
- Code identifiers: WordWise→WordLens, wordWise→wordLens, WORD_WISE→WORD_LENS.
- Files/dirs: src/services/wordwise→wordlens, WordWisePanel→WordLensPanel,
wordwise{Ruby,Section}.ts, build/sync scripts, test dirs/fixtures,
data/wordwise→data/wordlens.
- Storage paths: CDN base, R2 key, on-device cache dir, WORDLENS_R2_BUCKET env,
pnpm wordlens:{manifest,sync}. manifest.json is path-agnostic so its
sha256/bytes stay valid (verified).
- biome.json: point the formatter-ignore at data/wordlens so the generated
one-line gloss packs aren't pretty-printed on commit.
Migration notes:
- Re-run `pnpm wordlens:sync` to upload packs to cdn.readest.com/wordlens/.
- Persisted view-settings keys renamed (wordWiseEnabled/Level/HintLang and
wordWiseAutoDownload) — saved values reset to defaults once on upgrade.
- Cached packs under the old Data/wordwise/ orphan (harmless re-download).
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2.3 KiB
name, description, metadata
| name | description | metadata | ||||||
|---|---|---|---|---|---|---|---|---|
| koplugin-note-deletion-sync | koplugin deleting a note didn't sync to Readest — push only walked live annotations; fixed with persisted tombstones |
|
readest.koplugin deletions of highlights/bookmarks never reached the server (#4119 push direction; the pull direction was already handled by removeDeletedAnnotations).
Root cause: SyncAnnotations:push builds its payload from getAnnotations, which walks ui.annotation.annotations (the live list). A deleted note is already removed from that list, so it can never appear in a push — the server never gets a deleted_at, and the next pull resurrects it.
Fix (all in apps/readest.koplugin/):
readest_syncannotations.lua: extractedbuildNoteDescriptor(item, book_hash, meta_hash)(shared bygetAnnotationsand the new deletion path). AddedrecordDeletion(doc_settings, item)— stampsdeletedAt = os.time()*1000on the descriptor and persists it underdoc_settings.readest_sync.deleted_notes(per-book sidecar, survives restart/offline).pushfoldsdeleted_notesinto the payload (re-stamping current book/meta hash) and clears them in the success callback only (failed push retries).main.luaonAnnotationsModified(items): detects a removal viaitems.index_modified < 0(additions use positive index_modified; note-text edits / type-changes carry no index_modified — see KOReaderReaderBookmark:removeItemByIndex). Records the tombstone whenaccess_tokenis set (independent ofauto_sync, so a later manual/close push still carries it).
Key facts: note id is deterministic — server-created notes keep their stored item.id (pulled in), koplugin-created ones derive generateNoteId(hash, type, pos0, pos1); both match the server row, so the tombstone targets it. Server sync.ts POST picks the tombstone via clientDeletedAt > serverDeletedAt (deletedAt wins even when updatedAt is stale). Missing text/note in the payload is fine (sanitizeString(undefined) returns undefined; plain highlights already push note=nil). Tests in spec/syncannotations_spec.lua (recordDeletion + push-folds-tombstones, UI-glued push driven by stub client/doc_settings). Related: custom-fonts-reincarnation-4410 (CRDT remove-wins).