Skip to content

Commit 81887b5

Browse files
committed
chore: improve error page
1 parent a0b3dcb commit 81887b5

File tree

11 files changed

+241
-41
lines changed

11 files changed

+241
-41
lines changed

lib/app/app_config.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ class AppConfig {
44
static const appId = '$appName.$orgName';
55
static const kAppTitle = 'Nebuchadnezzar';
66
static const String appOpenUrlScheme = 'im.nebuchadnezzar';
7-
static const String repoUrl =
8-
'https://github.com/ubuntu-flutter-community/nebuchadnezzar';
7+
static const String owner = 'ubuntu-flutter-community';
8+
static const String repo = 'nebuchadnezzar';
9+
static const host = 'github.com';
10+
static const scheme = 'https';
11+
static const String repoUrl = '$scheme://$host/$owner/$repo';
12+
static const String repoReportIssueUrl =
13+
'$scheme://$host/$owner/$repo/issues/new';
914
}

lib/app/view/error_page.dart

Lines changed: 110 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
1+
import 'dart:io';
2+
3+
import 'package:flutter/foundation.dart';
14
import 'package:flutter/material.dart';
5+
import 'package:url_launcher/url_launcher.dart';
26
import 'package:yaru/yaru.dart';
37
import '../../common/view/ui_constants.dart';
48
import '../../l10n/l10n.dart';
9+
import '../app_config.dart';
510

611
class ErrorPage extends StatelessWidget {
7-
const ErrorPage({super.key, required this.error});
12+
const ErrorPage({
13+
super.key,
14+
required this.error,
15+
this.onRetry,
16+
this.onRetryLabel,
17+
this.addQuitButton = false,
18+
});
819

920
final String error;
21+
final void Function()? onRetry;
22+
final String? onRetryLabel;
23+
final bool addQuitButton;
1024

1125
@override
1226
Widget build(BuildContext context) {
@@ -16,22 +30,114 @@ class ErrorPage extends StatelessWidget {
1630
border: BorderSide.none,
1731
backgroundColor: Colors.transparent,
1832
),
19-
body: ErrorBody(error: error),
33+
body: ErrorBody(
34+
error: error,
35+
onRetryLabel: onRetryLabel,
36+
onRetry: onRetry,
37+
addQuitButton: addQuitButton,
38+
),
2039
);
2140
}
2241
}
2342

2443
class ErrorBody extends StatelessWidget {
25-
const ErrorBody({super.key, required this.error});
44+
const ErrorBody({
45+
super.key,
46+
required this.error,
47+
this.onRetry,
48+
this.onRetryLabel,
49+
this.addQuitButton = false,
50+
});
2651

2752
final String error;
53+
final void Function()? onRetry;
54+
final String? onRetryLabel;
55+
final bool addQuitButton;
2856

2957
@override
3058
Widget build(BuildContext context) {
3159
return Center(
3260
child: Padding(
3361
padding: const EdgeInsets.all(kBigPadding),
34-
child: Text('An error occurred: $error'),
62+
child: SizedBox(
63+
width: 250,
64+
child: Column(
65+
mainAxisSize: MainAxisSize.min,
66+
children: [
67+
const Icon(Icons.bug_report, size: 30),
68+
const SizedBox(height: kMediumPadding),
69+
Text('An error occurred: $error'),
70+
const SizedBox(height: 2 * kBigPadding),
71+
SizedBox(
72+
child: Column(
73+
mainAxisSize: MainAxisSize.min,
74+
spacing: kMediumPadding,
75+
children: [
76+
if (onRetry != null)
77+
...[
78+
ElevatedButton.icon(
79+
icon: const Icon(YaruIcons.refresh),
80+
onPressed: onRetry,
81+
label: Text(onRetryLabel ?? context.l10n.retry),
82+
),
83+
OutlinedButton.icon(
84+
icon: const Icon(YaruIcons.send),
85+
onPressed: () {
86+
final String body =
87+
'''
88+
**Describe the bug**
89+
90+
A clear and concise description of what the bug is.
91+
92+
**To Reproduce**
93+
Steps to reproduce the behavior:
94+
1. Go to '...'
95+
2. Click on '....'
96+
3. Scroll down to '....'
97+
4. See error
98+
99+
**Screenshots**
100+
If applicable, add screenshots to help explain your problem.
101+
102+
**Additional context**
103+
Add any other context about the problem here.
104+
105+
**Error Log**
106+
```
107+
Platform: ${kIsWeb ? 'Web' : Platform.operatingSystem} ${kIsWeb ? '' : Platform.operatingSystemVersion}
108+
109+
------------ Stack Trace ------------
110+
${StackTrace.current}
111+
''';
112+
launchUrl(
113+
Uri(
114+
scheme: AppConfig.scheme,
115+
host: AppConfig.host,
116+
path:
117+
'/${AppConfig.owner}/${AppConfig.repo}/issues/new',
118+
queryParameters: {
119+
'title':
120+
'fix: ${error.toString().split('\n').first}',
121+
'body': body,
122+
},
123+
),
124+
);
125+
},
126+
label: Text(context.l10n.reportIssue),
127+
),
128+
if (addQuitButton)
129+
OutlinedButton.icon(
130+
icon: const Icon(YaruIcons.window_close),
131+
onPressed: () => exit(0),
132+
label: Text(context.l10n.closeApp),
133+
),
134+
].map((e) => SizedBox(width: double.infinity, child: e)),
135+
],
136+
),
137+
),
138+
],
139+
),
140+
),
35141
),
36142
);
37143
}

lib/app/view/wait_for_registration_page.dart

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@ import 'package:flutter_it/flutter_it.dart';
44
import '../../authentication/authentication_service.dart';
55
import '../../authentication/view/chat_login_page.dart';
66
import '../../encryption/view/check_encryption_setup_page.dart';
7+
import '../../register_dependencies.dart';
8+
import '../app_config.dart';
79
import 'app.dart';
810
import 'error_page.dart';
911
import 'splash_page.dart';
1012

13+
final _registrationRestartNotifier = ValueNotifier(UniqueKey());
14+
1115
class WaitForRegistrationPage extends StatefulWidget {
1216
const WaitForRegistrationPage({
1317
super.key,
@@ -37,34 +41,47 @@ class _WaitForRegistrationPageState extends State<WaitForRegistrationPage> {
3741
}
3842

3943
@override
40-
Widget build(BuildContext context) => FutureBuilder(
41-
future: _registrationReady,
42-
builder: (context, snapshot) => snapshot.hasError
43-
? App(
44-
themeMode: ThemeMode.system,
45-
lightTheme: widget.lightTheme,
46-
darkTheme: widget.darkTheme,
47-
highContrastDarkTheme: widget.highContrastDarkTheme,
48-
highContrastTheme: widget.highContrastTheme,
49-
child: ErrorPage(error: snapshot.error.toString()),
50-
)
51-
: snapshot.hasData
52-
? App(
53-
lightTheme: widget.lightTheme,
54-
darkTheme: widget.darkTheme,
55-
highContrastDarkTheme: widget.highContrastDarkTheme,
56-
highContrastTheme: widget.highContrastTheme,
57-
child: (!di<AuthenticationService>().isLogged)
58-
? const ChatLoginPage()
59-
: const CheckEncryptionSetupPage(),
60-
)
61-
: App(
62-
themeMode: ThemeMode.system,
63-
lightTheme: widget.lightTheme,
64-
darkTheme: widget.darkTheme,
65-
highContrastDarkTheme: widget.highContrastDarkTheme,
66-
highContrastTheme: widget.highContrastTheme,
67-
child: const SplashPage(),
68-
),
44+
Widget build(BuildContext context) => ValueListenableBuilder(
45+
valueListenable: _registrationRestartNotifier,
46+
builder: (context, value, child) {
47+
return FutureBuilder(
48+
future: _registrationReady,
49+
builder: (context, snapshot) => snapshot.hasError
50+
? App(
51+
themeMode: ThemeMode.system,
52+
lightTheme: widget.lightTheme,
53+
darkTheme: widget.darkTheme,
54+
highContrastDarkTheme: widget.highContrastDarkTheme,
55+
highContrastTheme: widget.highContrastTheme,
56+
child: ErrorPage(
57+
error: snapshot.error.toString(),
58+
addQuitButton: true,
59+
onRetry: () {
60+
di.reset(dispose: false);
61+
registerDependencies();
62+
_registrationRestartNotifier.value = UniqueKey();
63+
},
64+
),
65+
)
66+
: snapshot.hasData
67+
? App(
68+
lightTheme: widget.lightTheme,
69+
darkTheme: widget.darkTheme,
70+
highContrastDarkTheme: widget.highContrastDarkTheme,
71+
highContrastTheme: widget.highContrastTheme,
72+
child: (!di<AuthenticationService>().isLogged)
73+
? const ChatLoginPage()
74+
: const CheckEncryptionSetupPage(),
75+
)
76+
: App(
77+
themeMode: ThemeMode.system,
78+
lightTheme: widget.lightTheme,
79+
darkTheme: widget.darkTheme,
80+
highContrastDarkTheme: widget.highContrastDarkTheme,
81+
highContrastTheme: widget.highContrastTheme,
82+
child: const SplashPage(title: Text(AppConfig.appName)),
83+
),
84+
);
85+
},
6986
);
7087
}

lib/chat_room/input/view/chat_input.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ class _NewWidgetState extends State<NewWidget> {
346346
},
347347
value: threadRootEventId != null,
348348
),
349-
Text('Create Thread'),
349+
const Text('Create Thread'),
350350
],
351351
),
352352
yaruInfoType: editEvent != null

lib/extensions/client_x.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ extension ClientX on Client {
4343
);
4444
// This reads potential credentials that might exist from previous sessions
4545
// to determine whether the user is logged in or not.
46-
await client.init().timeout(const Duration(seconds: 55));
46+
await client.init();
4747

4848
return client;
4949
}

lib/l10n/app_en.arb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3255,5 +3255,9 @@
32553255
}
32563256
},
32573257
"pusherDevices": "Pusher Devices",
3258-
"syncNow": "Sync now"
3259-
}
3258+
"syncNow": "Sync now",
3259+
"startAppUpPleaseWait": "Starting, please wait...",
3260+
"retry": "Retry",
3261+
"reportIssue": "Report issue",
3262+
"closeApp": "Close app"
3263+
}

lib/l10n/app_localizations.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4689,6 +4689,30 @@ abstract class AppLocalizations {
46894689
/// In en, this message translates to:
46904690
/// **'Sync now'**
46914691
String get syncNow;
4692+
4693+
/// No description provided for @startAppUpPleaseWait.
4694+
///
4695+
/// In en, this message translates to:
4696+
/// **'Starting, please wait...'**
4697+
String get startAppUpPleaseWait;
4698+
4699+
/// No description provided for @retry.
4700+
///
4701+
/// In en, this message translates to:
4702+
/// **'Retry'**
4703+
String get retry;
4704+
4705+
/// No description provided for @reportIssue.
4706+
///
4707+
/// In en, this message translates to:
4708+
/// **'Report issue'**
4709+
String get reportIssue;
4710+
4711+
/// No description provided for @closeApp.
4712+
///
4713+
/// In en, this message translates to:
4714+
/// **'Close app'**
4715+
String get closeApp;
46924716
}
46934717

46944718
class _AppLocalizationsDelegate

lib/l10n/app_localizations_de.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2667,4 +2667,16 @@ class AppLocalizationsDe extends AppLocalizations {
26672667

26682668
@override
26692669
String get syncNow => 'Sync now';
2670+
2671+
@override
2672+
String get startAppUpPleaseWait => 'Starting, please wait...';
2673+
2674+
@override
2675+
String get retry => 'Retry';
2676+
2677+
@override
2678+
String get reportIssue => 'Report issue';
2679+
2680+
@override
2681+
String get closeApp => 'Close app';
26702682
}

lib/l10n/app_localizations_en.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2667,4 +2667,16 @@ class AppLocalizationsEn extends AppLocalizations {
26672667

26682668
@override
26692669
String get syncNow => 'Sync now';
2670+
2671+
@override
2672+
String get startAppUpPleaseWait => 'Starting, please wait...';
2673+
2674+
@override
2675+
String get retry => 'Retry';
2676+
2677+
@override
2678+
String get reportIssue => 'Report issue';
2679+
2680+
@override
2681+
String get closeApp => 'Close app';
26702682
}

lib/l10n/app_localizations_sv.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2681,4 +2681,16 @@ class AppLocalizationsSv extends AppLocalizations {
26812681

26822682
@override
26832683
String get syncNow => 'Sync now';
2684+
2685+
@override
2686+
String get startAppUpPleaseWait => 'Starting, please wait...';
2687+
2688+
@override
2689+
String get retry => 'Retry';
2690+
2691+
@override
2692+
String get reportIssue => 'Report issue';
2693+
2694+
@override
2695+
String get closeApp => 'Close app';
26842696
}

0 commit comments

Comments
 (0)