245 lines
10 KiB
Markdown
245 lines
10 KiB
Markdown
# 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.
|