Skip to content

Commit ab91480

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

File tree

3 files changed

+44
-0
lines changed

3 files changed

+44
-0
lines changed

lib/log.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ bool debugLog(String message) {
3232
}
3333

3434
typedef ReportErrorCancellablyCallback = void Function(String? message, {String? details});
35+
typedef ReportErrorCallback = void Function(String message, {String? details});
3536

3637
/// Show the user an error message, without requiring them to interact with it.
3738
///
@@ -50,6 +51,17 @@ typedef ReportErrorCancellablyCallback = void Function(String? message, {String?
5051
// the app.
5152
ReportErrorCancellablyCallback reportErrorToUserBriefly = defaultReportErrorToUserBriefly;
5253

54+
/// Show the user a dismissable error message in a modal popup.
55+
///
56+
/// Typically this shows a [AlertDialog] containing the message.
57+
/// If called before the app's widget tree is ready (see [ZulipApp.ready]),
58+
/// then we give up on showing the message to the user,
59+
/// and just log the message to the console.
60+
// This gets set in [ZulipApp]. We need this indirection to keep `lib/log.dart`
61+
// from importing widget code, because the file is a dependency for the rest of
62+
// the app.
63+
ReportErrorCallback reportErrorToUserModally = defaultReportErrorToUserBriefly;
64+
5365
void defaultReportErrorToUserBriefly(String? message, {String? details}) {
5466
// Error dismissing is a no-op to the default handler.
5567
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 = defaultReportErrorToUserBriefly;
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 message, {String? details}) {
134+
assert(_ready.value);
135+
136+
showErrorDialog(
137+
context: navigatorKey.currentContext!,
138+
title: message,
139+
message: details);
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: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'dart:async';
22

33
import 'package:checks/checks.dart';
44
import 'package:flutter/material.dart';
5+
import 'package:flutter_checks/flutter_checks.dart';
56
import 'package:flutter_test/flutter_test.dart';
67
import 'package:zulip/log.dart';
78
import 'package:zulip/model/database.dart';
@@ -361,5 +362,24 @@ void main() {
361362
await tester.pumpAndSettle();
362363
check(findSnackBarByText('unrelated').evaluate()).single;
363364
});
365+
366+
testWidgets('reportErrorToUserModally', (tester) async {
367+
addTearDown(testBinding.reset);
368+
await tester.pumpWidget(const ZulipApp());
369+
const message = 'test error message';
370+
const details = 'details';
371+
372+
// Prior to app startup, reportErrorToUserModally only logs.
373+
reportErrorToUserModally(message, details: details);
374+
check(ZulipApp.ready).value.isFalse();
375+
await tester.pump();
376+
check(find.byType(AlertDialog)).findsNothing();
377+
378+
check(ZulipApp.ready).value.isTrue();
379+
// After app startup, reportErrorToUserModally displays an [AlertDialog].
380+
reportErrorToUserModally(message, details: details);
381+
await tester.pump();
382+
checkErrorDialog(tester, expectedTitle: message, expectedMessage: details);
383+
});
364384
});
365385
}

0 commit comments

Comments
 (0)