XingfenD
72cf13c8c3
chore(frontend): extend tsc coverage to e2e/configs, tighten vitest include (B0)
2026-09-16 15:13:35 +08:00
XingfenD
154ef11c90
docs: reader revamp implementation plan (18 tasks, 6 batches)
2026-09-16 15:10:02 +08:00
XingfenD
043b7fc480
docs: reader revamp spec (subproject ②)
2026-09-16 14:53:59 +08:00
XingfenD
cc18822c97
Merge remote-tracking branch 'origin/feat/frontend-quality'
CI / backend (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
2026-09-16 12:16:40 +08:00
XingfenD
2fccf3f2b3
docs: record TS side-by-side + legacy-peer-deps conventions (AGENTS.md + .npmrc)
CI / backend (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
2026-09-16 11:43:21 +08:00
XingfenD
caacaf9c30
docs: changelog for component testing + bundle review (B4 done, spec ④ complete)
2026-09-16 11:28:12 +08:00
XingfenD
5ba522753a
docs: README frontend gates (lint/e2e/analyze), bilingual
2026-09-16 11:21:35 +08:00
XingfenD
8f4c34c949
docs: bundle-review — align dependency sizes to source-level caliber, rewrite epubjs finding
2026-09-16 11:18:44 +08:00
XingfenD
0bf8129f6e
docs: bundle review findings (B4)
2026-09-16 11:06:58 +08:00
XingfenD
f5c33f538e
chore(frontend): bundle analyzer via npm run analyze (B4)
2026-09-16 11:00:22 +08:00
XingfenD
cd02a88b59
ci(e2e): render configs from templates before compose up
2026-09-16 10:56:47 +08:00
XingfenD
4ba55fcf2a
ci: e2e workflow (workflow_dispatch) + changelog (B3 done)
2026-09-16 10:53:23 +08:00
XingfenD
f2f06a516b
test(frontend): e2e admin smoke (create library + scan)
2026-09-16 10:48:23 +08:00
XingfenD
9c6339d35e
test(frontend): e2e main flow (login→shelf→cbz→bookmark→logout) + axe scans
2026-09-15 17:29:20 +08:00
XingfenD
217adf5914
test(frontend): e2e api/axe helpers
2026-09-15 14:13:58 +08:00
XingfenD
ba28fe9037
test(frontend): tiny 3-page CBZ fixture for e2e
2026-09-15 14:11:24 +08:00
XingfenD
b65ea93984
test(frontend): playwright e2e scaffolding (config + scripts)
2026-09-15 12:00:45 +08:00
XingfenD
a3755bcfab
test(frontend): sample component tests for button/dialog/theme-toggle (B2)
2026-09-15 11:54:56 +08:00
XingfenD
38957b4c2c
fix(frontend): install @testing-library/dom (missing peer under legacy-peer-deps)
2026-09-15 11:50:44 +08:00
XingfenD
ca419410b4
test(frontend): component testing infra (jsdom + testing-library + vitest projects)
2026-09-15 11:46:20 +08:00
XingfenD
147339083b
chore(frontend): wire lint+format into check gate, changelog (B1 done)
2026-09-15 11:44:21 +08:00
XingfenD
a427aa1c4a
fix(frontend): resolve all eslint errors to zero (B1)
2026-09-15 11:39:21 +08:00
XingfenD
29167d3cea
style(frontend): prettier baseline format (no logic change)
2026-09-15 11:27:54 +08:00
XingfenD
09a02fa0d7
chore(frontend): eslint flat config + prettier baseline config
2026-09-15 11:22:02 +08:00
XingfenD
24c5d42531
docs: frontend quality implementation plan (16 tasks, 4 batches)
2026-09-15 11:12:38 +08:00
XingfenD
42a39ceef8
docs: frontend engineering quality spec (subproject ④)
2026-09-15 10:59:43 +08:00
XingfenD
b3a207a5d2
Merge remote-tracking branch 'origin/fix/backend-hardening'
CI / backend (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
2026-09-15 00:42:26 +08:00
XingfenD
8305af9d5c
docs: changelog + README backend structure for batch C (Task 29)
...
CI / backend (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
- CHANGELOG [Unreleased]: consolidated the duplicated Added/Changed/Fixed
groups left by earlier batches into one group each (no entry dropped);
added batch C entries — port-based restructure, media/upload domain
packages, sweep moved to scanner ticker (B16), router contract test,
portsfake unit-test layer. Upload-sweep wording no longer promises the
old 24h opportunistic request-path behaviour.
- README.md / README_zh.md: new 'Backend structure' section documenting
the port/fake layout (cmd/webui composition root, handlers as HTTP-only,
internal/ports + portsfake, media/upload/store/scanner/bookfile
responsibilities) and the two-tier testing approach (real PG+Redis
integration vs fake-injected unit, route table pinned by contract test)
Gate: gofmt clean, go vet clean, go test -p 1 all pass (0 skip),
scripts/smoke.sh ALL SMOKE TESTS PASSED against a live webui on :18080
2026-09-14 23:37:36 +08:00
XingfenD
85c61d9f24
refactor: consolidate isUnique and path validation helpers (Task 28)
...
- seed.Admin: hand-rolled pgconn.PgError 23505 check → store.IsUniqueViolation
(single predicate for unique violations across the codebase)
- books.absBookPath: local hasPrefixDir (filepath.Rel-based) removed in favor
of bookfile.Contains, which also resolves symlinks — stricter escape check
- handlers isUnique alias + libraries.go local prefix check were already
folded into ports.IsUniqueViolation / bookfile.Contains in Task 25;
scanner.inside was folded in Task 24 — this commit closes the last two
Full gate green: gofmt, vet, go test -p 1 (real PG+Redis, 0 skip)
2026-09-14 23:26:16 +08:00
XingfenD
cc1470f6e4
test: portsfake + router contract test + handler unit tests (Task 27)
...
- internal/ports/portsfake: hand-written in-memory fakes for all 9 ports
(Users/Libraries/Books/Progress/Bookmarks/RateLimiter/Scanner/Media/Uploads);
error semantics mirror the real store exactly — pgx.ErrNoRows for misses,
store.ErrLastAdmin guard, and *pgconn.PgError{Code:23505} for unique
violations (ports.IsUniqueViolation only accepts the PgError shape, so the
fakes must produce it to exercise the 409 branch without touching prod code)
- Media/Uploads fakes are hook-programmable: one field per error branch, so a
test can force e.g. CompleteErr=ErrIncomplete without stubbing the rest
- Scanner fake is mutex-guarded + WaitForScan: handler fires ScanLibraryByID
in a goroutine, tests stay deterministic
- router_test.go: TestRouterContract pins all 27 routes — any route table
change now fails the test explicitly
- handler unit tests (~30 cases, no PG/Redis): users CRUD branches (self-delete
400, last-admin 400, dup 409, 204 ok), library reserved names (contract:
code=bad_request message=reserved_name, per original impl), upload sentinel
mapping (413/400/404 per branch)
- NewRouter takes pure port interfaces; main.go distributes *store.Store
across the 5 store ports at the composition root
Full gate green: gofmt, vet, go test -p 1 (real PG+Redis, 0 skip)
2026-09-14 23:23:10 +08:00
XingfenD
7baadedeb4
refactor(handlers): consume port interfaces, wire media+upload assembly (Task 25+26)
...
- H now holds only small port interfaces (UserStore/LibraryStore/BookStore/
ProgressStore/BookmarkStore/RateLimiter/Scanner/Media/UploadSessions);
NewRouter is the composition root distributing *store.Store and *redispkg.R
- ports.Media gains EnsurePage; ChaptersOf returns ports.Chapter (media's
local duplicate dropped); *media.M now provably satisfies ports.Media;
ports.UploadSessions gains LibraryID for root validation before Complete
- content.go: duplicated page-index cache + cover self-heal + page extract
logic removed in favor of media service — same redis keys, same contract;
path traversal check stays in handler (403 semantics preserved)
- getLibrary/getLibRow merged into getLib(c, id); idParam helper dedupes
:id parsing; isUnique replaced by ports.IsUniqueViolation (Task 28 partial)
- main.go assembles media + upload and passes upload.U as scanner Sweeper
Full gate green: gofmt, vet, go test -p 1 (real PG+Redis, 0 skip)
2026-09-14 22:56:15 +08:00
XingfenD
b9b7022212
refactor(scanner): merge add/update into ingest, use shared utilities
...
- add/update consolidated into ingest(isNew) — persist branch differs,
error handling and cover path fully shared (Task 24)
- zipIndex/cover use bookfile.OpenReaderAt instead of hand-rolled
open+stat pairs
- root containment check uses bookfile.Contains (local inside removed)
- cover write goes through media.WriteAtomic (now exported, log-free —
callers own context); media no longer logs inside the atomic helper
2026-09-14 22:12:30 +08:00
XingfenD
fbd5cd243d
feat(upload): extract upload subsystem + move sweep to scanner ticker (B16)
...
- internal/upload owns chunked-upload domain logic (fingerprint resume,
part tmp+rename, assemble, session sweep) and the shared UniquePath
helper used by both single-file and chunked completion paths
- handlers/uploads.go is now HTTP-only: bind params, call upload.U, map
sentinel errors to the unchanged status/code/message contract
- B16: session sweep moved out of the UploadInit request path onto the
scanner ticker via a Sweeper hook (upload.U satisfies it)
- unit tests for the package without PG/Redis; contract pinned by the
existing handler integration tests (all green)
2026-09-14 22:00:25 +08:00
XingfenD
443f4acfa9
feat(media): Media service with EnsureCover, EnsurePage, PageIndex, ChaptersOf, writeAtomic
CI / backend (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
2026-09-14 19:50:34 +08:00
XingfenD
5ad277241c
feat(bookfile): add Contains and OpenReaderAt utilities
2026-09-14 19:49:50 +08:00
XingfenD
18bd32e0f6
refactor(store): split into per-aggregate files, unexport pool, remove dead ListBookIDs
2026-09-14 19:49:18 +08:00
XingfenD
0c3b34c184
feat(ports): define consumer-side interfaces, sentinel errors, IsUniqueViolation
2026-09-14 19:47:27 +08:00
XingfenD
f99f5a7878
docs: changelog for batch B (B1-B13 bug fixes); gofmt store.go
2026-09-14 19:46:16 +08:00
XingfenD
08b81fde60
fix(upload): retry on O_EXCL collision in single-file upload (B12)
2026-09-14 19:45:08 +08:00
XingfenD
8023a7ec5c
fix(serve): check cover write errors, clean tmp only on failure path (B11)
2026-09-14 19:43:27 +08:00
XingfenD
0c5dfd4353
fix(library): reject reserved names (cache, .uploads) with 400 reserved_name (B8)
2026-09-14 19:42:52 +08:00
XingfenD
0e62d4aa18
fix(handlers): Upload io.Copy error → 500 not 413 (B6), Me distinguishes no-rows from DB errors (B7)
2026-09-14 19:42:25 +08:00
XingfenD
b82a891c50
fix: upload part tmp+rename (B4), transactional last-admin DeleteUser (B5), RowsAffected order (B13)
2026-09-14 19:42:11 +08:00
XingfenD
8fbc58eaaa
fix(redis,scanner): atomic IncrWindow Lua, lock rand/ctx fixes, ScanLock renewal, single-flight, error logging (B1,B2,B3,B9,B10,B11)
2026-09-14 19:40:53 +08:00
XingfenD
2c2f6d3116
chore: gofmt content_test.go
2026-09-14 19:38:33 +08:00
XingfenD
26111e73af
docs: changelog + README updates for batch A (migrations, CI, B14/B15/B17)
2026-09-14 19:38:16 +08:00
XingfenD
b63d50e04b
fix(smoke): drop ignored root_path field, align with API contract (B17)
2026-09-14 19:37:42 +08:00
XingfenD
f26aac103b
fix(config): validate DATABASE_URL required and parseable, log redis disabled (B15)
2026-09-14 19:37:26 +08:00
XingfenD
f0437139f3
fix(main): channel-based serve error instead of log.Fatalf in goroutine (B14)
2026-09-14 19:36:57 +08:00
XingfenD
161128cac0
ci: add GitHub Actions workflow (Gitea Actions compatible)
2026-09-14 19:36:31 +08:00
XingfenD
6d3d23c3f9
feat(db): ordered migration system with advisory lock and baseline detection
2026-09-14 19:36:21 +08:00
XingfenD
c9b32db592
docs(plan): backend hardening implementation plan — 29 tasks across 3 batches
2026-09-14 19:33:30 +08:00
XingfenD
942a9952ca
docs(spec): clarify batch attribution for B8/B9-2 (depend on batch-C packages)
2026-09-14 19:14:45 +08:00
XingfenD and CommandCodeBot
2cf842af9e
docs(spec): backend hardening design — migrations, 17 bug fixes, ports/internal restructure, CI
...
Co-authored-by: CommandCodeBot <noreply@commandcode.ai >
2026-09-14 16:55:44 +08:00
XingfenD
a22b44be06
Merge branch 'fix/cbz-end-chapter-jump'
2026-09-08 22:45:20 +08:00
XingfenD
2e43cb2423
fix(web): stop CBZ reader snapping/bouncing at chapter end on mixed-orientation books
2026-09-08 22:42:05 +08:00
XingfenD
90b39d4f97
Merge branch 'feat/ui-redesign'
2026-09-08 21:48:41 +08:00
XingfenD
fd227c1f00
feat(web): table-style 库管理, admin entries under avatar 系统管理, shelf-view upload button
2026-09-08 21:45:03 +08:00
XingfenD
3178c2802f
refactor(web): extract prefetch slider into reusable RdSlider component
2026-09-08 21:31:20 +08:00
XingfenD
472e58bec9
fix(web): unify 更多 menu text size, add 0-3 tick anchors under prefetch slider
2026-09-08 21:30:26 +08:00
XingfenD
d2c852d6f0
feat(web): iconify reader chrome, move 连读/预读 into 更多 menu with slider
2026-09-08 21:29:01 +08:00
XingfenD
9c2b7e2074
feat(web): collapse reader toc/bookmark buttons into single 导航 toolbar button
2026-09-08 21:11:16 +08:00
XingfenD
65e07a0890
chore: ignore tsc buildinfo artifact
2026-09-08 21:08:52 +08:00
XingfenD
48161ea1ff
feat(web): unify reader TOC and bookmarks into one left nav drawer with tabs
2026-09-08 21:08:42 +08:00
XingfenD
4f4c7e5434
chore: gitignore playwright artifacts
2026-09-08 20:48:38 +08:00
XingfenD
6fbe3b0794
fix(web): active lib highlight, rail a11y names, card focus ring, AA accent + destructive tokens, touch-reachable menu, brand wordmark, chrome unify
2026-09-08 20:37:20 +08:00
XingfenD
7e0847815d
docs(changelog): phase-1 modern redesign — shadcn tokens, dual theme, app shell, rebuilt public surfaces
2026-09-08 19:37:38 +08:00
XingfenD
7727baa25b
fix(web): theme menu items fire on keyboard select (onSelect)
2026-09-08 19:19:45 +08:00
XingfenD
dcaf502de6
feat(ui): admin pages on shadcn table/card/alert-dialog; drop TopBar, trim icons/ui.ts to reader-compat surface
2026-09-08 19:14:41 +08:00
XingfenD
273f35a42f
fix(web): shelf search debounce merges against live searchParams (no lost sort/group clicks)
2026-09-08 19:08:05 +08:00
XingfenD
b1c0db6c03
feat(ui): shelf rebuilt — sticky toolbar (search/sort/group in URL), rail, menu cards, alert-dialog delete
2026-09-08 18:58:16 +08:00
XingfenD
d9e9e95ece
feat(ui): login rebuilt on shadcn card/label/input, theme toggle available pre-auth
2026-09-08 17:47:17 +08:00
XingfenD
52e95a48d8
fix(ui): gate app sidebar to md+ and use onSelect for logout (keyboard path)
2026-09-08 17:41:29 +08:00
XingfenD
7957e5cee5
feat(ui): AppShell layout route — desktop rail, tablet icon rail, mobile tabs, theme toggle
2026-09-08 17:35:14 +08:00
XingfenD
913f3286bb
feat(lib): shelf sort/section pure helpers + formatSize extraction, table tests
2026-09-08 17:29:07 +08:00
XingfenD
03bc537308
feat(ui): semantic light/dark tokens, ThemeProvider with FOUC guard, token-restyle Toaster/Cover
2026-09-08 17:17:44 +08:00
XingfenD
87b7545a94
feat(ui): shadcn/radix toolchain — deps, @ alias, cn, generated primitives
2026-09-08 17:07:28 +08:00
XingfenD
ee676c2d2e
docs(plan): modern redesign phase-1 implementation plan — 8 tasks from toolchain to acceptance walkthrough
2026-09-08 17:02:02 +08:00
XingfenD
b8a5b3deb6
docs(design): phase-1 modern redesign spec — shadcn/radix foundation, dual theme, app shell, shelf/admin rebuild; readers deferred to phase 2
2026-09-08 16:49:46 +08:00
XingfenD
2721df8ea9
fix(web): upload toast always showed 0 files (live FileList read after input reset); snapshot before upload
2026-09-08 16:22:12 +08:00
XingfenD
e5dacc0a77
fix(cbz): clamp locked cur at chapter end, hide 连读 on flat packs, silent restore, tighten prefetch storage
2026-09-08 15:28:27 +08:00
XingfenD
60c4ccf26f
fix(cbz): window-relative scroll geometry locks head boundary; default prefetch 2 when key absent
2026-09-08 15:15:42 +08:00
XingfenD
f63b639f64
feat(cbz): chapter-scoped continuous reading — lock scroll at chapter end, screen paging, prefetch next N chapters; drop 连读/整页/适高 modes
2026-09-08 15:01:28 +08:00
XingfenD
cd251b940c
feat(cbz): pure chapter-window helpers (chapterIndexAt/chapterWin) with table tests
2026-09-08 14:56:46 +08:00
XingfenD
bba82e5529
docs(plan): correct container names to podman compose underscores
2026-09-08 14:54:34 +08:00
XingfenD
497dc16604
fix(deploy): COPY paths in web Dockerfiles still referenced old web/ dir after web->frontend rename — dev image build failed
2026-09-08 14:53:29 +08:00
XingfenD
37ddff89a5
docs(cbz): chapter-scoped reading implementation plan — 3 tasks, virt helpers TDD first
2026-09-08 14:51:03 +08:00
XingfenD
a39ddf7b57
docs: add cbz chapter-scoped reading design spec
2026-09-08 14:45:15 +08:00
XingfenD
ec3f2c587e
feat(reader): remove admin delete button from reader header; shelf card hover remains the only delete entry
2026-09-08 13:08:46 +08:00
XingfenD
a43b73dcef
fix(cbz): attach resize observer via callback ref + drop vh from scroll-mode geometry deps — fixes constant per-page gaps and refetch storm on mobile
2026-09-08 13:05:58 +08:00
XingfenD
32b9d3a136
feat(ui): content-first shelf redesign — responsive cover grid, hover overlays, format badges, skeletons, sticky blurred top bar, brand login, SVG icon set, animated toasts
2026-09-08 13:05:40 +08:00
XingfenD
02ac3e5f7f
Merge branch 'feat/bookmarks'
2026-09-08 12:33:32 +08:00
XingfenD
40e9999e6a
chore(bookmarks): changelog + e2e verification (create/jump/patch/delete against live api, seek page serves real jpeg)
2026-09-08 12:32:36 +08:00
XingfenD
d989668650
feat(bookmarks): shared useBookmarks panel + wired into all four readers
2026-09-08 01:06:39 +08:00
XingfenD
b2c5c4a445
feat(bookmarks): client plumbing — saver capture + bookmark api
2026-09-08 01:04:44 +08:00
XingfenD
0fe3bc3057
feat(bookmarks): api+store — per-user CRUD, owner-scoped 404, percent-ordered list
2026-09-08 01:03:44 +08:00
XingfenD
e117ad52d3
docs(bookmarks): implementation plan — 4 tasks, backend vertical slice first, shared useBookmarks panel wired into all readers
2026-09-08 00:59:46 +08:00
XingfenD
928e52c604
docs(bookmarks): design spec — per-user bookmarks table, REST CRUD with owner-scoped 404s, capture/seek reuse of progress locators, shared sidebar component
2026-09-08 00:40:00 +08:00
XingfenD
aa18eb66eb
Merge branch 'feat/cbz-chapters'
2026-09-08 00:24:40 +08:00
XingfenD
66466ec8d1
Merge branch 'feat/chunked-upload'
2026-09-08 00:24:40 +08:00