forked from akai/readest
fix(css): multiply mix blend for images in dark override color mode (#4763)
This commit is contained in:
@@ -65,12 +65,15 @@
|
||||
- [Android hyphen selection (#1553)](android-hyphen-selection-bounds-1553.md) — Blink paints start handle on last hyphen; repair anchor + custom handles
|
||||
- [NativeFile vs RemoteFile I/O](android-nativefile-remotefile-io.md) — NativeFile slow; RemoteFile can't replace (asset Range broken); handle-reuse 2.3×
|
||||
- [Window-state sanitizer (#4398)](window-state-sanitize-4398.md) — invalid `.window-state.json` crashes WebView2; sanitizer plugin before window-state
|
||||
- [Android Open-with intent (#4521)](android-open-with-intent-flow.md) — VIEW=transient→reader, SEND=library; Telegram fails cold-start + foreign-file read
|
||||
- [Android Open-with intent (#4521)](android-open-with-intent-flow.md) — VIEW/SEND pipeline; VIEW routing now gated by `autoImportBooksOnOpen` (#4747, mobile default ON → import); Telegram cold-start + foreign-file read
|
||||
- [Dict lookup browser hijack (#4559)](dict-lookup-browser-hijack-4559.md) — missing `<queries>` ACTION_PROCESS_TEXT sdk36; filter browsers in `decideLookupDispatch`
|
||||
- [Large-PDF OOM range flood (#3470)](pdf-oom-range-flood-3470.md) — makePDF fires all ranges un-awaited → OOM; MAX_CONCURRENT_RANGES=6
|
||||
- [Android themed icon (#4733)](android-themed-icon-4733.md) — `tauri icon` emits no monochrome → force-commit; tint=SRC_IN, negative-space gap
|
||||
|
||||
## Reader Features & UI
|
||||
- [Search modes #4560 + spoiler-bound bug](search-modes-4560-and-spoiler-bound-bug.md) — regex + nearby-words in foliate search.js (phased); deferred cache/searchBook; lookupPassage spoiler bound (page vs chunk ordinal) already wrong
|
||||
- [OPDS groups carousel (#4750)](opds-groups-carousel-4750.md) — >=2 groups → horizontal react-virtuoso carousel; lazy covers; `handle.scrollBy` vertical-only so page by `scrollToIndex`; card covers rounded + badge dropped (kept in detail)
|
||||
- [Image zoom trackpad flicker (#4742)](image-zoom-trackpad-flicker-4742.md) — macOS trackpad pinch = `ctrl+wheel` stream; `0.05s` transform transition restarts each event → flicker; `isWheelZooming` debounce gates transition off
|
||||
- [Instant Highlight ate tap/swipe (Android)](instant-highlight-tap-paginate.md) — `handlePointerDown` preventDefault killed tap-paginate; touch still-hold gate `INSTANT_HOLD_MS=300`
|
||||
- [Keyboard selection adjust (#4728)](keyboard-selection-adjust-4728.md) — Shift+←/→ char, Ctrl/Alt+Shift word; `onAdjustTextSelection` in useBookShortcuts
|
||||
- [Annotator onLoad listener leak (#4735)](annotator-onload-listener-leak-paragraph-mode.md) — per-section onLoad leaked listeners; `useRendererInputListeners` once-per-view
|
||||
@@ -90,6 +93,7 @@
|
||||
- [Biometric app-lock (#4645)](biometric-app-lock-4645.md) — read flag from `appLockStore` not settingsStore; plugin `cfg(mobile)`
|
||||
- [Reference Pages (#4542)](reference-pages-672-4542.md) — 'reference' progressStyle from foliate pageList; per-book `referencePageCount`
|
||||
- [Share intent + toolbar (#4014)](annotation-share-toolbar-4014.md) — Share tool gated mobile+macOS; drag-drop customizer; `annotationToolbarItems`
|
||||
- [Customize Toolbar global (serializeConfig) #4760](customize-toolbar-global-serializeconfig.md) — was per-book; root cause `serializeConfig` `!==` ref-compares array viewSettings → always stored as stale per-book override shadowing global; fix = value compare (`isSameViewSettingValue`) in viewSettings reduce only; field stays `annotationToolbarItems` in AnnotatorConfig (no exception/rename/move); limitation: pre-existing v0.11.12 overrides not retro-cleared
|
||||
- [Native iOS TTS (#4676)](native-ios-tts-4676.md) — AVSpeechSynthesizer plugin; pause==stop, never `end` on didCancel; rate `pow^(1/2.5)`
|
||||
- [Native TTS offline halt (#4613)](native-tts-offline-autoadvance-4613.md) — `#speak` advances only on `end`; native SKIP-on-error via `forward()` + cap
|
||||
- [Edge TTS word highlight (#4017)](edge-tts-word-highlighting-4017.md) — `audio.metadata` WordBoundary synced by rAF; gates on UA not Origin
|
||||
@@ -109,6 +113,7 @@
|
||||
- [OPDS Firefox strict-XML (#4479)](opds-firefox-strict-xml-4479.md) — junk after `</feed>` → parsererror; `parseOPDSXML` slices to last close tag
|
||||
- [OPDS2 JSON search greyed (#4502)](opds2-json-search-4502.md) — `isSearchLink` ignored templated opds+json; expand `{?query}` BEFORE resolveURL
|
||||
- [OPDS HTML description (#4503)](opds-html-description-4503.md) — double-escaped into unsanitized HTML; decode-once + sanitize
|
||||
- [OPDS self-link metadata (#4749)](opds-self-link-metadata-4749.md) — summary pubs need `rel:self` deref (`opds-publication+json`); JSON `description` is HTML → `getOPDSDescriptionHtml(content ?? description)`
|
||||
- [D-pad Navigation](dpad-navigation.md) — Android TV remote / arrow-key nav design + pitfalls
|
||||
- [koplugin cover upload (#4374)](koplugin-cover-upload.md) — local covers uploaded blank; `extractLocalCover` via `getCoverImage`
|
||||
|
||||
@@ -119,6 +124,7 @@
|
||||
- [TXT chapter measure-word FP (#4658)](txt-chapter-measure-word-4658.md) — strong `[章节回讲篇话]` vs weak `[卷本册部封]` needs separator
|
||||
- [Cover stale (in-place mutation)](cover-stale-inplace-mutation-memo.md) — mutated book in place → memo skip; pure `getBookWithUpdatedMetadata`
|
||||
- [Series/author back no-op (#4437)](series-folder-back-noop-4437.md) — Next 16.2 empty-search `router.replace` no-op; `handleBack` `group=''` workaround
|
||||
- [Library/reader separate texture (#4743)](library-reader-separate-texture-4743.md) — shared `#background-texture` style; `libraryBackground*` device-local + inherit; `none` must unmount; store inits `{}`
|
||||
|
||||
## Architecture & Patterns
|
||||
- foliate-js is a git submodule at `packages/foliate-js/`; multiview paginator preloads adjacent sections (multiple View/Overlayer per book)
|
||||
|
||||
@@ -11,7 +11,7 @@ Android "Open with Readest" / "Send to Readest" file-intent pipeline and the #45
|
||||
|
||||
**Pipeline (ACTION_VIEW = "Open with", ACTION_SEND = "Share"):**
|
||||
- `NativeBridgePlugin.kt::handleIntent` is the real handler (NOT `MainActivity.kt` — its ACTION_SEND branch is legacy/redundant). → `emitSharedIntent("VIEW"|"SEND", uris)` → JS `useAppUrlIngress` `shared-intent` plugin listener → `app-incoming-url` event → `useOpenWithBooks`.
|
||||
- VIEW → `openTransient` → straight to reader (ephemeral book, `deletedAt` set, `filePath` = the content:// URI, no library write/upload). SEND → `window.OPEN_WITH_FILES` → `library/page.tsx::processOpenWithFiles` (full ingest + force cloud upload on mobile).
|
||||
- VIEW routing is now gated by `autoImportBooksOnOpen` (PR #4747, issue #4746): `shouldOpenTransient(action, autoImportBooksOnOpen)` in `helpers/openWith.ts` → only `VIEW` with the setting OFF goes `openTransient` (ephemeral book, `deletedAt` set, `filePath` = content:// URI, no library write/upload); `VIEW` with it ON falls through to the SEND path. SEND (and VIEW-with-import-on) → `window.OPEN_WITH_FILES` → `library/page.tsx::processOpenWithFiles` (full ingest + force cloud upload on mobile). The setting defaults TRUE on mobile (`DEFAULT_MOBILE_SYSTEM_SETTINGS`, desktop default still false) and its "Auto Import on File Open" toggle is now shown on mobile too. `useOpenWithBooks.handle` reads it via `appService.loadSettings()` (disk), NOT the settings store — the store is unhydrated during the cold-start intent replay and would wrongly fall back to transient. So the Telegram default is now import-to-library (persists past the dying URI grant); transient is opt-out.
|
||||
- content:// read: `nativeAppService.openFile` → if URI contains `com.android.externalstorage` → direct `NativeFile` (real path); else `copyURIToPath` → `contentResolver.openInputStream` → copy to Cache → `NativeFile`. `basename` here is LEXICAL (`@tauri-apps/api/path`), not a ContentResolver `DISPLAY_NAME` query — but EPUB format is sniffed by zip magic (`document.ts isZip()`), so an extension-less content URI still opens.
|
||||
- The Tauri deep-link plugin's `getCurrent()`/`onOpenUrl` only fire for configured deep-link domains (`https://web.readest.com`, `readest:`); `content://`/`file://` VIEW intents are filtered out by `DeepLinkPlugin.isDeepLink()`, so file opens flow ONLY through the native `shared-intent` channel, never the deep-link plugin.
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
name: customize-toolbar-global-serializeconfig
|
||||
description: Customize Toolbar applied per-book not global; root cause = serializeConfig compared viewSettings by reference (!==) so array values were always stored as stale per-book overrides
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: project
|
||||
originSessionId: c6601464-9463-4ac3-99c0-e7527e4051b5
|
||||
---
|
||||
|
||||
Customize Toolbar (annotation bar, #4014, shipped v0.11.12) changes only applied
|
||||
to the book where edited, not globally. Fixed in PR #4760 (MERGED, squashed onto
|
||||
main as 7da5f8321).
|
||||
|
||||
**Root cause:** `serializeConfig` (`src/utils/serializer.ts`) decides which per-book
|
||||
viewSettings to persist as overrides via `globalViewSettings[key] !== value` — a
|
||||
*reference* compare. It deep-clones the config first (`JSON.parse(JSON.stringify)`),
|
||||
so any **array/object** viewSettings value (`annotationToolbarItems`, and latently
|
||||
`paragraphMode`, `proofreadRules`, `ttsHighlightOptions`, `noteExportConfig`) is a
|
||||
fresh reference ≠ global → stored as a per-book override on **every** save (progress
|
||||
autosave serializes with settings each relocate). On reopen the merge
|
||||
`{ ...globalViewSettings, ...perBookOverrides }` lets the stale override shadow
|
||||
global → a global toolbar change never reaches already-saved books.
|
||||
|
||||
**Fix (final — minimal, general, no special-casing):** compare viewSettings values
|
||||
by content, not reference. Added `isSameViewSettingValue(a,b) = a===b ||
|
||||
JSON.stringify(a)===JSON.stringify(b)`, used in the viewSettings reduce ONLY
|
||||
(searchConfig left on `!==` — it holds functions / large `results`). The field
|
||||
stays `annotationToolbarItems` in `AnnotatorConfig` (normal per-book viewSettings,
|
||||
honors the isGlobal "Apply to This Book" toggle). PR diff is just serializer.ts +
|
||||
serializer.test.ts.
|
||||
|
||||
**Iteration history (user steered):** (1) a `GLOBAL_ONLY_VIEW_SETTINGS` exception
|
||||
forcing global save + strip/ignore per-book — rejected "don't make it an exception";
|
||||
(2) move field to `SystemSettings.globalReadSettings` — rejected "too much";
|
||||
(3) rename `annotationToolbarItems`→`annotationToolbar` for a clean slate — rejected,
|
||||
keep the original name (it's synced in globalViewSettings). Landing point: keep the
|
||||
name, fix only the serializer reference-compare bug.
|
||||
|
||||
**Known limitation (no rename clean-slate):** existing books may carry a per-book
|
||||
`annotationToolbarItems` override from the buggy v0.11.12 build. The value compare
|
||||
stops new ones and drops an existing one on next save when it matches global, but
|
||||
does NOT retroactively clear an override whose content differs from current global —
|
||||
those books keep the stale toolbar until re-saved while equal to global. A follow-up
|
||||
one-time migration (clear persisted per-book toolbar overrides) would close this if
|
||||
needed.
|
||||
|
||||
Tests: `src/__tests__/utils/serializer.test.ts` — array setting equal to global is
|
||||
not persisted; differing array still persisted.
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
name: image-zoom-trackpad-flicker-4742
|
||||
description: "Trackpad pinch-zoom flickered the image viewer; macOS pinch = ctrl+wheel stream, disable CSS transition during continuous gestures"
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: project
|
||||
originSessionId: affbfa14-0152-4d69-8fce-f7e0b9ee97a3
|
||||
---
|
||||
|
||||
ImageViewer (`src/app/reader/components/ImageViewer.tsx`) flickered when zooming an open image with a MacBook trackpad pinch (#4742, PR #4748).
|
||||
|
||||
**Root cause:** on macOS a trackpad pinch-to-zoom is delivered to the WebView as a rapid stream of `wheel` events with `ctrlKey: true` (NOT touch events), so it flows through `handleWheel`. The zoomed `<img>` kept its `transition: transform 0.05s ease-out` whenever `isDragging` was false. Pinch wheel events fire faster than 50ms apart, so each event restarted the in-flight transition from its interpolated mid-point — the transform constantly lagged and caught up = visible flicker. Same root cause as the #4451 pan flicker, which only fixed the pan path and (via `isDragging` set in `onTouchStart`) the touch-pinch path; the wheel-zoom path was the only continuous gesture left with the transition on. That's why touch pinch on iPhone was smooth but trackpad pinch flickered.
|
||||
|
||||
**Fix:** added an `isWheelZooming` state set on each `handleWheel` event and cleared on a 200ms debounce (wheel has no explicit gesture-end). Transition is `isDragging || isWheelZooming ? 'none' : 'transform 0.05s ease-out'`. Discrete zoom (buttons, double-click, keyboard) keeps the smoothing.
|
||||
|
||||
**General pattern:** never run a CSS `transition` on a transform that's being updated by a high-frequency continuous input stream (drag, touch pinch, trackpad/`ctrl+wheel` pinch) — the interrupted-transition restart flickers. Gate the transition off for the duration of the gesture. Maintainer couldn't repro on macOS 15.6.1 (WebKit) while reporter hit it on macOS 26.5.1 / WebKit 605.1.15; the fix is version-independent. Related: [[instant-highlight-tap-paginate]].
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
name: library-reader-separate-texture-4743
|
||||
description: "Separate library vs reader background texture (#4743); shared-style-element + two gotchas"
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: project
|
||||
originSessionId: dfdb7b38-1869-4fb4-b869-c32301c80128
|
||||
---
|
||||
|
||||
#4743: library and reader shared one background texture; split so each is set independently.
|
||||
|
||||
**Architecture**: ONE global `<style id="background-texture">` paints `body::before` (covers library) plus reader containers (`.foliate-viewer/.sidebar-container/.notebook-container ::before`). Library and reader are separate routes (only one mounted), so the split = store two values + have each page apply its own on activation, not separate style elements. New device-local `SystemSettings.libraryBackground{TextureId,Opacity,Size}` (NOT in settings sync whitelist — texture *selection* is per-device like reader's `backgroundTextureId`; only image binaries sync via `texture` replica kind). `getLibraryViewSettings(settings)` in `helpers/settings.ts` resolves each field with `?? globalViewSettings.<field>` so the bookshelf inherits the reader texture until decoupled (no migration). `ColorPanel` is context-aware via `isLibraryContext = !bookKey`: library context writes `libraryBackground*` via `saveSysSettings`, reader context unchanged via `saveViewSettings`. Applied at boot (`Providers`) + on every library mount (`library/page.tsx` effect).
|
||||
|
||||
**Gotcha 1 — `useBackgroundTexture` early-returned on `'none'` WITHOUT unmounting.** Since library+reader share the one style element, switching a page to None must actively clear a texture the OTHER page mounted. Fixed: always delegate to `applyTexture(envConfig, textureId || 'none')` (it unmounts on 'none'); only set CSS vars / addTexture for a real texture. Also fixes the symmetric reader case (opening a 'none' book after a textured one).
|
||||
|
||||
**Gotcha 2 — `useSettingsStore` initializes `settings: {} as SystemSettings`.** So `settings.globalViewSettings` is `undefined` on the first renders before `appService.loadSettings()` runs. Any NEW effect/deps that deep-derefs `settings.globalViewSettings.<x>` crashes the library with "Cannot read properties of undefined (reading 'backgroundTextureId')". Caught only in a hard reload (HMR kept old store state, so first nav didn't repro). Fix = optional-chain in effect deps + make the resolver tolerate missing globalViewSettings (fallback to 'none'). Relates to [[cover-stale-inplace-mutation-memo]].
|
||||
|
||||
Verified end-to-end in dev-web: library moon texture, reader stays none, round-trip persists, None clears live. Related: [[wordlens-feature]] i18n (recent feature commits ship `_()` strings WITHOUT running `i18n:extract`; translations are batched separately — don't commit locale churn in a feature PR).
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: opds-groups-carousel-4750
|
||||
description: OPDS feed groups (>=2) render as horizontal virtualized carousels with lazy cover loading
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: project
|
||||
originSessionId: 3073b2b0-8219-42cc-8e3f-547715b86b01
|
||||
---
|
||||
|
||||
#4750 (PR #4755, merged): when an OPDS `feed.groups.length >= 2`, `FeedView` renders each group's publications/navigation as a horizontal carousel (`src/app/opds/components/GroupCarousel.tsx`) instead of the grid; single-group feeds keep the grid. Matches Thorium.
|
||||
|
||||
`GroupCarousel` wraps a horizontal `react-virtuoso` `Virtuoso` (`horizontalDirection`), so only in-view items mount → covers load lazily as you scroll (verified via network: ~12 covers/group fetched regardless of group size; far-right items fetch only after scrolling to them).
|
||||
|
||||
Gotchas (cost real debugging):
|
||||
- `VirtuosoHandle.scrollBy({left})` is a **no-op** in horizontal mode (the handle maps to the vertical axis). Page the arrows by **index** via `scrollToIndex({index, align, behavior})`, tracking the visible range from `rangeChanged`.
|
||||
- Virtuoso sizes the horizontal track **lazily**, so a pixel `scrollBy` on the scroller element clamps to the currently-rendered width — another reason to scroll by index.
|
||||
- Arrow visibility comes from `atTopStateChange`/`atBottomStateChange` (top=left, bottom=right). Row height is measured from the first `[data-carousel-item]`; arrows are vertically centered on the cover by measuring the first `<figure>` (cards have title/author below, so centering on the whole row looks low).
|
||||
- Scrollbar hidden via a scoped `.no-scrollbar` util in `globals.css`; arrows use `eink-bordered`.
|
||||
- Tests must mock `react-virtuoso` (jsdom has no layout) like the TOCView/BooknoteView tests — render all items via `itemContent`.
|
||||
|
||||
`PublicationCard` (shared by carousel + grids) got rounded covers (`overflow-hidden rounded`, matching the library bookshelf) and dropped the inline acquisition/price badge — that badge still renders on the detail page (`PublicationView`).
|
||||
|
||||
Related: [[virtuoso_overlayscrollbars]].
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
name: opds-self-link-metadata-4749
|
||||
description: OPDS 2.0 summary publications need self-link dereference for full metadata; JSON description is HTML
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: project
|
||||
originSessionId: 0e1e6ec0-38c1-45a2-aab6-52b78a5ad38a
|
||||
---
|
||||
|
||||
Readest issue #4749 (pglaf/Gutenberg test feed `https://opds-test.pglaf.org/opds/`). Two related OPDS bugs, both fixed together.
|
||||
|
||||
**1. Summary publications need a `self`-link dereference.** OPDS 2.0 feeds may list a publication with only minimal metadata + a `rel:"self"` link of type `application/opds-publication+json` (no acquisition links, no description) — the server sends the full record only when the client follows that link on click. Thorium does this; Readest did not.
|
||||
- New `src/app/opds/utils/opdsPublication.ts`: `getPublicationDetailHref(pub)` finds the `rel:"self"` link whose type is `application/opds-publication+json` or Atom `application/atom+xml;type=entry`; `parsePublicationDocument(text, docURL)` parses JSON or Atom-entry XML (reuses foliate `getPublication`) and **absolutizes** links/images hrefs against `docURL` so downloads/cover resolve regardless of the feed's `baseURL`.
|
||||
- `page.tsx`: renamed derived `publication` → `basePublication`; an effect fetches the detail doc (via `fetchWithAuth` + proxy refs) when `selectedPublication` is set AND a detail link exists (skip directly-loaded entry docs — already full); merges as `{ metadata: resolved.metadata, links/images: resolved.* || base.* }` keyed by `source===basePublication` so a stale fetch can't bleed into the next selection. Summary renders immediately, upgrades in place.
|
||||
|
||||
**2. JSON `description` is HTML.** OPDS 2.0 keeps the summary in plain `metadata.description` (no typed `<content>`), and pglaf fills it with `<p>...</p>`. `PublicationView` rendered `<p>{description}</p>` → literal tags. Fix: `getOPDSDescriptionHtml(content ?? description)` so the (sanitized) markup renders. See [[bug-patterns]] and prior [[OPDS HTML description (#4503)]] decode-once+sanitize.
|
||||
|
||||
**Why:** less data per feed page + faster load; client dereferences on demand.
|
||||
**How to apply:** when an OPDS publication looks under-populated, check for a `rel:"self"` publication-type link before assuming the feed is the whole record. Related OPDS notes: opds-firefox-strict-xml-4479, opds2-json-search-4502, opds-html-description-4503.
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
name: search-modes-4560-and-spoiler-bound-bug
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: project
|
||||
originSessionId: c416114a-72e6-40ed-a3ed-4b2d5fd7d5f4
|
||||
---
|
||||
|
||||
**#4560 (Calibre-parity search)** was scoped down via `/autoplan` review (both Codex + Claude
|
||||
agreed the original "foundational Turso-cached engine + searchBook agent tool" was over-scoped).
|
||||
Decision = **phase it**.
|
||||
|
||||
**PR-1 (done, branch `feat/search-modes-regex-nearby-4560`, worktree `/Users/chrox/dev/readest-feat-search-modes-regex-nearby-4560`):**
|
||||
adds `regex` + `nearby-words` modes INSIDE the foliate submodule `packages/foliate-js/search.js`
|
||||
(`regexSearch`, `nearbyWordsSearch`, `mode` dispatch in `search()`/`searchMatcher`); per-word `cfis`
|
||||
+ annotation dedupe in `view.js`; `BookSearchConfig.mode`/`nearbyWords` + `BookSearchMatch.cfis` +
|
||||
`SearchExcerpt.segments` in `types/book.ts` (schema v2→v3 in `serializer.ts`, `utils/searchConfig.ts`
|
||||
helper); sidebar mode selector + greyed modifiers + "within N words" stepper + `searchError` state +
|
||||
segmented excerpt. Nearby distance = **words** (default 10), via a control — NOT chars, NOT a trailing
|
||||
number in the query. **foliate-js is a submodule** — search.js/view.js changes must be committed in
|
||||
the submodule first, then the parent pointer updated.
|
||||
|
||||
**Deferred:** PR-2 = perf cache (only if measured; neutral `search.db`, NEVER `reedy.db` — that DB is
|
||||
opt-in/desktop-gated and its delete-cleanup wouldn't run for non-AI users; FTS ngram is NOT a
|
||||
guaranteed superset so it must fall back to full scan; run regex in a Web Worker for real backtracking
|
||||
isolation). PR-3 = `searchBook` agent tool.
|
||||
|
||||
**Pre-existing bug to fix in PR-3:** `lookupPassage` spoiler protection is already wrong — it passes
|
||||
`currentPage` (a rendered page ordinal, `AIAssistant.tsx`) as `spoilerBoundPosition`, but `ReedyDb`
|
||||
compares it to `c.position_index`, a **global chunk ordinal** (`positionIndex: all.length`,
|
||||
`BookIndexer.ts`). Page count ≠ chunk count, so the bound is off. Fix searchBook (and lookupPassage)
|
||||
to spoiler-bound by the current **CFI → (sectionIndex, charOffset)**, not a position integer.
|
||||
Related: [[koplugin-stats-sync]] is unrelated; see plan at
|
||||
`~/.claude/plans/the-search-might-be-glistening-mccarthy.md`.
|
||||
@@ -265,7 +265,8 @@ const getColorStyles = (
|
||||
}
|
||||
img {
|
||||
${isDarkMode && invertImgColorInDark ? 'filter: invert(100%);' : ''}
|
||||
${!isDarkMode && overrideColor ? 'mix-blend-mode: multiply;' : ''}
|
||||
${isDarkMode && overrideColor ? 'filter: grayscale(100%) contrast(1.2) brightness(1.2);' : ''}
|
||||
${overrideColor ? 'mix-blend-mode: multiply;' : ''}
|
||||
}
|
||||
svg, img {
|
||||
${overrideColor ? `background-color: transparent !important;` : ''};
|
||||
|
||||
Reference in New Issue
Block a user