Skip to content

Commit a7a8beb

Browse files
committed
log: Add reportErrorModally
Signed-off-by: Zixuan James Li <[email protected]>
1 parent c0b41c6 commit a7a8beb

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

lib/log.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ bool debugLog(String message) {
3636
// `null` for the `message` parameter and promptly dismiss the reported errors.
3737
typedef ReportErrorCancellablyCallback = void Function(String? message, {String? details});
3838

39+
typedef ReportErrorCallback = void Function(String title, {String? message});
40+
3941
/// Show the user an error message, without requiring them to interact with it.
4042
///
4143
/// Typically this shows a [SnackBar] containing the message.
@@ -53,10 +55,25 @@ typedef ReportErrorCancellablyCallback = void Function(String? message, {String?
5355
// the app.
5456
ReportErrorCancellablyCallback reportErrorToUserBriefly = defaultReportErrorToUserBriefly;
5557

58+
/// Show the user a dismissable error message in a modal popup.
59+
///
60+
/// Typically this shows an [AlertDialog] with `title` as the title, `message`
61+
/// as the body. If called before the app's widget tree is ready
62+
/// (see [ZulipApp.ready]), then we give up on showing the message to the user,
63+
/// and just log the message to the console.
64+
// This gets set in [ZulipApp]. We need this indirection to keep `lib/log.dart`
65+
// from importing widget code, because the file is a dependency for the rest of
66+
// the app.
67+
ReportErrorCallback reportErrorToUserModally = defaultReportErrorToUserModally;
68+
5669
void defaultReportErrorToUserBriefly(String? message, {String? details}) {
5770
_reportErrorToConsole(message, details);
5871
}
5972

73+
void defaultReportErrorToUserModally(String title, {String? message}) {
74+
_reportErrorToConsole(title, message);
75+
}
76+
6077
void _reportErrorToConsole(String? message, String? details) {
6178
// Error dismissing is a no-op for the console.
6279
if (message == null) return;

lib/widgets/app.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class ZulipApp extends StatefulWidget {
8585
static void debugReset() {
8686
_snackBarCount = 0;
8787
reportErrorToUserBriefly = defaultReportErrorToUserBriefly;
88+
reportErrorToUserModally = defaultReportErrorToUserModally;
8889
_ready.dispose();
8990
_ready = ValueNotifier(false);
9091
}
@@ -128,10 +129,21 @@ class ZulipApp extends StatefulWidget {
128129
newSnackBar.closed.whenComplete(() => _snackBarCount--);
129130
}
130131

132+
/// The callback we normally use as [reportErrorToUserModally].
133+
static void _reportErrorToUserModally(String title, {String? message}) {
134+
assert(_ready.value);
135+
136+
showErrorDialog(
137+
context: navigatorKey.currentContext!,
138+
title: title,
139+
message: message);
140+
}
141+
131142
void _declareReady() {
132143
assert(navigatorKey.currentContext != null);
133144
_ready.value = true;
134145
reportErrorToUserBriefly = _reportErrorToUserBriefly;
146+
reportErrorToUserModally = _reportErrorToUserModally;
135147
}
136148

137149
@override

test/widgets/app_test.dart

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,5 +363,24 @@ void main() {
363363
await tester.pumpAndSettle();
364364
check(findSnackBarByText('unrelated').evaluate()).single;
365365
});
366+
367+
testWidgets('reportErrorToUserModally', (tester) async {
368+
addTearDown(testBinding.reset);
369+
await tester.pumpWidget(const ZulipApp());
370+
const title = 'test title';
371+
const message = 'test message';
372+
373+
// Prior to app startup, reportErrorToUserModally only logs.
374+
reportErrorToUserModally(title, message: message);
375+
check(ZulipApp.ready).value.isFalse();
376+
await tester.pump();
377+
checkNoErrorDialog(tester);
378+
379+
check(ZulipApp.ready).value.isTrue();
380+
// After app startup, reportErrorToUserModally displays an [AlertDialog].
381+
reportErrorToUserModally(title, message: message);
382+
await tester.pump();
383+
checkErrorDialog(tester, expectedTitle: title, expectedMessage: message);
384+
});
366385
});
367386
}

0 commit comments

Comments
 (0)