From 59f3060a047203a011d77b6925b8c9c24d41f08f Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 28 Apr 2026 18:40:28 +0800 Subject: [PATCH] fix(terminal): dialog, close window Signed-off-by: fufesou --- flutter/lib/common.dart | 5 +++++ flutter/lib/desktop/pages/terminal_page.dart | 8 ++++++-- flutter/lib/desktop/pages/terminal_tab_page.dart | 6 ++++++ flutter/lib/desktop/widgets/tabbar_widget.dart | 1 + flutter/lib/models/terminal_model.dart | 6 +++--- 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index e579db36a..5eb88399f 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -716,6 +716,11 @@ closeConnection({String? id}) { stateGlobal.isInMainPage = true; } else { final controller = Get.find(); + if (controller.tabType == DesktopTabType.terminal && + controller.onCloseWindow != null) { + controller.onCloseWindow!(); + return; + } controller.closeBy(id); } } diff --git a/flutter/lib/desktop/pages/terminal_page.dart b/flutter/lib/desktop/pages/terminal_page.dart index a885eb011..7c6bb9814 100644 --- a/flutter/lib/desktop/pages/terminal_page.dart +++ b/flutter/lib/desktop/pages/terminal_page.dart @@ -27,6 +27,7 @@ class TerminalPage extends StatefulWidget { final bool? isSharedPassword; final String? connToken; final int terminalId; + /// Tab key for focus management, passed from parent to avoid duplicate construction final String tabKey; final SimpleWrapper?> _lastState = SimpleWrapper(null); @@ -57,7 +58,8 @@ class _TerminalPageState extends State super.initState(); // Listen for tab selection changes to request focus - _tabStateSubscription = widget.tabController.state.listen(_onTabStateChanged); + _tabStateSubscription = + widget.tabController.state.listen(_onTabStateChanged); // Use shared FFI instance from connection manager _ffi = TerminalConnectionManager.getConnection( @@ -144,7 +146,9 @@ class _TerminalPageState extends State // Use post-frame callback to ensure widget is fully laid out in focus tree WidgetsBinding.instance.addPostFrameCallback((_) { // Re-check conditions after frame: mounted, focusable, still selected, not already focused - if (!mounted || !_terminalFocusNode.canRequestFocus || _terminalFocusNode.hasFocus) return; + if (!mounted || + !_terminalFocusNode.canRequestFocus || + _terminalFocusNode.hasFocus) return; final state = widget.tabController.state.value; if (state.selected >= 0 && state.selected < state.tabs.length) { if (state.tabs[state.selected].key == widget.tabKey) { diff --git a/flutter/lib/desktop/pages/terminal_tab_page.dart b/flutter/lib/desktop/pages/terminal_tab_page.dart index ab64c1a12..8b9ade2de 100644 --- a/flutter/lib/desktop/pages/terminal_tab_page.dart +++ b/flutter/lib/desktop/pages/terminal_tab_page.dart @@ -46,6 +46,7 @@ class _TerminalTabPageState extends State { .setTitle(getWindowNameWithId(id)); }; tabController.onRemoved = (_, id) => onRemoveId(id); + tabController.onCloseWindow = _closeWindowFromConnection; final terminalId = params['terminalId'] ?? _nextTerminalId++; tabController.add(_createTerminalTab( peerId: params['id'], @@ -561,6 +562,11 @@ class _TerminalTabPageState extends State { } } + Future _closeWindowFromConnection() async { + await _closeAllTabs(); + await WindowController.fromWindowId(windowId()).close(); + } + int windowId() { return widget.params["windowId"]; } diff --git a/flutter/lib/desktop/widgets/tabbar_widget.dart b/flutter/lib/desktop/widgets/tabbar_widget.dart index ac7d80017..ef195b493 100644 --- a/flutter/lib/desktop/widgets/tabbar_widget.dart +++ b/flutter/lib/desktop/widgets/tabbar_widget.dart @@ -99,6 +99,7 @@ class DesktopTabController { /// index, key Function(int, String)? onRemoved; Function(String)? onSelected; + Future Function()? onCloseWindow; DesktopTabController( {required this.tabType, this.onRemoved, this.onSelected}); diff --git a/flutter/lib/models/terminal_model.dart b/flutter/lib/models/terminal_model.dart index 830d872dc..bcf14bde2 100644 --- a/flutter/lib/models/terminal_model.dart +++ b/flutter/lib/models/terminal_model.dart @@ -309,9 +309,9 @@ class TerminalModel with ChangeNotifier { final persistentSessions = (evt['persistent_sessions'] as List? ?? []) - .whereType() - .where((id) => !parent.terminalModels.containsKey(id)) - .toList(); + .whereType() + .where((id) => !parent.terminalModels.containsKey(id)) + .toList(); if (kWindowId != null && persistentSessions.isNotEmpty) { DesktopMultiWindow.invokeMethod( kWindowId!,