From 79a1f888d6518f64363217cdc5cee683a4bb12d4 Mon Sep 17 00:00:00 2001 From: dignow <136106582+dignow@users.noreply.github.com> Date: Wed, 24 Jul 2024 14:00:49 +0800 Subject: [PATCH] fix: flutter remove setState in initState (#8807) Signed-off-by: dignow --- flutter/lib/common/widgets/peer_tab_page.dart | 26 +++++++++++++------ .../lib/desktop/pages/file_manager_page.dart | 5 +++- .../lib/desktop/pages/port_forward_page.dart | 5 +++- flutter/lib/desktop/pages/remote_page.dart | 17 +++++++----- flutter/lib/desktop/pages/server_page.dart | 13 +++++++--- flutter/lib/desktop/widgets/popup_menu.dart | 6 +++++ .../lib/desktop/widgets/remote_toolbar.dart | 6 +++-- .../lib/desktop/widgets/tabbar_widget.dart | 6 +++-- flutter/lib/mobile/pages/connection_page.dart | 4 +-- flutter/lib/mobile/pages/remote_page.dart | 6 +++-- flutter/lib/mobile/pages/settings_page.dart | 4 +-- src/virtual_display_manager.rs | 2 +- 12 files changed, 69 insertions(+), 31 deletions(-) diff --git a/flutter/lib/common/widgets/peer_tab_page.dart b/flutter/lib/common/widgets/peer_tab_page.dart index 3b92ab1eb..66fba2312 100644 --- a/flutter/lib/common/widgets/peer_tab_page.dart +++ b/flutter/lib/common/widgets/peer_tab_page.dart @@ -78,6 +78,13 @@ class _PeerTabPageState extends State @override void initState() { + WidgetsBinding.instance.addPostFrameCallback((_) { + _loadLocalOptions(); + }); + super.initState(); + } + + Future _loadLocalOptions() async { final uiType = bind.getLocalFlutterOption(k: kOptionPeerCardUiType); if (uiType != '') { peerCardUiType.value = int.parse(uiType) == 0 @@ -88,7 +95,6 @@ class _PeerTabPageState extends State } hideAbTagsPanel.value = bind.mainGetLocalOption(key: kOptionHideAbTagsPanel) == 'Y'; - super.initState(); } Future handleTabSelection(int tabIndex) async { @@ -875,18 +881,22 @@ class _PeerSortDropdownState extends State { @override void initState() { if (!PeerSortType.values.contains(peerSort.value)) { - Future.delayed(Duration.zero, () { - // do not change obx directly in initState, so do in future. - peerSort.value = PeerSortType.remoteId; - bind.setLocalFlutterOption( - k: kOptionPeerSorting, - v: peerSort.value, - ); + // do not change obx directly in initState, so do in future. + WidgetsBinding.instance.addPostFrameCallback((_) { + _loadLocalOptions(); }); } super.initState(); } + Future _loadLocalOptions() async { + peerSort.value = PeerSortType.remoteId; + bind.setLocalFlutterOption( + k: kOptionPeerSorting, + v: peerSort.value, + ); + } + @override Widget build(BuildContext context) { final style = TextStyle( diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index 29ab0f806..3b4428f99 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -98,7 +98,10 @@ class _FileManagerPageState extends State } debugPrint("File manager page init success with id ${widget.id}"); _ffi.dialogManager.setOverlayState(_overlayKeyState); - widget.tabController.onSelected?.call(widget.id); + // Call onSelected in post frame callback, since we cannot guarantee that the callback will not call setState. + WidgetsBinding.instance.addPostFrameCallback((_) { + widget.tabController.onSelected?.call(widget.id); + }); } @override diff --git a/flutter/lib/desktop/pages/port_forward_page.dart b/flutter/lib/desktop/pages/port_forward_page.dart index 99f8df340..5541cb8b3 100644 --- a/flutter/lib/desktop/pages/port_forward_page.dart +++ b/flutter/lib/desktop/pages/port_forward_page.dart @@ -65,7 +65,10 @@ class _PortForwardPageState extends State isRdp: widget.isRDP); Get.put(_ffi, tag: 'pf_${widget.id}'); debugPrint("Port forward page init success with id ${widget.id}"); - widget.tabController.onSelected?.call(widget.id); + // Call onSelected in post frame callback, since we cannot guarantee that the callback will not call setState. + WidgetsBinding.instance.addPostFrameCallback((_) { + widget.tabController.onSelected?.call(widget.id); + }); } @override diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index f108f7444..08656a4df 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -135,11 +135,13 @@ class _RemotePageState extends State if (!isWeb) bind.pluginSyncUi(syncTo: kAppTypeDesktopRemote); _ffi.qualityMonitorModel.checkShowQualityMonitor(sessionId); _ffi.dialogManager.loadMobileActionsOverlayVisible(); - // Session option should be set after models.dart/FFI.start - _showRemoteCursor.value = bind.sessionGetToggleOptionSync( - sessionId: sessionId, arg: 'show-remote-cursor'); - _zoomCursor.value = bind.sessionGetToggleOptionSync( - sessionId: sessionId, arg: kOptionZoomCursor); + WidgetsBinding.instance.addPostFrameCallback((_) { + // Session option should be set after models.dart/FFI.start + _showRemoteCursor.value = bind.sessionGetToggleOptionSync( + sessionId: sessionId, arg: 'show-remote-cursor'); + _zoomCursor.value = bind.sessionGetToggleOptionSync( + sessionId: sessionId, arg: kOptionZoomCursor); + }); DesktopMultiWindow.addListener(this); // if (!_isCustomCursorInited) { // customCursorController.registerNeedUpdateCursorCallback( @@ -154,7 +156,10 @@ class _RemotePageState extends State // } _blockableOverlayState.applyFfi(_ffi); - widget.tabController?.onSelected?.call(widget.id); + // Call onSelected in post frame callback, since we cannot guarantee that the callback will not call setState. + WidgetsBinding.instance.addPostFrameCallback((_) { + widget.tabController?.onSelected?.call(widget.id); + }); } @override diff --git a/flutter/lib/desktop/pages/server_page.dart b/flutter/lib/desktop/pages/server_page.dart index 1cac2706e..9701ca409 100644 --- a/flutter/lib/desktop/pages/server_page.dart +++ b/flutter/lib/desktop/pages/server_page.dart @@ -129,7 +129,7 @@ class ConnectionManagerState extends State if (client != null) { gFFI.chatModel.changeCurrentKey(MessageKey(client.peerId, client.id)); if (client.unreadChatMessageCount.value > 0) { - Future.delayed(Duration.zero, () { + WidgetsBinding.instance.addPostFrameCallback((_) { client.unreadChatMessageCount.value = 0; gFFI.chatModel.showChatPage(MessageKey(client.peerId, client.id)); }); @@ -399,7 +399,10 @@ class _CmHeaderState extends State<_CmHeader> _time.value = _time.value + 1; } }); - gFFI.serverModel.tabController.onSelected?.call(client.id.toString()); + // Call onSelected in post frame callback, since we cannot guarantee that the callback will not call setState. + WidgetsBinding.instance.addPostFrameCallback((_) { + gFFI.serverModel.tabController.onSelected?.call(client.id.toString()); + }); } @override @@ -732,7 +735,8 @@ class _CmControlPanel extends StatelessWidget { child: buildButton(context, color: MyTheme.accent, onClick: null, onTapDown: (details) async { - final devicesInfo = await AudioInput.getDevicesInfo(true, true); + final devicesInfo = + await AudioInput.getDevicesInfo(true, true); List devices = devicesInfo['devices'] as List; if (devices.isEmpty) { msgBox( @@ -764,7 +768,8 @@ class _CmControlPanel extends StatelessWidget { value: d, groupValue: currentDevice, onChanged: (v) { - if (v != null) AudioInput.setDevice(v, true, true); + if (v != null) + AudioInput.setDevice(v, true, true); }, child: Container( child: Text( diff --git a/flutter/lib/desktop/widgets/popup_menu.dart b/flutter/lib/desktop/widgets/popup_menu.dart index 7d8f7c78c..003979a70 100644 --- a/flutter/lib/desktop/widgets/popup_menu.dart +++ b/flutter/lib/desktop/widgets/popup_menu.dart @@ -48,6 +48,12 @@ class MyPopupMenuItemState> @override void initState() { super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + _initEnabled(); + }); + } + + Future _initEnabled() async { if (widget.enabled != null) { enabled.value = widget.enabled!.value; } diff --git a/flutter/lib/desktop/widgets/remote_toolbar.dart b/flutter/lib/desktop/widgets/remote_toolbar.dart index 9db65e072..cfc52c777 100644 --- a/flutter/lib/desktop/widgets/remote_toolbar.dart +++ b/flutter/lib/desktop/widgets/remote_toolbar.dart @@ -372,7 +372,7 @@ class _RemoteToolbarState extends State { initState() { super.initState(); - Future.delayed(Duration.zero, () async { + WidgetsBinding.instance.addPostFrameCallback((_) async { _fractionX.value = double.tryParse(await bind.sessionGetOption( sessionId: widget.ffi.sessionId, arg: 'remote-menubar-drag-x') ?? @@ -1278,7 +1278,9 @@ class _ResolutionsMenuState extends State<_ResolutionsMenu> { @override void initState() { super.initState(); - _getLocalResolutionWayland(); + WidgetsBinding.instance.addPostFrameCallback((_) { + _getLocalResolutionWayland(); + }); } Rect? scaledRect() { diff --git a/flutter/lib/desktop/widgets/tabbar_widget.dart b/flutter/lib/desktop/widgets/tabbar_widget.dart index 513441113..a19ce105b 100644 --- a/flutter/lib/desktop/widgets/tabbar_widget.dart +++ b/flutter/lib/desktop/widgets/tabbar_widget.dart @@ -1271,12 +1271,14 @@ class ActionIcon extends StatefulWidget { } class _ActionIconState extends State { - var hover = false.obs; + final hover = false.obs; @override void initState() { super.initState(); - hover.value = false; + WidgetsBinding.instance.addPostFrameCallback((_) { + hover.value = false; + }); } @override diff --git a/flutter/lib/mobile/pages/connection_page.dart b/flutter/lib/mobile/pages/connection_page.dart index 4a2bb8b55..914fdec34 100644 --- a/flutter/lib/mobile/pages/connection_page.dart +++ b/flutter/lib/mobile/pages/connection_page.dart @@ -55,14 +55,14 @@ class _ConnectionPageState extends State { super.initState(); if (!isWeb) _uniLinksSubscription = listenUniLinks(); if (_idController.text.isEmpty) { - () async { + WidgetsBinding.instance.addPostFrameCallback((_) async { final lastRemoteId = await bind.mainGetLastRemoteId(); if (lastRemoteId != _idController.id) { setState(() { _idController.id = lastRemoteId; }); } - }(); + }); } if (isAndroid) { if (!bind.isCustomClient()) { diff --git a/flutter/lib/mobile/pages/remote_page.dart b/flutter/lib/mobile/pages/remote_page.dart index 30598085f..3b962a1c3 100644 --- a/flutter/lib/mobile/pages/remote_page.dart +++ b/flutter/lib/mobile/pages/remote_page.dart @@ -83,9 +83,11 @@ class _RemotePageState extends State { initSharedStates(widget.id); gFFI.chatModel .changeCurrentKey(MessageKey(widget.id, ChatModel.clientModeID)); - gFFI.chatModel.voiceCallStatus.value = VoiceCallStatus.notStarted; + WidgetsBinding.instance.addPostFrameCallback((_) { + gFFI.chatModel.voiceCallStatus.value = VoiceCallStatus.notStarted; + gFFI.dialogManager.loadMobileActionsOverlayVisible(); + }); _blockableOverlayState.applyFfi(gFFI); - gFFI.dialogManager.loadMobileActionsOverlayVisible(); } @override diff --git a/flutter/lib/mobile/pages/settings_page.dart b/flutter/lib/mobile/pages/settings_page.dart index dd95c4275..72e48c6f5 100644 --- a/flutter/lib/mobile/pages/settings_page.dart +++ b/flutter/lib/mobile/pages/settings_page.dart @@ -118,7 +118,7 @@ class _SettingsState extends State with WidgetsBindingObserver { _hideNetwork = bind.mainGetBuildinOption(key: kOptionHideNetworkSetting) == 'Y'; - () async { + WidgetsBinding.instance.addPostFrameCallback((_) async { var update = false; if (_hasIgnoreBattery) { @@ -177,7 +177,7 @@ class _SettingsState extends State with WidgetsBindingObserver { if (update) { setState(() {}); } - }(); + }); } @override diff --git a/src/virtual_display_manager.rs b/src/virtual_display_manager.rs index af5eda973..7807bd3d5 100644 --- a/src/virtual_display_manager.rs +++ b/src/virtual_display_manager.rs @@ -2,7 +2,7 @@ use hbb_common::{bail, platform::windows::is_windows_version_or_greater, ResultT use std::sync::atomic; // This string is defined here. -// https://github.com/rustdesk/RustDeskIddDriver/blob/b370aad3f50028b039aad211df60c8051c4a64d6/RustDeskIddDriver/RustDeskIddDriver.inf#LL73C1-L73C40 +// https://github.com/rustdesk-org/RustDeskIddDriver/blob/b370aad3f50028b039aad211df60c8051c4a64d6/RustDeskIddDriver/RustDeskIddDriver.inf#LL73C1-L73C40 pub const RUSTDESK_IDD_DEVICE_STRING: &'static str = "RustDeskIddDriver Device\0"; pub const AMYUNI_IDD_DEVICE_STRING: &'static str = "USB Mobile Monitor Virtual Display\0";