Freeze backend terminal resize while editing

This commit is contained in:
sladro 2026-04-10 20:04:35 +08:00
parent b460957bcf
commit f3a4749053
3 changed files with 63 additions and 2 deletions

View File

@ -330,6 +330,7 @@ class _TerminalPageState extends ConsumerState<TerminalPage>
}
void _applyInputMode() {
_coordinator.setBackendResizeEnabled(_inputMode != _TerminalInputMode.edit);
_terminalFocusNode.canRequestFocus = _inputMode == _TerminalInputMode.edit;
if (_inputMode == _TerminalInputMode.edit) {
_terminalFocusNode.requestFocus();

View File

@ -87,11 +87,23 @@ class TerminalSessionCoordinator extends ChangeNotifier {
int? _lastSentColumns;
int? _lastSentRows;
int? _lastReceivedSequence;
bool _isBackendResizeEnabled = true;
bool get isLoadingOlderHistory => _isLoadingOlderHistory;
String get connectionStatus => _connectionStatus;
void setBackendResizeEnabled(bool enabled) {
if (_isBackendResizeEnabled == enabled) {
return;
}
_isBackendResizeEnabled = enabled;
if (enabled) {
_flushPendingResize();
}
}
Future<void> start({bool isReconnect = false}) async {
_cancelPendingReconnect();
_cancelPendingResize();
@ -521,13 +533,18 @@ class TerminalSessionCoordinator extends ChangeNotifier {
final socketSession = _socketSession;
final columns = _pendingResizeColumns;
final rows = _pendingResizeRows;
_pendingResizeColumns = null;
_pendingResizeRows = null;
if (socketSession == null || columns == null || rows == null) {
return;
}
if (!_isBackendResizeEnabled) {
return;
}
_pendingResizeColumns = null;
_pendingResizeRows = null;
if (_lastSentColumns == columns && _lastSentRows == rows) {
return;
}

View File

@ -500,6 +500,49 @@ void main() {
},
);
test(
'edit mode freezes backend resize until read mode resumes',
() async {
final controller = TerminalInteractionController();
final apiClient = _FakeAgentApiClient();
final sessionFactory = _FakeTerminalSessionFactory();
final resizeScheduler = _FakeResizeScheduler();
final session = Session(
sessionId: 'abc',
name: 'codex-main',
status: 'idle',
);
final coordinator = TerminalSessionCoordinator(
controller: controller,
apiClient: apiClient,
session: session,
sessionFactory: sessionFactory.create,
onFrame: (_) {},
onRestore: (_) {},
viewportProvider: () => const TerminalViewport(columns: 80, rows: 24),
resizeScheduler: resizeScheduler.schedule,
);
await coordinator.start();
final socketSession = sessionFactory.createdSessions.single;
coordinator.setBackendResizeEnabled(false);
coordinator.handleTerminalResize(98, 26);
resizeScheduler.runPending();
expect(socketSession.resizeCalls, const [
[80, 24],
]);
coordinator.setBackendResizeEnabled(true);
expect(socketSession.resizeCalls, const [
[80, 24],
[98, 26],
]);
},
);
test(
'frames from a replaced socket session are ignored after reconnect starts',
() async {