Files
MangaCircus/docs/reading-insights-concept.md

245 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Reading Story concept
Status: first release implemented on 2026-10-04. The Active Reading Clock records the
underlying per-user, per-chapter measurements and MangaCircus now returns the compact
library, manga and chapter summaries described below. The bounded daily Reading Journal
remains a later phase.
Policy update 2026-10-06: a timed read now means a visit with at least 60% viewed
page coverage, not exhaustive 100% verification. No speed ceiling applies. Below-
threshold lookup visits do not enter these summaries; existing history is retained.
First/last durations continue growing until departure. See `reading-time-concept.md`.
## Product idea
Call the retrospective feature **Your Reading Story**. The Active Reading Clock is the
instrument visible while reading; Reading Story is the quiet, personal record it builds.
The feature should answer four pleasant questions:
1. How much time have I spent with this manga?
2. What did this chapter take me to read?
3. Where am I in the story, including partially timed chapters?
4. What does my reading habit look like over time?
It is not a productivity score. Do not rank users, award points for longer sessions, or
describe a reader as fast or slow. Those patterns would reward timer inflation and turn a
private leisure activity into a competition.
## Display language
Use **active time**, **reading time**, and **timed**. Never call it screen time or claim
that MangaCircus proved comprehension.
Durations are friendly rather than stopwatch-precise outside the live reader:
| Stored measurement | Display |
|---|---|
| no reading record | `Not timed` |
| 1–59 seconds | `Under a minute` |
| 60 seconds–59 minutes | rounded to the nearest minute, for example `7 min` |
| 1 hour or more | hours and minutes, for example `3 h 42 min` |
| incomplete current pass | `4 min active · in progress` |
| one completed pass | `6 min first read` |
| completed rereads | `5 min last read · 18 min total · 3 passes` |
Zero must not mean “read instantly.” A chapter with no record is **Not timed**, because
the setting may have been disabled or the chapter may have been marked read manually.
Loading wait and unqualified visit drafts remain diagnostic details; they are not mixed
into the headline reading duration.
## 1. Reader: the live clock
Keep the implemented bottom-toolbar clock as the immediate view:
```text
[ ⏱ 06:14 · Reading ]
```
Tapping it opens the detail panel. At 60% coverage show a gentle confirmation:
**Reading time is now counted · 60% of pages viewed**. Time continues accumulating;
this does not claim the entire chapter has been read or alter ordinary progress.
For subsequent qualifying visits say **Reread time is now counted**.
“Together” makes the lifetime number feel connected to the story rather than to work.
## 2. Manga page: Your Reading Story card
Place one card after the hero and before metadata. Hide it entirely when the user has no
timing records for this manga; do not show a large empty dashboard.
```text
┌ Your Reading Story ─────────────────────────────────────────┐
│ 3 h 42 min together 31 chapters timed 4 rereads │
│ Typical chapter 7 min Last read Ch. 45 · 18 min ago │
│ │
│ Reading rhythm │
│ 01 ▂▂▃▂▅▃▂ 02 ▃▄▂▂▃ 03 ▂▂▆▃▂ │
│ Each bar is one completed chapter; height is active time. │
└────────────────────────────────────────────────────────────┘
```
The headline values are:
- **time together:** sum of `totalActiveMs` for every chapter in this manga;
- **chapters timed:** chapters with any credible active time;
- **completed passes:** sum of completed passes, phrased as rereads only after subtracting
the first completed pass per chapter;
- **typical chapter:** median `lastCompleteMs` across completed chapters, never the mean;
- **last read:** chapter with the newest `updatedAt`.
The **Reading rhythm** is a compact chapter sequence, grouped by the existing volume
boundaries. It visualises only completed-pass duration. A gap means “not timed,” not zero.
Bars use a log-like capped scale so one very long chapter does not flatten the rest.
Hovering or tapping a bar reveals chapter number, title, last completed duration, lifetime
time and pass count. Selecting a volume with the existing filter also filters this rhythm.
On narrow screens, show the first four headline values in a two-column grid and make the
rhythm horizontally scrollable. The card is collapsible and remembers its state per user.
## 3. Chapter list: useful, quiet timing
Add the duration between the page count and chapter title, using a fixed-width column so
the current chapter-row alignment stays clean:
```text
Ch. 45 35 p. 7 min The Twin Swords ✓ read
Ch. 44 31 p. 4 min The Visitor ✓ read
Ch. 43 29 p. Not timed A Quiet Morning ✓ read
```
The compact column shows the last completed pass. An incomplete chapter shows its current
active time with a small hollow clock, such as `◷ 3 min`. A chapter with multiple passes
gets a subtle repeat marker: `7 min ↻2`. Its accessible label and tooltip expand this to
`Last read 7 minutes; 2 completed passes; 19 minutes total`.
Do not put lifetime time directly into every row; that makes reread chapters visually
noisy. Lifetime detail belongs in the tooltip/tap sheet and Reading Story card.
The chapter timing column is hidden when the clock setting is disabled. Existing history
is preserved and becomes visible again if the user re-enables the setting.
## 4. Library dashboard: one personal summary strip
Above the current filters and cover grid, show a compact strip only when at least one
chapter has been timed:
```text
Your Reading Story 18 h 26 min together · 146 chapters timed
Most time with Berserk · Continue your last chapter →
```
Add two optional library sorts:
- **Recently timed** — newest reading `updatedAt` first;
- **Time together** — manga with the largest personal active-time total first.
Do not put duration badges on every cover by default. They compete with new-chapter badges
and reading progress. A future `Show reading time on covers` preference may opt into a
small `3 h 42 min` line below the existing read count.
The first release should not claim “today,” “this week,” streaks, or a calendar. The
current compact database has totals and latest timestamps, but no honest time-series
history from which those values can be reconstructed.
## 5. Later: Reading Journal
If readers enjoy Reading Story, add bounded daily aggregates rather than raw activity
events:
```jsonc
"daily": {
"2026-10-04": { "activeMs": 2840000, "chapters": 6, "completedPasses": 5 }
}
```
Keep at most 400 daily buckets per user, folding older values into yearly totals. This
enables a private activity calendar, `this week`, `this year`, and “you returned to this
story after 3 months” without storing pointer movements, individual page timestamps or a
surveillance-style event log.
Recommended journal messages are descriptive, not judgemental:
- **A long evening with Berserk · 1 h 18 min**
- **You returned to Gantz after 42 days**
- **Volume 4 was your longest volume · 2 h 06 min**
- **12 chapters reread this year**
Avoid streak pressure, “goal missed,” speed comparisons, and global leaderboards.
## API and derived-data design
Keep the raw `reading` records private to their owner. Add derived summaries at the
existing authenticated boundaries:
### `GET /api/library`
Each manga may include:
```jsonc
"reading": {
"activeMs": 13320000,
"timedChapters": 31,
"completedChapters": 29,
"completedPasses": 35,
"rereads": 6,
"typicalChapterMs": 421000,
"lastChapterId": "3/45",
"updatedAt": 1791130200000
}
```
Also return a top-level personal total derived in the same pass. This avoids an extra
request and lets library sorting work locally like the existing filters.
### `GET /api/manga`
Return the manga aggregate plus a small public summary on each chapter:
```jsonc
"reading": {
"totalActiveMs": 1140000,
"lastCompleteMs": 421000,
"completedPasses": 2,
"currentPassMs": 0,
"currentPassComplete": true,
"updatedAt": 1791130200000
}
```
Do not send input-mode totals, rejected views or page ranges to the manga page. They are
reader diagnostics and would make the overview payload and interface unnecessarily noisy.
Derive all aggregates on the server from the compact records during these requests. The
library is small and JSON-backed; a second denormalised cache would create invalidation
work without a current need. If measurement proves this slow, cache by a monotonic
reading-data revision rather than writing duplicate totals into `db.json`.
## Controls, privacy and corrections
Under **Settings → Reading**, explain: “Reading Story is private to your account.” Add:
- **Show Reading Story** — controls retrospective UI separately from collecting the clock;
- **Forget one manga’s reading time** — available on that manga's card menu;
- **Delete all reading-time history** — destructive, confirmed with the account password;
- **Export my reading-time summary** — compact JSON, with no raw input events.
Turning off the Active Reading Clock stops collection but does not silently erase history.
The retrospective display setting may hide existing history without changing it. An admin
must not see another user’s Reading Story through the normal admin interface.
## Delivery status
Implemented:
1. Server-side summary helpers and tests for missing, partial, complete and reread records.
2. Manga-page card, volume-aware rhythm and aligned chapter-duration column.
3. Library summary strip and the two personal-time sorts.
4. User controls for hide, per-manga deletion, password-confirmed complete deletion and export.
5. A gentle reader completion message for first reads and rereads.
Deferred: observe real use before adding bounded daily aggregates and the Reading Journal.
This order immediately makes the existing measurements useful without changing the clock
protocol or committing MangaCircus to a larger analytics history.