Hide "Disconnected" overlay if DevTools is reconnected to a VM (#2099) * Hide "Disconnected" overlay if DevTools is reconnected to a VM * Add subscription to autoDispose
diff --git a/packages/devtools_app/lib/src/initializer.dart b/packages/devtools_app/lib/src/initializer.dart index 6063282..e69a6c7 100644 --- a/packages/devtools_app/lib/src/initializer.dart +++ b/packages/devtools_app/lib/src/initializer.dart
@@ -60,6 +60,9 @@ bool _dependenciesLoaded = false; + OverlayEntry currentDisconnectedOverlay; + StreamSubscription<bool> disconnectedOverlayReconnectSubscription; + @override void initState() { super.initState(); @@ -113,16 +116,30 @@ /// Shows a "disconnected" overlay if the [service.serviceManager] is not currently connected. void _handleNoConnection() { WidgetsBinding.instance.addPostFrameCallback((_) { - if (!_checkLoaded() && ModalRoute.of(context).isCurrent) { + if (!_checkLoaded() && + ModalRoute.of(context).isCurrent && + currentDisconnectedOverlay == null) { Overlay.of(context).insert(_createDisconnectedOverlay()); + + // Set up a subscription to hide the overlay if we become reconnected. + disconnectedOverlayReconnectSubscription = serviceManager.onStateChange + .where((connected) => connected) + .listen((_) => hideDisconnectedOverlay()); + autoDispose(disconnectedOverlayReconnectSubscription); } }); } + void hideDisconnectedOverlay() { + currentDisconnectedOverlay?.remove(); + currentDisconnectedOverlay = null; + disconnectedOverlayReconnectSubscription?.cancel(); + disconnectedOverlayReconnectSubscription = null; + } + OverlayEntry _createDisconnectedOverlay() { final theme = Theme.of(context); - OverlayEntry overlay; - overlay = OverlayEntry( + currentDisconnectedOverlay = OverlayEntry( builder: (context) => Container( // TODO(dantup): Change this to a theme colour and ensure it works in both dart/light themes color: const Color.fromRGBO(128, 128, 128, 0.5), @@ -134,7 +151,7 @@ if (widget.allowConnectionScreenOnDisconnect) RaisedButton( onPressed: () { - overlay.remove(); + hideDisconnectedOverlay(); Navigator.of(context).popAndPushNamed(homeRoute); }, child: const Text('Connect to Another App')) @@ -145,9 +162,7 @@ ), const Spacer(), RaisedButton( - onPressed: () { - overlay.remove(); - }, + onPressed: hideDisconnectedOverlay, child: const Text('Review History'), ), ], @@ -155,7 +170,7 @@ ), ), ); - return overlay; + return currentDisconnectedOverlay; } @override
diff --git a/packages/devtools_app/test/initializer_test.dart b/packages/devtools_app/test/initializer_test.dart index 70ab10c..bd9b67d 100644 --- a/packages/devtools_app/test/initializer_test.dart +++ b/packages/devtools_app/test/initializer_test.dart
@@ -67,6 +67,25 @@ expect(find.text('Disconnected'), findsOneWidget); }); + testWidgets('closes disconnected overlay upon reconnect', + (WidgetTester tester) async { + final serviceManager = FakeServiceManager(useFakeService: true); + setGlobal(ServiceConnectionManager, serviceManager); + + // Trigger a disconnect and ensure the overlay appears. + await tester.pumpFrames(app, const Duration(milliseconds: 100)); + serviceManager.changeState(false); + await tester.pumpFrames(app, const Duration(milliseconds: 100)); + expect(find.text('Disconnected'), findsOneWidget); + + // Trigger a reconnect + serviceManager.changeState(true); + + // Expect no overlay. + await tester.pumpFrames(app, const Duration(milliseconds: 100)); + expect(find.text('Disconnected'), findsNothing); + }); + testWidgets('builds contents when initialized', (WidgetTester tester) async { await tester.pumpWidget(app);
diff --git a/packages/devtools_app/test/support/mocks.dart b/packages/devtools_app/test/support/mocks.dart index 06826e3..715baf5 100644 --- a/packages/devtools_app/test/support/mocks.dart +++ b/packages/devtools_app/test/support/mocks.dart
@@ -110,7 +110,7 @@ @override Stream<bool> get onStateChange => stateChangeStream.stream; - StreamController<bool> stateChangeStream = StreamController(); + StreamController<bool> stateChangeStream = StreamController.broadcast(); void changeState(bool value) { hasConnection = value;