diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index fb389b45e646..4e97449124f7 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -2730,30 +2730,6 @@ Future osxRequestAudio() async { return await kMacOSPermChannel.invokeMethod("requestRecordAudio"); } -class DraggableNeverScrollableScrollPhysics extends ScrollPhysics { - /// Creates scroll physics that does not let the user scroll. - const DraggableNeverScrollableScrollPhysics({super.parent}); - - @override - DraggableNeverScrollableScrollPhysics applyTo(ScrollPhysics? ancestor) { - return DraggableNeverScrollableScrollPhysics(parent: buildParent(ancestor)); - } - - @override - bool shouldAcceptUserOffset(ScrollMetrics position) { - // TODO: find a better solution to check if the offset change is caused by the scrollbar. - // Workaround: when dragging with the scrollbar, it always triggers an [IdleScrollActivity]. - if (position is ScrollPositionWithSingleContext) { - // ignore: invalid_use_of_protected_member, invalid_use_of_visible_for_testing_member - return position.activity is IdleScrollActivity; - } - return false; - } - - @override - bool get allowImplicitScrolling => false; -} - Widget futureBuilder( {required Future? future, required Widget Function(dynamic data) hasData}) { return FutureBuilder( diff --git a/flutter/lib/common/widgets/peers_view.dart b/flutter/lib/common/widgets/peers_view.dart index e14e198bd105..3e34f882d1de 100644 --- a/flutter/lib/common/widgets/peers_view.dart +++ b/flutter/lib/common/widgets/peers_view.dart @@ -5,7 +5,6 @@ import 'package:dynamic_layouts/dynamic_layouts.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hbb/consts.dart'; -import 'package:flutter_hbb/desktop/widgets/scroll_wrapper.dart'; import 'package:flutter_hbb/models/ab_model.dart'; import 'package:flutter_hbb/models/peer_tab_model.dart'; import 'package:flutter_hbb/models/state_model.dart'; @@ -271,33 +270,24 @@ class _PeersViewState extends State<_PeersView> }, ) : peerCardUiType.value == PeerUiType.list - ? DesktopScrollWrapper( - scrollController: _scrollController, - child: ListView.builder( - controller: _scrollController, - physics: DraggableNeverScrollableScrollPhysics(), - itemCount: peers.length, - itemBuilder: (BuildContext context, int index) { - return buildOnePeer(peers[index], false) - .marginOnly( - right: space, - top: index == 0 ? 0 : space / 2, - bottom: space / 2); - }), + ? ListView.builder( + controller: _scrollController, + itemCount: peers.length, + itemBuilder: (BuildContext context, int index) { + return buildOnePeer(peers[index], false).marginOnly( + right: space, + top: index == 0 ? 0 : space / 2, + bottom: space / 2); + }, ) - : DesktopScrollWrapper( - scrollController: _scrollController, - child: DynamicGridView.builder( - controller: _scrollController, - physics: DraggableNeverScrollableScrollPhysics(), - gridDelegate: SliverGridDelegateWithWrapping( - mainAxisSpacing: space / 2, - crossAxisSpacing: space), - itemCount: peers.length, - itemBuilder: (BuildContext context, int index) { - return buildOnePeer(peers[index], false); - }), - )); + : DynamicGridView.builder( + gridDelegate: SliverGridDelegateWithWrapping( + mainAxisSpacing: space / 2, + crossAxisSpacing: space), + itemCount: peers.length, + itemBuilder: (BuildContext context, int index) { + return buildOnePeer(peers[index], false); + })); if (updateEvent == UpdateEvent.load) { _curPeers.clear(); diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index c313958bddfc..f6f9c4d34f9a 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -244,10 +244,6 @@ const double kDesktopIconButtonSplashRadius = 20; /// [kMinCursorSize] indicates min cursor (w, h) const int kMinCursorSize = 12; -/// [kDefaultScrollAmountMultiplier] indicates how many rows can be scrolled after a minimum scroll action of mouse -const kDefaultScrollAmountMultiplier = 5.0; -const kDefaultScrollDuration = Duration(milliseconds: 50); -const kDefaultMouseWheelThrottleDuration = Duration(milliseconds: 50); const kFullScreenEdgeSize = 0.0; const kMaximizeEdgeSize = 0.0; // Do not use kWindowResizeEdgeSize directly. Use `windowResizeEdgeSize` in `common.dart` instead. diff --git a/flutter/lib/desktop/pages/desktop_home_page.dart b/flutter/lib/desktop/pages/desktop_home_page.dart index 9728d6b478e2..04a186b84c63 100644 --- a/flutter/lib/desktop/pages/desktop_home_page.dart +++ b/flutter/lib/desktop/pages/desktop_home_page.dart @@ -12,7 +12,6 @@ import 'package:flutter_hbb/consts.dart'; import 'package:flutter_hbb/desktop/pages/connection_page.dart'; import 'package:flutter_hbb/desktop/pages/desktop_setting_page.dart'; import 'package:flutter_hbb/desktop/pages/desktop_tab_page.dart'; -import 'package:flutter_hbb/desktop/widgets/scroll_wrapper.dart'; import 'package:flutter_hbb/models/platform_model.dart'; import 'package:flutter_hbb/models/server_model.dart'; import 'package:flutter_hbb/plugin/ui_manager.dart'; @@ -125,47 +124,43 @@ class _DesktopHomePageState extends State child: Container( width: isIncomingOnly ? 280.0 : 200.0, color: Theme.of(context).colorScheme.background, - child: DesktopScrollWrapper( - scrollController: _leftPaneScrollController, - child: Stack( - children: [ - SingleChildScrollView( - controller: _leftPaneScrollController, - physics: DraggableNeverScrollableScrollPhysics(), - child: Column( - key: _childKey, - children: children, - ), + child: Stack( + children: [ + SingleChildScrollView( + controller: _leftPaneScrollController, + child: Column( + key: _childKey, + children: children, ), - if (isOutgoingOnly) - Positioned( - bottom: 6, - left: 12, - child: Align( - alignment: Alignment.centerLeft, - child: InkWell( - child: Obx( - () => Icon( - Icons.settings, - color: _editHover.value - ? textColor - : Colors.grey.withOpacity(0.5), - size: 22, - ), + ), + if (isOutgoingOnly) + Positioned( + bottom: 6, + left: 12, + child: Align( + alignment: Alignment.centerLeft, + child: InkWell( + child: Obx( + () => Icon( + Icons.settings, + color: _editHover.value + ? textColor + : Colors.grey.withOpacity(0.5), + size: 22, ), - onTap: () => { - if (DesktopSettingPage.tabKeys.isNotEmpty) - { - DesktopSettingPage.switch2page( - DesktopSettingPage.tabKeys[0]) - } - }, - onHover: (value) => _editHover.value = value, ), + onTap: () => { + if (DesktopSettingPage.tabKeys.isNotEmpty) + { + DesktopSettingPage.switch2page( + DesktopSettingPage.tabKeys[0]) + } + }, + onHover: (value) => _editHover.value = value, ), - ) - ], - ), + ), + ) + ], ), ), ); diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index 69100470f0ea..0c7586e7036c 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -19,7 +19,6 @@ import 'package:get/get.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher_string.dart'; -import 'package:flutter_hbb/desktop/widgets/scroll_wrapper.dart'; import '../../common/widgets/dialog.dart'; import '../../common/widgets/login.dart'; @@ -226,13 +225,11 @@ class _DesktopSettingPageState extends State Expanded( child: Container( color: Theme.of(context).scaffoldBackgroundColor, - child: DesktopScrollWrapper( - scrollController: controller, - child: PageView( - controller: controller, - physics: NeverScrollableScrollPhysics(), - children: _children(), - )), + child: PageView( + controller: controller, + physics: NeverScrollableScrollPhysics(), + children: _children(), + ), ), ) ], @@ -281,13 +278,10 @@ class _DesktopSettingPageState extends State Widget _listView({required List<_TabInfo> tabs}) { final scrollController = ScrollController(); - return DesktopScrollWrapper( - scrollController: scrollController, - child: ListView( - physics: DraggableNeverScrollableScrollPhysics(), - controller: scrollController, - children: tabs.map((tab) => _listItem(tab: tab)).toList(), - )); + return ListView( + controller: scrollController, + children: tabs.map((tab) => _listItem(tab: tab)).toList(), + ); } Widget _listItem({required _TabInfo tab}) { @@ -349,22 +343,19 @@ class _GeneralState extends State<_General> { @override Widget build(BuildContext context) { final scrollController = ScrollController(); - return DesktopScrollWrapper( - scrollController: scrollController, - child: ListView( - physics: DraggableNeverScrollableScrollPhysics(), - controller: scrollController, - children: [ - if (!isWeb) service(), - theme(), - _Card(title: 'Language', children: [language()]), - if (!isWeb) hwcodec(), - if (!isWeb) audio(context), - if (!isWeb) record(context), - if (!isWeb) WaylandCard(), - other() - ], - ).marginOnly(bottom: _kListViewBottomMargin)); + return ListView( + controller: scrollController, + children: [ + if (!isWeb) service(), + theme(), + _Card(title: 'Language', children: [language()]), + if (!isWeb) hwcodec(), + if (!isWeb) audio(context), + if (!isWeb) record(context), + if (!isWeb) WaylandCard(), + other() + ], + ).marginOnly(bottom: _kListViewBottomMargin); } Widget theme() { @@ -705,29 +696,26 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin { @override Widget build(BuildContext context) { super.build(context); - return DesktopScrollWrapper( - scrollController: scrollController, - child: SingleChildScrollView( - physics: DraggableNeverScrollableScrollPhysics(), - controller: scrollController, - child: Column( - children: [ - _lock(locked, 'Unlock Security Settings', () { - locked = false; - setState(() => {}); - }), - AbsorbPointer( - absorbing: locked, - child: Column(children: [ - permissions(context), - password(context), - _Card(title: '2FA', children: [tfa()]), - _Card(title: 'ID', children: [changeId()]), - more(context), - ]), - ), - ], - )).marginOnly(bottom: _kListViewBottomMargin)); + return SingleChildScrollView( + controller: scrollController, + child: Column( + children: [ + _lock(locked, 'Unlock Security Settings', () { + locked = false; + setState(() => {}); + }), + AbsorbPointer( + absorbing: locked, + child: Column(children: [ + permissions(context), + password(context), + _Card(title: '2FA', children: [tfa()]), + _Card(title: 'ID', children: [changeId()]), + more(context), + ]), + ), + ], + )).marginOnly(bottom: _kListViewBottomMargin); } Widget tfa() { @@ -1384,28 +1372,23 @@ class _NetworkState extends State<_Network> with AutomaticKeepAliveClientMixin { // TODO: support web proxy final hideProxy = isWeb || bind.mainGetBuildinOption(key: kOptionHideProxySetting) == 'Y'; - return DesktopScrollWrapper( - scrollController: scrollController, - child: ListView( - controller: scrollController, - physics: DraggableNeverScrollableScrollPhysics(), - children: [ - _lock(locked, 'Unlock Network Settings', () { - locked = false; - setState(() => {}); - }), - AbsorbPointer( - absorbing: locked, - child: Column(children: [ - if (!hideServer) server(enabled), - if (!hideProxy) - _Card(title: 'Proxy', children: [ - _Button('Socks5/Http(s) Proxy', changeSocks5Proxy, - enabled: enabled), - ]), - ]), - ), - ]).marginOnly(bottom: _kListViewBottomMargin)); + return ListView(controller: scrollController, children: [ + _lock(locked, 'Unlock Network Settings', () { + locked = false; + setState(() => {}); + }), + AbsorbPointer( + absorbing: locked, + child: Column(children: [ + if (!hideServer) server(enabled), + if (!hideProxy) + _Card(title: 'Proxy', children: [ + _Button('Socks5/Http(s) Proxy', changeSocks5Proxy, + enabled: enabled), + ]), + ]), + ), + ]).marginOnly(bottom: _kListViewBottomMargin); } server(bool enabled) { @@ -1494,19 +1477,14 @@ class _DisplayState extends State<_Display> { @override Widget build(BuildContext context) { final scrollController = ScrollController(); - return DesktopScrollWrapper( - scrollController: scrollController, - child: ListView( - controller: scrollController, - physics: DraggableNeverScrollableScrollPhysics(), - children: [ - viewStyle(context), - scrollStyle(context), - imageQuality(context), - codec(context), - if (!isWeb) privacyModeImpl(context), - other(context), - ]).marginOnly(bottom: _kListViewBottomMargin)); + return ListView(controller: scrollController, children: [ + viewStyle(context), + scrollStyle(context), + imageQuality(context), + codec(context), + if (!isWeb) privacyModeImpl(context), + other(context), + ]).marginOnly(bottom: _kListViewBottomMargin); } Widget viewStyle(BuildContext context) { @@ -1729,15 +1707,12 @@ class _AccountState extends State<_Account> { @override Widget build(BuildContext context) { final scrollController = ScrollController(); - return DesktopScrollWrapper( - scrollController: scrollController, - child: ListView( - physics: DraggableNeverScrollableScrollPhysics(), - controller: scrollController, - children: [ - _Card(title: 'Account', children: [accountAction(), useInfo()]), - ], - ).marginOnly(bottom: _kListViewBottomMargin)); + return ListView( + controller: scrollController, + children: [ + _Card(title: 'Account', children: [accountAction(), useInfo()]), + ], + ).marginOnly(bottom: _kListViewBottomMargin); } Widget accountAction() { @@ -1834,18 +1809,14 @@ class _PluginState extends State<_Plugin> { Widget build(BuildContext context) { bind.pluginListReload(); final scrollController = ScrollController(); - return DesktopScrollWrapper( - scrollController: scrollController, - child: ChangeNotifierProvider.value( - value: pluginManager, - child: Consumer(builder: (context, model, child) { - return ListView( - physics: DraggableNeverScrollableScrollPhysics(), - controller: scrollController, - children: model.plugins.map((entry) => pluginCard(entry)).toList(), - ).marginOnly(bottom: _kListViewBottomMargin); - }), - ), + return ChangeNotifierProvider.value( + value: pluginManager, + child: Consumer(builder: (context, model, child) { + return ListView( + controller: scrollController, + children: model.plugins.map((entry) => pluginCard(entry)).toList(), + ).marginOnly(bottom: _kListViewBottomMargin); + }), ); } @@ -1897,75 +1868,72 @@ class _AboutState extends State<_About> { final fingerprint = data['fingerprint'].toString(); const linkStyle = TextStyle(decoration: TextDecoration.underline); final scrollController = ScrollController(); - return DesktopScrollWrapper( - scrollController: scrollController, - child: SingleChildScrollView( - controller: scrollController, - physics: DraggableNeverScrollableScrollPhysics(), - child: _Card(title: translate('About RustDesk'), children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox( - height: 8.0, - ), - SelectionArea( - child: Text('${translate('Version')}: $version') - .marginSymmetric(vertical: 4.0)), - SelectionArea( - child: Text('${translate('Build Date')}: $buildDate') - .marginSymmetric(vertical: 4.0)), - if (!isWeb) - SelectionArea( - child: Text('${translate('Fingerprint')}: $fingerprint') - .marginSymmetric(vertical: 4.0)), - InkWell( - onTap: () { - launchUrlString('https://rustdesk.com/privacy.html'); - }, - child: Text( - translate('Privacy Statement'), - style: linkStyle, - ).marginSymmetric(vertical: 4.0)), - InkWell( - onTap: () { - launchUrlString('https://rustdesk.com'); - }, - child: Text( - translate('Website'), - style: linkStyle, - ).marginSymmetric(vertical: 4.0)), - Container( - decoration: const BoxDecoration(color: Color(0xFF2c8cff)), - padding: - const EdgeInsets.symmetric(vertical: 24, horizontal: 8), - child: SelectionArea( - child: Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Copyright © ${DateTime.now().toString().substring(0, 4)} Purslane Ltd.\n$license', - style: const TextStyle(color: Colors.white), - ), - Text( - translate('Slogan_tip'), - style: TextStyle( - fontWeight: FontWeight.w800, - color: Colors.white), - ) - ], + return SingleChildScrollView( + controller: scrollController, + child: _Card(title: translate('About RustDesk'), children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox( + height: 8.0, + ), + SelectionArea( + child: Text('${translate('Version')}: $version') + .marginSymmetric(vertical: 4.0)), + SelectionArea( + child: Text('${translate('Build Date')}: $buildDate') + .marginSymmetric(vertical: 4.0)), + if (!isWeb) + SelectionArea( + child: Text('${translate('Fingerprint')}: $fingerprint') + .marginSymmetric(vertical: 4.0)), + InkWell( + onTap: () { + launchUrlString('https://rustdesk.com/privacy.html'); + }, + child: Text( + translate('Privacy Statement'), + style: linkStyle, + ).marginSymmetric(vertical: 4.0)), + InkWell( + onTap: () { + launchUrlString('https://rustdesk.com'); + }, + child: Text( + translate('Website'), + style: linkStyle, + ).marginSymmetric(vertical: 4.0)), + Container( + decoration: const BoxDecoration(color: Color(0xFF2c8cff)), + padding: + const EdgeInsets.symmetric(vertical: 24, horizontal: 8), + child: SelectionArea( + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Copyright © ${DateTime.now().toString().substring(0, 4)} Purslane Ltd.\n$license', + style: const TextStyle(color: Colors.white), ), - ), - ], - )), - ).marginSymmetric(vertical: 4.0) - ], - ).marginOnly(left: _kContentHMargin) - ]), - )); + Text( + translate('Slogan_tip'), + style: TextStyle( + fontWeight: FontWeight.w800, + color: Colors.white), + ) + ], + ), + ), + ], + )), + ).marginSymmetric(vertical: 4.0) + ], + ).marginOnly(left: _kContentHMargin) + ]), + ); }); } } diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index cca2074a242c..912b06b0282b 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -6,7 +6,6 @@ import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:provider/provider.dart'; import 'package:wakelock_plus/wakelock_plus.dart'; -import 'package:flutter_improved_scrolling/flutter_improved_scrolling.dart'; import 'package:flutter_hbb/models/state_model.dart'; import '../../consts.dart'; @@ -742,12 +741,6 @@ class _ImagePaintState extends State { ScrollController horizontal, ScrollController vertical, ) { - final scrollConfig = CustomMouseWheelScrollConfig( - scrollDuration: kDefaultScrollDuration, - scrollCurve: Curves.linearToEaseOut, - mouseWheelTurnsThrottleTimeMs: - kDefaultMouseWheelThrottleDuration.inMilliseconds, - scrollAmountMultiplier: kDefaultScrollAmountMultiplier); var widget = child; if (layoutSize.width < size.width) { widget = ScrollConfiguration( @@ -793,36 +786,26 @@ class _ImagePaintState extends State { ); } if (layoutSize.width < size.width) { - widget = ImprovedScrolling( - scrollController: horizontal, - enableCustomMouseWheelScrolling: cursorOverImage.isFalse, - customMouseWheelScrollConfig: scrollConfig, - child: RawScrollbar( - thickness: kScrollbarThickness, - thumbColor: Colors.grey, - controller: horizontal, - thumbVisibility: false, - trackVisibility: false, - notificationPredicate: layoutSize.height < size.height - ? (notification) => notification.depth == 1 - : defaultScrollNotificationPredicate, - child: widget, - ), + widget = RawScrollbar( + thickness: kScrollbarThickness, + thumbColor: Colors.grey, + controller: horizontal, + thumbVisibility: false, + trackVisibility: false, + notificationPredicate: layoutSize.height < size.height + ? (notification) => notification.depth == 1 + : defaultScrollNotificationPredicate, + child: widget, ); } if (layoutSize.height < size.height) { - widget = ImprovedScrolling( - scrollController: vertical, - enableCustomMouseWheelScrolling: cursorOverImage.isFalse, - customMouseWheelScrollConfig: scrollConfig, - child: RawScrollbar( - thickness: kScrollbarThickness, - thumbColor: Colors.grey, - controller: vertical, - thumbVisibility: false, - trackVisibility: false, - child: widget, - ), + widget = RawScrollbar( + thickness: kScrollbarThickness, + thumbColor: Colors.grey, + controller: vertical, + thumbVisibility: false, + trackVisibility: false, + child: widget, ); } diff --git a/flutter/lib/desktop/widgets/scroll_wrapper.dart b/flutter/lib/desktop/widgets/scroll_wrapper.dart deleted file mode 100644 index c5bc3394b439..000000000000 --- a/flutter/lib/desktop/widgets/scroll_wrapper.dart +++ /dev/null @@ -1,27 +0,0 @@ -import 'package:flutter/widgets.dart'; -import 'package:flutter_hbb/consts.dart'; -import 'package:flutter_improved_scrolling/flutter_improved_scrolling.dart'; - -class DesktopScrollWrapper extends StatelessWidget { - final ScrollController scrollController; - final Widget child; - const DesktopScrollWrapper( - {Key? key, required this.scrollController, required this.child}) - : super(key: key); - - @override - Widget build(BuildContext context) { - return ImprovedScrolling( - scrollController: scrollController, - enableCustomMouseWheelScrolling: true, - // enableKeyboardScrolling: true, // strange behavior on mac - customMouseWheelScrollConfig: CustomMouseWheelScrollConfig( - scrollDuration: kDefaultScrollDuration, - scrollCurve: Curves.linearToEaseOut, - mouseWheelTurnsThrottleTimeMs: - kDefaultMouseWheelThrottleDuration.inMilliseconds, - scrollAmountMultiplier: kDefaultScrollAmountMultiplier), - child: child, - ); - } -} diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock index 31f04ce4076d..98f3eef96353 100644 --- a/flutter/pubspec.lock +++ b/flutter/pubspec.lock @@ -530,15 +530,6 @@ packages: url: "https://github.com/rustdesk-org/flutter_gpu_texture_renderer" source: git version: "0.0.1" - flutter_improved_scrolling: - dependency: "direct main" - description: - path: "." - ref: HEAD - resolved-ref: "62f09545149f320616467c306c8c5f71714a18e6" - url: "https://github.com/rustdesk-org/flutter_improved_scrolling" - source: git - version: "0.0.3" flutter_keyboard_visibility: dependency: "direct main" description: diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index bec58a4d6ced..3a4f46b2a36f 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -71,13 +71,6 @@ dependencies: debounce_throttle: ^2.0.0 file_picker: ^5.1.0 flutter_svg: ^2.0.5 - flutter_improved_scrolling: - # currently, we use flutter 3.10.0+. - # - # for flutter 3.0.5, please use official version(just comment code below). - # if build rustdesk by flutter >=3.3, please use our custom pub below (uncomment code below). - git: - url: https://github.com/rustdesk-org/flutter_improved_scrolling uni_links: git: url: https://github.com/rustdesk-org/uni_links