Reader settings per login session
Each sign-in keeps its own reader mode, zoom, page tone and skipping once it changes one; sessions that never changed follow the latest set, and a new sign-in starts from the session used last. Settings -> Reading shows every session's state, lets a session follow the latest again or become the latest, and turns the feature off for one shared set. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
03767d5704
commit
e3e57b60bd
9 files changed
+326
-27
No files matched your search
+26
-5
@@ -130,11 +130,14 @@ This keeps ids human-readable and derivable without a database. The price: renam
|
||||
"readingStory": true, // show private retrospective summaries when history exists
|
||||
"continueRow": true, // library: "Continue where you left off" row at the top
|
||||
"zoom": { "flow": 1, "page": 1.5, "book": 1, "strip": 0.8 }, // page zoom per mode
|
||||
"webhook": ""
|
||||
}
|
||||
"webhook": "",
|
||||
"readerPerSession": true // reader settings per login session (section 6.7)
|
||||
},
|
||||
"readerFrom": "3f9c…" // public id of the session the latest reader settings came from
|
||||
}
|
||||
},
|
||||
"sessions": { "<sha256 of token>": { "u": "admin", "t": 1790796794000 } },
|
||||
"sessions": { "<sha256 of token>": { "u": "admin", "t": 1790796794000, "seen": 1790796794000,
|
||||
"agent": "<User-Agent>", "reader": { …locked reader settings, only after a change… } } },
|
||||
"progress": { "admin": { "Moon Garden": { "1/2": {
|
||||
"v": "c0002 Roots [MangaDex]", // version read
|
||||
"p": 4, "n": 14, // page index in that version (all pages), page count
|
||||
@@ -177,7 +180,7 @@ This keeps ids human-readable and derivable without a database. The price: renam
|
||||
|
||||
| Path | Handling |
|
||||
|------|----------|
|
||||
| `/api/*` | `routes["<METHOD> <path>"]`. Handlers get `{ u, b, q, req, res }` and return an object, which is sent as JSON. Throwing `HttpError(code, message, extra)` sends `{ error, ...extra }` with that status (for example `nextAllowedAt` on a discovery `429`) |
|
||||
| `/api/*` | `routes["<METHOD> <path>"]`. Handlers get `{ u, b, q, req, res, sess, sk }` (`sess` = the login session record, `sk` its key) and return an object, which is sent as JSON. Throwing `HttpError(code, message, extra)` sends `{ error, ...extra }` with that status (for example `nextAllowedAt` on a discovery `429`) |
|
||||
| `/lib/*` | Image files from `LIBRARY`. Requires a session, allows image extensions only, and the path must resolve inside `LIBRARY`. `ETag` + `private, max-age=86400` |
|
||||
| everything else | Static files from `public/` (`/` → `index.html`). `ETag` + `no-cache` |
|
||||
|
||||
@@ -194,7 +197,9 @@ All requests and responses are JSON. POSTs require `Content-Type: application/js
|
||||
| `POST /api/login` `{name, password}` | public | Starts a session (cookie `sid`) |
|
||||
| `POST /api/logout` | user | Ends the session |
|
||||
| `GET /api/me` | user | Name, admin flag, settings, unread count |
|
||||
| `POST /api/settings` `{…partial}` | user | Validated update of the settings keys above |
|
||||
| `POST /api/settings` `{…partial}` | user | Validated update of the settings keys above; reader keys go to the current session (6.7) |
|
||||
| `GET /api/reader-sessions` | user | `{ enabled, current, latestFrom, latest, sessions: [{ id, device, created, seen, current, locked, reader }] }` |
|
||||
| `POST /api/reader-sessions` `{id, action}` | user | `follow`: the session drops its own reader settings and follows the latest; `latest`: its settings become the latest |
|
||||
| `POST /api/password` `{old, new}` | user | Change password |
|
||||
| `GET /api/library` | user | Manga list with covers, counts, the user's read count, unread notifications, last read, and optional personal Reading Story aggregates |
|
||||
| `GET /api/manga?m=` | user | Manga details, books, chapters with ranked versions, progress, optional chapter-time summaries, and `continue` target |
|
||||
@@ -269,6 +274,22 @@ The reader alone talks to AniList for discovery ([discovery.md](discovery.md)).
|
||||
(all reasons, strongest first) next to `reason`; seed evidence carries `fetchedAt`.
|
||||
- `DISCOVERY_ANILIST_URL` overrides the AniList endpoint (tests point it at a local fixture server).
|
||||
|
||||
### 6.7 Reader settings per session
|
||||
|
||||
The reader keys (`startMode`, `lastMode`, `adapt`, `skipExtras`, `skipCovers`, `flowPageGap`, `pageTone`, `zoom`)
|
||||
can differ per login session, so a phone and a desktop keep their own mode and zoom (`reader-sessions.js`):
|
||||
|
||||
- `user.settings` holds the **latest** reader set. A session without its own set follows it.
|
||||
- The first reader change in a session copies the latest set into `session.reader` with the change applied: the session
|
||||
is now **locked** and keeps that set whatever other sessions do. The change also becomes the latest set.
|
||||
- Loading a page (`GET /api/me`) from a locked session makes its set the latest again, so a new sign-in starts from the
|
||||
session used last. A new sign-in has no set of its own until it changes something.
|
||||
- Other settings (Reading Story, dates, discovery, webhook, …) stay per user.
|
||||
- `readerPerSession: false` (Settings → Reading) brings back one shared set: changes go to `user.settings` and apply to
|
||||
every session. Locked sets are kept and apply again when the switch is turned back on.
|
||||
|
||||
Settings → Reading → *Reader settings per session* lists the user's sessions (device from the User-Agent, sign-in and last
|
||||
activity, own or following) with "Follow latest again" and "Use for new sessions".
|
||||
## 7. Frontend
|
||||
|
||||
### 7.1 Pages
|
||||
|
||||
Reference in new issue
Block a user