feat(reader): Auto Scroll reading mode for scrolled flow (#4998) (#4999)

Teleprompter-style continuous scrolling toggled from the View menu
(Shift+A), available only in scrolled mode. A PacedScroller drives
whole-pixel forward steps at a constant, user-adjustable velocity;
the speed (25-500 percent, persisted as autoScrollSpeed) is tuned
from a floating control pill that also offers pause/resume and exit,
and fades away while scrolling to keep the mode immersive.

Tapping the page pauses and resumes instead of turning pages or
toggling the bars; manual wheel or drag input simply composes with
the paced scrolling. Escape or leaving scrolled mode ends the
session. When forward progress stalls the session hops to the next
section (single-section scroll mode) or stops with a toast at the
end of the book. Vertical-writing books scroll along the horizontal
axis with the sign convention foliate uses for scrolled offsets.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Huang Xin
2026-07-08 00:45:02 +09:00
committed by GitHub
parent 17de9357dd
commit f8ad47a418
46 changed files with 926 additions and 33 deletions
@@ -123,6 +123,11 @@ const ViewMenu: React.FC<ViewMenuProps> = ({
eventDispatcher.dispatch('rsvp-start', { bookKey });
};
const toggleAutoScroll = () => {
setIsDropdownOpen?.(false);
eventDispatcher.dispatch('autoscroll-toggle', { bookKey });
};
const handleShare = () => {
setIsDropdownOpen?.(false);
if (!bookData?.book) return;
@@ -382,6 +387,14 @@ const ViewMenu: React.FC<ViewMenuProps> = ({
onClick={toggleScrolledMode}
/>
<MenuItem
label={_('Auto Scroll')}
shortcut='Shift+A'
Icon={viewState?.autoScrollEnabled ? MdCheck : undefined}
onClick={toggleAutoScroll}
disabled={!isScrolledMode}
/>
<hr aria-hidden='true' className='border-base-300 my-1' />
<MenuItem