Moments: per-user saved pages and regions with one category (BL-0055)

Reader: bookmark button and M save the page (Flow: page at the reading
line, Book: the spread) with an optional dragged region, exactly one
category (Twist, Hot, Awesome, Cute, Funny, Feels) and a note. I now
toggles the bars; ? lists all keys. Keys dispatch through public/keys.js,
which also feeds the new Settings -> Keyboard shortcuts section.

Manga page: "Your moments" strip of crops (story or recent order,
category filters), viewer with step, full page, edit, delete and
"Open in reader" (read.html ...&p=). Moments point at pages by file
name and show "page moved" when the file is gone. Private per user.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
MaashkinoozheandClaude Opus 5.5 committed 2026-10-27 12:30:24 +01:00
1 parent 41e7ed063e
commit 74842c59e0
15 files changed
+734 -18

No files matched your search

+35
View File
@@ -0,0 +1,35 @@
'use strict';
/*
* Keyboard shortcuts. The reader dispatches keys through READER_KEYS, and Settings and the reader's "?" list
* are drawn from the same tables, so the documentation cannot drift from what the keys do.
*/
const READER_KEYS = [
{ keys: ['ArrowLeft', 'ArrowRight'], label: '← →', action: 'turn', text: 'Previous / next page, following the reading direction' },
{ keys: [' ', 'PageDown'], label: 'Space · Page Down', action: 'forward', text: 'Next page (Shift + Space: previous) · Page and Book mode' },
{ keys: ['PageUp'], label: 'Page Up', action: 'back', text: 'Previous page · Page and Book mode' },
{ keys: ['+', '='], label: '+', action: 'zoomIn', text: 'Zoom in 5 %' },
{ keys: ['-'], label: '−', action: 'zoomOut', text: 'Zoom out 5 %' },
{ keys: ['0'], label: '0', action: 'zoomFit', text: 'Fit the screen (100 %)' },
{ keys: ['m', 'M'], label: 'M', action: 'moment', text: 'Save a moment of the page you are on' },
{ keys: ['i', 'I'], label: 'I', action: 'bars', text: 'Show or hide the controls' },
{ keys: ['Escape'], label: 'Esc', action: 'bars', text: 'Show or hide the controls (closes an open dialog first)' },
{ keys: ['f', 'F'], label: 'F', action: 'fullscreen', text: 'Fullscreen' },
{ keys: ['?'], label: '?', action: 'help', text: 'Show these shortcuts' },
];
const MOMENT_VIEWER_KEYS = [
{ keys: ['ArrowLeft', 'ArrowRight'], label: '← →', action: 'step', text: 'Previous / next moment' },
{ keys: ['Escape'], label: 'Esc', action: 'close', text: 'Close the viewer' },
];
const KEY_GROUPS = [
{ title: 'Reader', keys: READER_KEYS },
{ title: 'Moments viewer (manga page)', keys: MOMENT_VIEWER_KEYS },
];
const keyAction = (table, key) => (table.find(entry => entry.keys.includes(key)) || {}).action || null;
function keyTable(groups = KEY_GROUPS) {
return groups.map(group => h('section', { class: 'key-group' }, h('h3', {}, group.title),
h('table', { class: 'key-table' }, h('tbody', {}, group.keys.map(entry =>
h('tr', {}, h('td', {}, h('kbd', {}, entry.label)), h('td', {}, entry.text)))))));
}
if (typeof module !== 'undefined') module.exports = { READER_KEYS, MOMENT_VIEWER_KEYS, KEY_GROUPS, keyAction };