fix(tui): pause/resume stdin subscription around external editor

io.stdin is a single-subscription stream — calling listen() a second time
after cancel() throws 'Stream has already been listened to'. Use
keySub.pause() before launching the editor and keySub.resume() after
it exits instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Chris Hendrickson 2026-04-25 14:22:09 -04:00
parent 5c3d00e2a4
commit eeed3fdba0

View file

@ -302,9 +302,7 @@ class TuiCommand extends DewCommand {
} }
// Key stream raw bytes converted to Key values without blocking. // Key stream raw bytes converted to Key values without blocking.
// Declared as var so it can be cancelled and re-created around external editor. final keySub = io.stdin.listen((bytes) {
StreamSubscription<List<int>> keySub;
keySub = io.stdin.listen((bytes) {
for (final key in _parseKeys(bytes)) { for (final key in _parseKeys(bytes)) {
if (!events.isClosed) events.add(_TuiKey(key)); if (!events.isClosed) events.add(_TuiKey(key));
} }
@ -649,7 +647,7 @@ class TuiCommand extends DewCommand {
'${io.Directory.systemTemp.path}/dew_edit_${es.ticket.id}.md', '${io.Directory.systemTemp.path}/dew_edit_${es.ticket.id}.md',
); );
await tmpFile.writeAsString(es.body); await tmpFile.writeAsString(es.body);
await keySub.cancel(); keySub.pause();
console.rawMode = false; console.rawMode = false;
console.showCursor(); console.showCursor();
console.clearScreen(); console.clearScreen();
@ -661,13 +659,9 @@ class TuiCommand extends DewCommand {
await proc.exitCode; await proc.exitCode;
es.body = await tmpFile.readAsString(); es.body = await tmpFile.readAsString();
await tmpFile.delete(); await tmpFile.delete();
keySub = io.stdin.listen((bytes) {
for (final key in _parseKeys(bytes)) {
if (!events.isClosed) events.add(_TuiKey(key));
}
});
console.rawMode = true; console.rawMode = true;
console.hideCursor(); console.hideCursor();
keySub.resume();
default: default:
break; break;
} }