fix(terminal): reconnect suppress next output

Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
fufesou
2026-04-29 20:11:11 +08:00
parent d5568d9188
commit b516dfb15b
4 changed files with 5 additions and 7 deletions

View File

@@ -58,8 +58,7 @@ class _TerminalPageState extends State<TerminalPage>
super.initState(); super.initState();
// Listen for tab selection changes to request focus // Listen for tab selection changes to request focus
_tabStateSubscription = _tabStateSubscription = widget.tabController.state.listen(_onTabStateChanged);
widget.tabController.state.listen(_onTabStateChanged);
// Use shared FFI instance from connection manager // Use shared FFI instance from connection manager
_ffi = TerminalConnectionManager.getConnection( _ffi = TerminalConnectionManager.getConnection(
@@ -146,9 +145,7 @@ class _TerminalPageState extends State<TerminalPage>
// Use post-frame callback to ensure widget is fully laid out in focus tree // Use post-frame callback to ensure widget is fully laid out in focus tree
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
// Re-check conditions after frame: mounted, focusable, still selected, not already focused // Re-check conditions after frame: mounted, focusable, still selected, not already focused
if (!mounted || if (!mounted || !_terminalFocusNode.canRequestFocus || _terminalFocusNode.hasFocus) return;
!_terminalFocusNode.canRequestFocus ||
_terminalFocusNode.hasFocus) return;
final state = widget.tabController.state.value; final state = widget.tabController.state.value;
if (state.selected >= 0 && state.selected < state.tabs.length) { if (state.selected >= 0 && state.selected < state.tabs.length) {
if (state.tabs[state.selected].key == widget.tabKey) { if (state.tabs[state.selected].key == widget.tabKey) {

View File

@@ -288,8 +288,7 @@ class TerminalModel with ChangeNotifier {
// On reconnect, the server may replay recent output. That replay can include // On reconnect, the server may replay recent output. That replay can include
// terminal queries like DSR/DA; xterm answers them through onOutput as // terminal queries like DSR/DA; xterm answers them through onOutput as
// "^[[1;1R^[[2;2R^[[>0;0;0c", which must not be sent back to the peer. // "^[[1;1R^[[2;2R^[[>0;0;0c", which must not be sent back to the peer.
_suppressNextTerminalDataOutput = _suppressNextTerminalDataOutput = evt['replay_in_next_data'] == true;
message == 'Reconnected to existing terminal with pending output';
// Fallback: if terminal view is not yet ready but already has valid // Fallback: if terminal view is not yet ready but already has valid
// dimensions (e.g. layout completed before open response arrived), // dimensions (e.g. layout completed before open response arrived),

View File

@@ -1135,6 +1135,7 @@ impl InvokeUiSession for FlutterHandler {
("message", json!(&opened.message)), ("message", json!(&opened.message)),
("pid", json!(opened.pid)), ("pid", json!(opened.pid)),
("service_id", json!(&opened.service_id)), ("service_id", json!(&opened.service_id)),
("replay_in_next_data", json!(opened.replay_in_next_data)),
]; ];
if !opened.persistent_sessions.is_empty() { if !opened.persistent_sessions.is_empty() {
event_data.push(("persistent_sessions", json!(opened.persistent_sessions))); event_data.push(("persistent_sessions", json!(opened.persistent_sessions)));

View File

@@ -1111,6 +1111,7 @@ impl TerminalServiceProxy {
} else { } else {
"Reconnected to existing terminal".to_string() "Reconnected to existing terminal".to_string()
}; };
opened.replay_in_next_data = has_pending;
opened.pid = session.pid; opened.pid = session.pid;
opened.service_id = self.service_id.clone(); opened.service_id = self.service_id.clone();
if service.needs_session_sync { if service.needs_session_sync {