Skip to content

Commit

Permalink
app: Add ZulipApp.scaffoldMessenger
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
gnprice and PIG208 committed Sep 24, 2024
1 parent ea8c765 commit 9aa0471
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 1 deletion.
16 changes: 16 additions & 0 deletions lib/widgets/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,22 @@ class ZulipApp extends StatefulWidget {
/// to be mounted.
static final navigatorKey = GlobalKey<NavigatorState>();

/// The [ScaffoldMessengerState] for the app.
///
/// This is null during the app's early startup, while [ready] is still false.
///
/// For code that exists entirely outside the widget tree and has no natural
/// [BuildContext] of its own, this enables controlling snack bars.
/// Where a relevant [BuildContext] does exist, prefer using that instead,
/// with [ScaffoldMessenger.of].
static ScaffoldMessengerState? get scaffoldMessenger {
final context = navigatorKey.currentContext;
if (context == null) return null;
// Not maybeOf; we use MaterialApp, which provides ScaffoldMessenger,
// so it's a bug if navigatorKey is mounted somewhere lacking that.
return ScaffoldMessenger.of(context);
}

/// Reset the state of [ZulipApp] statics, for testing.
///
/// TODO refactor this better, perhaps unify with ZulipBinding
Expand Down
3 changes: 2 additions & 1 deletion test/flutter_checks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
library;

import 'package:checks/checks.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

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

extension ValueNotifierChecks<T> on Subject<ValueNotifier<T>> {
extension ValueListenableChecks<T> on Subject<ValueListenable<T>> {
Subject<T> get value => has((c) => c.value, 'value');
}

Expand Down
13 changes: 13 additions & 0 deletions test/widgets/app_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,17 @@ void main() {
..bottom.isLessThan(2 / 3 * screenHeight);
});
});

group('scaffoldMessenger', () {
testWidgets('scaffoldMessenger becomes non-null after startup', (tester) async {
addTearDown(testBinding.reset);
await tester.pumpWidget(const ZulipApp());

check(ZulipApp.scaffoldMessenger).isNull();
check(ZulipApp.ready).value.isFalse();
await tester.pump();
check(ZulipApp.scaffoldMessenger).isNotNull();
check(ZulipApp.ready).value.isTrue();
});
});
}

0 comments on commit 9aa0471

Please sign in to comment.