From d308c2ac608782395366af1ab8c6be116750e377 Mon Sep 17 00:00:00 2001 From: nyne Date: Sun, 24 Aug 2025 19:52:24 +0800 Subject: [PATCH] Add mouse scroll speed setting. Close #471 --- assets/translation.json | 6 ++-- lib/foundation/appdata.dart | 1 + lib/pages/reader/images.dart | 55 ++++++++++++++++++++++++---------- lib/pages/settings/reader.dart | 15 ++++++++++ 4 files changed, 60 insertions(+), 17 deletions(-) diff --git a/assets/translation.json b/assets/translation.json index e922c71..acad614 100644 --- a/assets/translation.json +++ b/assets/translation.json @@ -410,7 +410,8 @@ "Clear specific reader settings for all comics": "清除所有漫画的特殊阅读设置", "Clear specific reader settings for this comic": "清除该漫画的特殊阅读设置", "Enable comic specific settings": "启用此漫画特定设置", - "Ignore Certificate Errors": "忽略证书错误" + "Ignore Certificate Errors": "忽略证书错误", + "Mouse scroll speed": "鼠标滚动速度" }, "zh_TW": { "Home": "首頁", @@ -823,6 +824,7 @@ "Clear specific reader settings for all comics": "清除所有漫畫的特殊閱讀設定", "Clear specific reader settings for this comic": "清除該漫畫的特殊閱讀設定", "Enable comic specific settings": "啟用此漫畫特定設定", - "Ignore Certificate Errors": "忽略證書錯誤" + "Ignore Certificate Errors": "忽略證書錯誤", + "Mouse scroll speed": "滑鼠滾動速度" } } \ No newline at end of file diff --git a/lib/foundation/appdata.dart b/lib/foundation/appdata.dart index 0afcf5b..1b18abf 100644 --- a/lib/foundation/appdata.dart +++ b/lib/foundation/appdata.dart @@ -191,6 +191,7 @@ class Settings with ChangeNotifier { 'showSystemStatusBar': false, 'comicSpecificSettings': >{}, 'ignoreBadCertificate': false, + 'readerScrollSpeed': 1.0, // 0.5 - 3.0 }; operator [](String key) { diff --git a/lib/pages/reader/images.dart b/lib/pages/reader/images.dart index 2ac90f3..b034884 100644 --- a/lib/pages/reader/images.dart +++ b/lib/pages/reader/images.dart @@ -638,27 +638,52 @@ class _ContinuousModeState extends State<_ContinuousMode> cacheImages(page); } - double? futurePosition; + double? _futurePosition; void smoothTo(double offset) { - futurePosition ??= scrollController.offset; - if (futurePosition! > scrollController.position.maxScrollExtent && - offset > 0) { - return; - } else if (futurePosition! < scrollController.position.minScrollExtent && - offset < 0) { + if (HardwareKeyboard.instance.isShiftPressed) { return; } - futurePosition = futurePosition! + offset * 1.2; - futurePosition = futurePosition!.clamp( + var currentLocation = scrollController.position.pixels; + var old = _futurePosition; + _futurePosition ??= currentLocation; + double k = (_futurePosition! - currentLocation).abs() / 1600 + 1; + final customSpeed = appdata.settings.getReaderSetting( + context.reader.cid, + context.reader.type.sourceKey, + "readerScrollSpeed", + ); + if (customSpeed is num) { + k *= customSpeed; + } + _futurePosition = _futurePosition! + offset * k; + var beforeOffset = (_futurePosition! - currentLocation).abs(); + _futurePosition = _futurePosition!.clamp( scrollController.position.minScrollExtent, scrollController.position.maxScrollExtent, ); - scrollController.animateTo( - futurePosition!, - duration: const Duration(milliseconds: 200), + var afterOffset = (_futurePosition! - currentLocation).abs(); + if (_futurePosition == old) return; + var target = _futurePosition!; + var duration = const Duration(milliseconds: 160); + if (afterOffset < beforeOffset) { + duration = duration * (afterOffset / beforeOffset); + if (duration < Duration(milliseconds: 10)) { + duration = Duration(milliseconds: 10); + } + } + scrollController + .animateTo( + _futurePosition!, + duration: duration, curve: Curves.linear, - ); + ) + .then((_) { + var current = scrollController.position.pixels; + if (current == target && current == _futurePosition) { + _futurePosition = null; + } + }); } void onPointerSignal(PointerSignalEvent event) { @@ -787,7 +812,7 @@ class _ContinuousModeState extends State<_ContinuousMode> disableScroll = true; }); } - futurePosition = null; + _futurePosition = null; if (_isMouseScrolling) { setState(() { _isMouseScrolling = false; @@ -1009,7 +1034,7 @@ class _ContinuousModeState extends State<_ContinuousMode> @override void toPage(int page) { itemScrollController.jumpTo(index: page); - futurePosition = null; + _futurePosition = null; } @override diff --git a/lib/pages/settings/reader.dart b/lib/pages/settings/reader.dart index df036c2..6cb739f 100644 --- a/lib/pages/settings/reader.dart +++ b/lib/pages/settings/reader.dart @@ -177,6 +177,21 @@ class _ReaderSettingsState extends State { comicSource: isEnabledSpecificSettings ? widget.comicSource : null, ), ), + SliverAnimatedVisibility( + visible: appdata.settings['readerMode']!.startsWith('continuous'), + child: _SliderSetting( + title: "Mouse scroll speed".tl, + settingsIndex: "readerScrollSpeed", + interval: 0.1, + min: 0.5, + max: 3, + onChanged: () { + widget.onChanged?.call("readerScrollSpeed"); + }, + comicId: isEnabledSpecificSettings ? widget.comicId : null, + comicSource: isEnabledSpecificSettings ? widget.comicSource : null, + ), + ), _SwitchSetting( title: 'Double tap to zoom'.tl, settingKey: 'enableDoubleTapToZoom',