diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index 2c1746bd1..eae3f1d69 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -49,10 +49,15 @@ enum MouseFocusScope { } class FileManagerPage extends StatefulWidget { - const FileManagerPage({Key? key, required this.id, this.forceRelay}) + const FileManagerPage( + {Key? key, + required this.id, + required this.tabController, + this.forceRelay}) : super(key: key); final String id; final bool? forceRelay; + final DesktopTabController tabController; @override State createState() => _FileManagerPageState(); @@ -85,6 +90,7 @@ class _FileManagerPageState extends State } debugPrint("File manager page init success with id ${widget.id}"); _ffi.dialogManager.setOverlayState(_overlayKeyState); + widget.tabController.onSelected?.call(widget.id); } @override diff --git a/flutter/lib/desktop/pages/file_manager_tab_page.dart b/flutter/lib/desktop/pages/file_manager_tab_page.dart index 2d1b75299..d41397833 100644 --- a/flutter/lib/desktop/pages/file_manager_tab_page.dart +++ b/flutter/lib/desktop/pages/file_manager_tab_page.dart @@ -31,7 +31,7 @@ class _FileManagerTabPageState extends State { _FileManagerTabPageState(Map params) { Get.put(DesktopTabController(tabType: DesktopTabType.fileTransfer)); - tabController.onSelected = (_, id) { + tabController.onSelected = (id) { WindowController.fromWindowId(windowId()) .setTitle(getWindowNameWithId(id)); }; @@ -44,6 +44,7 @@ class _FileManagerTabPageState extends State { page: FileManagerPage( key: ValueKey(params['id']), id: params['id'], + tabController: tabController, forceRelay: params['forceRelay'], ))); } @@ -71,6 +72,7 @@ class _FileManagerTabPageState extends State { page: FileManagerPage( key: ValueKey(id), id: id, + tabController: tabController, forceRelay: args['forceRelay'], ))); } else if (call.method == "onDestroy") { diff --git a/flutter/lib/desktop/pages/port_forward_page.dart b/flutter/lib/desktop/pages/port_forward_page.dart index bb4965b13..3a16ffbe1 100644 --- a/flutter/lib/desktop/pages/port_forward_page.dart +++ b/flutter/lib/desktop/pages/port_forward_page.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hbb/common.dart'; +import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart'; import 'package:flutter_hbb/models/model.dart'; import 'package:flutter_hbb/models/platform_model.dart'; import 'package:get/get.dart'; @@ -27,9 +28,14 @@ class _PortForward { class PortForwardPage extends StatefulWidget { const PortForwardPage( - {Key? key, required this.id, required this.isRDP, this.forceRelay}) + {Key? key, + required this.id, + required this.tabController, + required this.isRDP, + this.forceRelay}) : super(key: key); final String id; + final DesktopTabController tabController; final bool isRDP; final bool? forceRelay; @@ -58,6 +64,7 @@ class _PortForwardPageState extends State Wakelock.enable(); } debugPrint("Port forward page init success with id ${widget.id}"); + widget.tabController.onSelected?.call(widget.id); } @override diff --git a/flutter/lib/desktop/pages/port_forward_tab_page.dart b/flutter/lib/desktop/pages/port_forward_tab_page.dart index 65d6208fd..751fc696c 100644 --- a/flutter/lib/desktop/pages/port_forward_tab_page.dart +++ b/flutter/lib/desktop/pages/port_forward_tab_page.dart @@ -31,7 +31,7 @@ class _PortForwardTabPageState extends State { isRDP = params['isRDP']; tabController = Get.put(DesktopTabController(tabType: DesktopTabType.portForward)); - tabController.onSelected = (_, id) { + tabController.onSelected = (id) { WindowController.fromWindowId(windowId()) .setTitle(getWindowNameWithId(id)); }; @@ -43,6 +43,7 @@ class _PortForwardTabPageState extends State { page: PortForwardPage( key: ValueKey(params['id']), id: params['id'], + tabController: tabController, isRDP: isRDP, forceRelay: params['forceRelay'], ))); @@ -77,6 +78,7 @@ class _PortForwardTabPageState extends State { key: ValueKey(args['id']), id: id, isRDP: isRDP, + tabController: tabController, forceRelay: args['forceRelay'], ))); } else if (call.method == "onDestroy") { diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index ba2138deb..8259b53d0 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -24,6 +24,7 @@ import '../../common/shared_state.dart'; import '../../utils/image.dart'; import '../widgets/remote_toolbar.dart'; import '../widgets/kb_layout_type_chooser.dart'; +import '../widgets/tabbar_widget.dart'; final SimpleWrapper _firstEnterImage = SimpleWrapper(false); @@ -33,6 +34,7 @@ class RemotePage extends StatefulWidget { required this.id, required this.password, required this.menubarState, + required this.tabController, this.switchUuid, this.forceRelay, }) : super(key: key); @@ -43,6 +45,7 @@ class RemotePage extends StatefulWidget { final String? switchUuid; final bool? forceRelay; final SimpleWrapper?> _lastState = SimpleWrapper(null); + final DesktopTabController tabController; FFI get ffi => (_lastState.value! as _RemotePageState)._ffi; @@ -146,6 +149,7 @@ class _RemotePageState extends State // } _blockableOverlayState.applyFfi(_ffi); + widget.tabController.onSelected?.call(widget.id); } @override diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart index 154069405..587b2f7fd 100644 --- a/flutter/lib/desktop/pages/remote_tab_page.dart +++ b/flutter/lib/desktop/pages/remote_tab_page.dart @@ -55,12 +55,14 @@ class _ConnectionTabPageState extends State { final peerId = params['id']; if (peerId != null) { ConnectionTypeState.init(peerId); - tabController.onSelected = (_, id) { + tabController.onSelected = (id) { final remotePage = tabController.state.value.tabs - .firstWhere((tab) => tab.key == id) - .page as RemotePage; - final ffi = remotePage.ffi; - bind.setCurSessionId(sessionId: ffi.sessionId); + .firstWhereOrNull((tab) => tab.key == id) + ?.page; + if (remotePage is RemotePage) { + final ffi = remotePage.ffi; + bind.setCurSessionId(sessionId: ffi.sessionId); + } WindowController.fromWindowId(windowId()) .setTitle(getWindowNameWithId(id)); }; @@ -75,6 +77,7 @@ class _ConnectionTabPageState extends State { id: peerId, password: params['password'], menubarState: _menubarState, + tabController: tabController, switchUuid: params['switch_uuid'], forceRelay: params['forceRelay'], ), @@ -111,6 +114,7 @@ class _ConnectionTabPageState extends State { id: id, password: args['password'], menubarState: _menubarState, + tabController: tabController, switchUuid: switchUuid, forceRelay: args['forceRelay'], ), diff --git a/flutter/lib/desktop/pages/server_page.dart b/flutter/lib/desktop/pages/server_page.dart index ee86ed31f..cdcb04325 100644 --- a/flutter/lib/desktop/pages/server_page.dart +++ b/flutter/lib/desktop/pages/server_page.dart @@ -35,9 +35,6 @@ class _DesktopServerPageState extends State tabController.onRemoved = (_, id) { onRemoveId(id); }; - tabController.onSelected = (_, id) { - windowManager.setTitle(getWindowNameWithId(id)); - }; super.initState(); } @@ -100,8 +97,17 @@ class ConnectionManagerState extends State { @override void initState() { gFFI.serverModel.updateClientState(); - gFFI.serverModel.tabController.onSelected = (index, _) => - gFFI.chatModel.changeCurrentID(gFFI.serverModel.clients[index].id); + gFFI.serverModel.tabController.onSelected = (client_id_str) { + final client_id = int.tryParse(client_id_str); + if (client_id != null) { + gFFI.chatModel.changeCurrentID(client_id); + final client = + gFFI.serverModel.clients.firstWhereOrNull((e) => e.id == client_id); + if (client != null) { + windowManager.setTitle(getWindowNameWithId(client.peerId)); + } + } + }; gFFI.chatModel.isConnManager = true; super.initState(); } @@ -328,6 +334,7 @@ class _CmHeaderState extends State<_CmHeader> _time.value = _time.value + 1; } }); + gFFI.serverModel.tabController.onSelected?.call(client.id.toString()); } @override diff --git a/flutter/lib/desktop/widgets/tabbar_widget.dart b/flutter/lib/desktop/widgets/tabbar_widget.dart index d17b77285..a5bab6fb4 100644 --- a/flutter/lib/desktop/widgets/tabbar_widget.dart +++ b/flutter/lib/desktop/widgets/tabbar_widget.dart @@ -17,7 +17,6 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; import 'package:get/get_rx/src/rx_workers/utils/debouncer.dart'; import 'package:scroll_pos/scroll_pos.dart'; -import 'package:uuid/uuid.dart'; import 'package:window_manager/window_manager.dart'; import '../../utils/multi_window_manager.dart'; @@ -28,7 +27,7 @@ const double _kDividerIndent = 10; const double _kActionIconSize = 12; class TabInfo { - final String key; + final String key; // Notice: cm use client_id.toString() as key final String label; final IconData? selectedIcon; final IconData? unselectedIcon; @@ -97,7 +96,7 @@ class DesktopTabController { /// index, key Function(int, String)? onRemoved; - Function(int, String)? onSelected; + Function(String)? onSelected; DesktopTabController( {required this.tabType, this.onRemoved, this.onSelected}); @@ -119,7 +118,8 @@ class DesktopTabController { assert(toIndex >= 0); } try { - jumpTo(toIndex); + // tabPage has not been initialized, call `onSelected` at the end of initState + jumpTo(toIndex, callOnSelected: false); } catch (e) { // call before binding controller will throw debugPrint("Failed to jumpTo: $e"); @@ -144,7 +144,9 @@ class DesktopTabController { onRemoved?.call(index, key); } - void jumpTo(int index) { + /// For addTab, tabPage has not been initialized, set [callOnSelected] to false, + /// and call [onSelected] at the end of initState + void jumpTo(int index, {bool callOnSelected = true}) { if (!isDesktop || index < 0) return; state.update((val) { val!.selected = index; @@ -160,18 +162,14 @@ class DesktopTabController { } })); }); - if (state.value.tabs.length > index) { - final key = state.value.tabs[index].key; - onSelected?.call(index, key); + if (callOnSelected) { + if (state.value.tabs.length > index) { + final key = state.value.tabs[index].key; + onSelected?.call(key); + } } } - void jumpBy(String key) { - if (!isDesktop) return; - final index = state.value.tabs.indexWhere((tab) => tab.key == key); - jumpTo(index); - } - void closeBy(String? key) { if (!isDesktop) return; assert(onRemoved != null);