diff --git a/packages/flutter_tools/lib/executable.dart b/packages/flutter_tools/lib/executable.dart index 26907596cf5..0938e64977a 100644 --- a/packages/flutter_tools/lib/executable.dart +++ b/packages/flutter_tools/lib/executable.dart @@ -136,6 +136,7 @@ Future main(List args) async { // So that we don't animate anything before calling applyFeatureFlags, default // the animations to disabled in real apps. defaultCliAnimationEnabled: false, + shutdownHooks: globals.shutdownHooks, ); // runner.run calls "terminal.applyFeatureFlags()" }, diff --git a/packages/flutter_tools/lib/src/base/terminal.dart b/packages/flutter_tools/lib/src/base/terminal.dart index 7443bd0f86e..4edce499576 100644 --- a/packages/flutter_tools/lib/src/base/terminal.dart +++ b/packages/flutter_tools/lib/src/base/terminal.dart @@ -7,6 +7,7 @@ import '../features.dart'; import 'io.dart' as io; import 'logger.dart'; import 'platform.dart'; +import 'process.dart'; enum TerminalColor { red, @@ -164,11 +165,14 @@ class AnsiTerminal implements Terminal { required Platform platform, DateTime? now, // Time used to determine preferredStyle. Defaults to 0001-01-01 00:00. bool defaultCliAnimationEnabled = true, + ShutdownHooks? shutdownHooks, }) : _stdio = stdio, _platform = platform, _now = now ?? DateTime(1), - _isCliAnimationEnabled = defaultCliAnimationEnabled; + _isCliAnimationEnabled = defaultCliAnimationEnabled { + shutdownHooks?.addShutdownHook(() { singleCharMode = false; }); + } final io.Stdio _stdio; final Platform _platform; @@ -319,7 +323,7 @@ class AnsiTerminal implements Terminal { return false; } final io.Stdin stdin = _stdio.stdin as io.Stdin; - return stdin.lineMode && stdin.echoMode; + return !stdin.lineMode && !stdin.echoMode; } @override set singleCharMode(bool value) { diff --git a/packages/flutter_tools/lib/src/globals.dart b/packages/flutter_tools/lib/src/globals.dart index bb39d9b14d2..7dd00897d64 100644 --- a/packages/flutter_tools/lib/src/globals.dart +++ b/packages/flutter_tools/lib/src/globals.dart @@ -243,6 +243,7 @@ final AnsiTerminal _defaultAnsiTerminal = AnsiTerminal( stdio: stdio, platform: platform, now: DateTime.now(), + shutdownHooks: shutdownHooks, ); /// The global Stdio wrapper. diff --git a/packages/flutter_tools/test/general.shard/base/terminal_test.dart b/packages/flutter_tools/test/general.shard/base/terminal_test.dart index 5810a582907..0e921dea111 100644 --- a/packages/flutter_tools/test/general.shard/base/terminal_test.dart +++ b/packages/flutter_tools/test/general.shard/base/terminal_test.dart @@ -5,6 +5,7 @@ import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/platform.dart'; +import 'package:flutter_tools/src/base/process.dart'; import 'package:flutter_tools/src/base/terminal.dart'; import 'package:test/fake.dart'; @@ -264,6 +265,18 @@ void main() { ); terminal.singleCharMode = true; }); + + testWithoutContext('singleCharMode is reset by shutdown hook', () { + final ShutdownHooks shutdownHooks = ShutdownHooks(); + final FakeStdio stdio = FakeStdio(); + final AnsiTerminal terminal = AnsiTerminal(stdio: stdio, platform: const LocalPlatform(), shutdownHooks: shutdownHooks); + stdio.stdinHasTerminal = true; + stdio._stdin = FakeStdin(); + + terminal.singleCharMode = true; + shutdownHooks.runShutdownHooks(BufferLogger.test()); + expect(terminal.singleCharMode, false); + }); } late Stream mockStdInStream;