2.9 KiB
2.9 KiB
name, description, metadata
| name | description | metadata | ||||||
|---|---|---|---|---|---|---|---|---|
| middle-click-autoscroll-4951 | Middle-click autoscroll in scrolled mode (#4951): Autoscroller RAF core + armed-books registry in iframeEventHandlers; scrolls via renderer.containerPosition |
|
Middle mouse button autoscroll for desktop Tauri apps in scrolled mode
(readest#4951), PR #4955 MERGED 2026-07-06 (merge 6f3b401c2). No settings
toggle: always on for desktop in scrolled mode (maintainer removed the toggle
as unnecessary; middle click has no other use in the reader). The same PR also
shipped a locale sync: 69 keys untranslated on main filled across 33 locales
(agents per language family; scanner-prunable keys preserved).
Key structure:
src/app/reader/utils/autoscroller.ts— pureAutoscrollerclass (RAF loop, 12px dead zone, 10 px/s per px linear velocity capped 4000, whole-pixel emission with fractional carry, held→sticky/drag state machine). Tested insrc/__tests__/reader/utils/autoscroller.test.tswith injected raf/now.useMiddleClickAutoscroll(bookKey, viewRef, containerRef)hook consumesiframe-mousedown/mouseup/mousemove/wheel/keydownmessages + window-level capture listeners; returns anchor (container-relative) forAutoscrollIndicator. Scrolls withrenderer.containerPosition += delta(public setter; native scroll path, so section preloading works). Axis fromrenderer.scrollProp('scrollLeft' = vertical writing → x axis; increasing scrollLeft always moves viewport right even in RTL, no special-casing).- iframeEventHandlers runs in the parent realm:
setAutoscrollArmed(bookKey)registry letshandleMousedownpreventDefault middle button (suppresses WebView2's native autoscroll on Windows, avoids double-drive) andhandleAuxclickswallow link opens;setAutoscrollTracking(bool)gates aniframe-mousemovepostMessage forwarder so it costs nothing when idle. - Pointer deltas use screenX/Y (same trick as useTouchEvent pinch) so iframe
coordinate spaces/transforms don't matter. Anchor window position computed in
the iframe handler via
event.view.frameElement.getBoundingClientRect()+ client-size scale, posted as windowX/windowY on button-1 mousedown only. - A left click that ends a sticky session must not also turn the page: the
hook consumes the later
iframe-single-clickviaeventDispatcher.onSyncwithin a 500ms window (usePagination checks dispatchSync consumption before paginating). - Setting
middleClickAutoscrollinBookLayout(default TRUE, user chose default-on), toggle in ControlPanel Scroll BoxedList, desktop only (appService?.isDesktopApp), disabled unless scrolled mode. Web excluded on purpose (browsers own middle click).
Related: i18n-extract-prunes-keys (followed its manual single-key insertion recipe for the 'Middle-Click Autoscroll' label across 33 locales).