Skip to content

Latest commit

 

History

History
37 lines (27 loc) · 4.03 KB

File metadata and controls

37 lines (27 loc) · 4.03 KB

UV Reader — agent notes

Standalone desktop reader (Electron) for EPUB/PDF/FB2/MOBI/AZW3/CBZ with highlights, notes and optional AI. Product name: UV Reader / 柚肥阅读. UI copy, README and docs are Chinese-first. The Obsidian plugin packaging has been removed; the reader UI is migrating from an Obsidian-hosted implementation to a host-agnostic one.

Layout

  • packages/reader/src/ — reader source. main.js (~13k lines) is still the UI entry and imports obsidian; every other module is pure (no host imports) and unit-tested.
  • packages/host-shim/ — Obsidian API compatibility layer that lets main.js run inside Electron during the migration.
  • apps/desktop/ — Electron shell (main/preload/renderer) with its own package.json and lockfile.

Commands

  • npm ci first; postinstall runs patch-pdfjs.cjs (idempotent pdf.js sentence-period fix, reverts on every fresh install).
  • npm test — reader-core tests (node --test tests/*.test.mjs). One file: node --test tests/core-config.test.mjs; one test: add --test-name-pattern="…".
  • npm run test:shim / npm run test:desktop — compatibility layer / shell tests.
  • npm run check:i18n — dictionary, placeholder, HTML and URL parity across 9 languages plus exact-string assertions about packages/reader/src/main.js.
  • npx eslint packages/reader/src/ --max-warnings=0 — CI treats warnings as failures.
  • npm run desktop:install (once; behind a blocked network set ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/), desktop:build, desktop:dev, desktop:start, desktop:smoke (boots against a starter book and exits 0/1), desktop:e2e (Playwright-Electron).

CI order (.github/workflows/ci.yml): test → test:shim → test:desktop → check:i18n → eslint → desktop build → smoke under xvfb.

Migration rules

  • packages/reader/src/main.js is the Obsidian-flavored UI being peeled apart; 15 test files and check-i18n assert exact substrings there. Rewording or moving code breaks the gates, so put testable logic in pure modules under packages/reader/src/*.js.
  • Keep packages/host-shim behavior-compatible with Obsidian: setViewState must call view.setState, Modal needs a close button/backdrop/Esc stack and must not clobber Modal.scope (history filtering uses filterScope), Setting needs settingEl, components need selectEl/toggleEl/sliderEl, and SecretStorage.getSecret must be synchronous.
  • Desktop builds write to apps/desktop/dist/ (gitignored). Never recreate root main.js/styles.css; those plugin artifacts are gone.
  • packages/reader/src/pdf-cmaps-data.js is generated by scripts/generate-pdf-cmaps.mjs; do not edit.
  • assets/starter-books/ are pinned Project Gutenberg sources (sha256 in catalog.json, -text -whitespace in .gitattributes); regenerate with npm run build:books, never hand-edit.
  • esbuild aliases node builtins and localforage to build-stubs/empty.js; __PDF_WORKER_CODE__ and __QBR_ENGINE_VIEW_TAG__ are build-time defines. Do not import node builtins from packages/reader/src/.

Product interaction preferences

  • Optimize for reading, highlighting and taking notes; minimize setup steps and cognitive load.
  • Use progressive disclosure. Show service/model choices, required inputs and real readiness first. Fold paths, protocols, installation commands, response customization, storage internals and maintenance. Surface blocking errors with a specific recovery action.
  • Prefer existing accounts, verified defaults, standard icons and short visible labels. Do not claim a connection works before checking it.
  • Unnecessary hover tooltips are off by default, including Obsidian tooltips generated from aria-label, setTooltip and native title. Preserve accessible names with aria-labelledby or visually hidden labels, keyboard focus, visible slider values and useful error feedback. Do not hide tooltips globally or affect other plugins.
  • A tooltip exception needs a concrete usability reason; do not add one just to repeat an icon label or visible text. Keep it scoped to the relevant control.