Skip to content

Commit 2fdaa81

Browse files
gnpricePIG208
authored andcommitted
log: Support reportErrorToUser* helpers.
The imports in `lib/log.dart` are for the code references in the reportErrorToUser* helpers' dart doc.
1 parent 86e3a95 commit 2fdaa81

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

lib/log.dart

+27
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import 'package:flutter/material.dart';
2+
3+
import 'widgets/app.dart';
14

25
/// Whether [debugLog] should do anything.
36
///
@@ -30,3 +33,27 @@ bool debugLog(String message) {
3033
}());
3134
return true;
3235
}
36+
37+
/// Display an error message.
38+
///
39+
/// This shows a [SnackBar] containing the message after app startup,
40+
/// otherwise logs it to the console.
41+
///
42+
/// See also: [ZulipApp._reportErrorToUserBriefly]
43+
void Function(String message) reportErrorToUserBriefly = _defaultReportErrorToUser;
44+
45+
/// Display an error message in a dialog.
46+
///
47+
/// This shows a dialog containing the message after app startup,
48+
/// otherwise logs it to the console.
49+
///
50+
/// See also: [ZulipApp._reportErrorToUserBriefly]
51+
void Function(String message) reportErrorToUserInDialog = _defaultReportErrorToUser;
52+
53+
void _defaultReportErrorToUser(String message) {
54+
// If this callback is still in place, then the app's widget tree
55+
// hasn't mounted yet even as far as the [Navigator].
56+
// So there's not much we can do to tell the user;
57+
// just log, in case the user is actually a developer watching the console.
58+
assert(debugLog(message));
59+
}

lib/widgets/app.dart

+14
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ import 'package:flutter/material.dart';
55
import 'package:flutter/scheduler.dart';
66
import 'package:flutter_gen/gen_l10n/zulip_localizations.dart';
77

8+
import '../log.dart';
89
import '../model/localizations.dart';
910
import '../model/narrow.dart';
1011
import 'about_zulip.dart';
1112
import 'app_bar.dart';
13+
import 'dialog.dart';
1214
import 'inbox.dart';
1315
import 'login.dart';
1416
import 'message_list.dart';
@@ -92,9 +94,21 @@ class ZulipApp extends StatefulWidget {
9294
/// Useful in tests.
9395
final List<NavigatorObserver>? navigatorObservers;
9496

97+
static void _reportErrorToUserBriefly(String message) {
98+
scaffoldMessenger?.showSnackBar(SnackBar(content: Text(message)));
99+
}
100+
101+
static void _reportErrorToUserInDialog(String message) {
102+
final context = navigatorKey.currentContext;
103+
if (context == null) return;
104+
showErrorDialog(context: context, title: 'Error', message: message);
105+
}
106+
95107
void _declareReady() {
96108
assert(navigatorKey.currentContext != null);
97109
_ready.value = true;
110+
reportErrorToUserBriefly = _reportErrorToUserBriefly;
111+
reportErrorToUserInDialog = _reportErrorToUserInDialog;
98112
}
99113

100114
@override

test/widgets/app_test.dart

+33
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:checks/checks.dart';
22
import 'package:flutter/material.dart';
33
import 'package:flutter_test/flutter_test.dart';
4+
import 'package:zulip/log.dart';
45
import 'package:zulip/model/database.dart';
56
import 'package:zulip/widgets/app.dart';
67
import 'package:zulip/widgets/inbox.dart';
@@ -164,5 +165,37 @@ void main() {
164165
check(ZulipApp.scaffoldMessenger).isNotNull();
165166
check(ZulipApp.ready).value.isTrue();
166167
});
168+
169+
testWidgets('reportErrorToUserBriefly shows snack bar', (tester) async {
170+
await tester.pumpWidget(const ZulipApp());
171+
172+
// Prior to app startup, reportErrorToUserBriefly only logs.
173+
reportErrorToUserBriefly('test error message');
174+
check(ZulipApp.ready).value.isFalse();
175+
await tester.pump();
176+
check(find.text('test error message').evaluate()).isEmpty();
177+
check(ZulipApp.ready).value.isTrue();
178+
179+
// After app startup, reportErrorToUserBriefly displays a snack bar.
180+
reportErrorToUserBriefly('test error message');
181+
await tester.pump();
182+
check(find.text('test error message').evaluate()).single;
183+
});
184+
185+
testWidgets('reportErrorToUserInDialog shows dialog', (tester) async {
186+
await tester.pumpWidget(const ZulipApp());
187+
188+
// Prior to app startup, reportErrorToUserInDialog only logs.
189+
reportErrorToUserInDialog('test error message');
190+
check(ZulipApp.ready).value.isFalse();
191+
await tester.pump();
192+
check(find.text('test error message').evaluate()).isEmpty();
193+
check(ZulipApp.ready).value.isTrue();
194+
195+
// After app startup, reportErrorToUserInDialog displays a dialog.
196+
reportErrorToUserInDialog('test error message');
197+
await tester.pump();
198+
check(find.text('test error message').evaluate()).single;
199+
});
167200
});
168201
}

0 commit comments

Comments
 (0)