Skip to content

Commit 9aa0471

Browse files
gnpricePIG208
andcommitted
app: Add ZulipApp.scaffoldMessenger
Also generalize ValueNotifierChecks to ValueListenableChecks. We can't write checks-extensions for ZulipApp.scaffoldMessenger or ZulipApp.ready, though, because Dart doesn't have extensions for static members. Apparently they're currently working on them: dart-lang/language#723 Co-authored-by: Zixuan James Li <[email protected]>
1 parent ea8c765 commit 9aa0471

File tree

3 files changed

+31
-1
lines changed

3 files changed

+31
-1
lines changed

lib/widgets/app.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,22 @@ class ZulipApp extends StatefulWidget {
6363
/// to be mounted.
6464
static final navigatorKey = GlobalKey<NavigatorState>();
6565

66+
/// The [ScaffoldMessengerState] for the app.
67+
///
68+
/// This is null during the app's early startup, while [ready] is still false.
69+
///
70+
/// For code that exists entirely outside the widget tree and has no natural
71+
/// [BuildContext] of its own, this enables controlling snack bars.
72+
/// Where a relevant [BuildContext] does exist, prefer using that instead,
73+
/// with [ScaffoldMessenger.of].
74+
static ScaffoldMessengerState? get scaffoldMessenger {
75+
final context = navigatorKey.currentContext;
76+
if (context == null) return null;
77+
// Not maybeOf; we use MaterialApp, which provides ScaffoldMessenger,
78+
// so it's a bug if navigatorKey is mounted somewhere lacking that.
79+
return ScaffoldMessenger.of(context);
80+
}
81+
6682
/// Reset the state of [ZulipApp] statics, for testing.
6783
///
6884
/// TODO refactor this better, perhaps unify with ZulipBinding

test/flutter_checks.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
library;
33

44
import 'package:checks/checks.dart';
5+
import 'package:flutter/foundation.dart';
56
import 'package:flutter/material.dart';
67
import 'package:flutter/services.dart';
78

@@ -51,7 +52,7 @@ extension RouteSettingsChecks<T> on Subject<RouteSettings> {
5152
Subject<Object?> get arguments => has((s) => s.arguments, 'arguments');
5253
}
5354

54-
extension ValueNotifierChecks<T> on Subject<ValueNotifier<T>> {
55+
extension ValueListenableChecks<T> on Subject<ValueListenable<T>> {
5556
Subject<T> get value => has((c) => c.value, 'value');
5657
}
5758

test/widgets/app_test.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,4 +157,17 @@ void main() {
157157
..bottom.isLessThan(2 / 3 * screenHeight);
158158
});
159159
});
160+
161+
group('scaffoldMessenger', () {
162+
testWidgets('scaffoldMessenger becomes non-null after startup', (tester) async {
163+
addTearDown(testBinding.reset);
164+
await tester.pumpWidget(const ZulipApp());
165+
166+
check(ZulipApp.scaffoldMessenger).isNull();
167+
check(ZulipApp.ready).value.isFalse();
168+
await tester.pump();
169+
check(ZulipApp.scaffoldMessenger).isNotNull();
170+
check(ZulipApp.ready).value.isTrue();
171+
});
172+
});
160173
}

0 commit comments

Comments
 (0)