Skip to content

Commit 71532ac

Browse files
committed
add error messages
1 parent 206160b commit 71532ac

File tree

11 files changed

+142
-31
lines changed

11 files changed

+142
-31
lines changed

lib/l10n/intl_en.arb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,9 @@
8383
"getApiKey": "Get API ID & Key",
8484
"getApiKeyHint": "In \"Preferences\" > \"Developer\"",
8585
"prev": "Previous",
86-
"next": "Next"
86+
"next": "Next",
87+
"wentWrong": "Something went wrong.",
88+
"retry": "Retry",
89+
"copy": "Copy",
90+
"errorLog": "Error log"
8791
}

lib/l10n/intl_zh.arb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,9 @@
8383
"getApiKey": "获取 API ID & KEY",
8484
"getApiKeyHint": "在 “偏好设置” > “开发者” 下",
8585
"prev": "前一项",
86-
"next": "后一项"
86+
"next": "后一项",
87+
"wentWrong": "发生错误",
88+
"retry": "重试",
89+
"copy": "复制",
90+
"errorLog": "错误日志"
8791
}

lib/main.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'dart:io';
22

33
import 'package:fluent_reader_lite/models/service.dart';
44
import 'package:fluent_reader_lite/pages/article_page.dart';
5+
import 'package:fluent_reader_lite/pages/error_log_page.dart';
56
import 'package:fluent_reader_lite/pages/settings/about_page.dart';
67
import 'package:fluent_reader_lite/pages/home_page.dart';
78
import 'package:fluent_reader_lite/pages/settings/feed_page.dart';
@@ -53,6 +54,7 @@ void main() async {
5354
class MyApp extends StatelessWidget {
5455
static final Map<String, Widget Function(BuildContext)> baseRoutes = {
5556
"/article": (context) => ArticlePage(),
57+
"/error-log": (context) => ErrorLogPage(),
5658
"/settings": (context) => SettingsPage(),
5759
"/settings/sources": (context) => SourcesPage(),
5860
"/settings/sources/edit": (context) => SourceEditPage(),

lib/models/sync_model.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class SyncModel with ChangeNotifier {
5656
lastSyncSuccess = true;
5757
} catch(exp) {
5858
lastSyncSuccess = false;
59+
Store.setErrorLog(exp.toString());
5960
print(exp);
6061
}
6162
lastSynced = DateTime.now();

lib/pages/article_page.dart

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import 'package:fluent_reader_lite/utils/global.dart';
1111
import 'package:fluent_reader_lite/utils/store.dart';
1212
import 'package:flutter/cupertino.dart';
1313
import 'package:flutter/material.dart';
14+
import 'package:flutter/services.dart';
1415
import 'package:intl/intl.dart';
1516
import 'package:http/http.dart' as http;
1617
import 'package:provider/provider.dart';
@@ -29,10 +30,14 @@ class ArticlePage extends StatefulWidget {
2930
ArticlePageState createState() => ArticlePageState();
3031
}
3132

33+
enum _ArticleLoadState {
34+
Loading, Success, Failure
35+
}
36+
3237
class ArticlePageState extends State<ArticlePage> {
3338
WebViewController _controller;
3439
int requestId = 0;
35-
bool loaded = false;
40+
_ArticleLoadState loaded = _ArticleLoadState.Loading;
3641
bool navigated = false;
3742
SourceOpenTarget _target;
3843
String iid;
@@ -44,7 +49,7 @@ class ArticlePageState extends State<ArticlePage> {
4449
}
4550
setState(() {
4651
iid = id;
47-
loaded = false;
52+
loaded = _ArticleLoadState.Loading;
4853
navigated = false;
4954
_target = null;
5055
if (isSource != null) isSourceFeed = isSource;
@@ -70,12 +75,15 @@ class ArticlePageState extends State<ArticlePage> {
7075
var html = (await http.get(item.link)).body;
7176
a = Uri.encodeComponent(html);
7277
} catch(exp) {
73-
setState(() { loaded = true; });
78+
if (mounted && currId == requestId) {
79+
setState(() { loaded = _ArticleLoadState.Failure; });
80+
}
7481
return;
7582
}
7683
} else {
7784
a = Uri.encodeComponent(item.content);
7885
}
86+
if (!mounted || currId != requestId) return;
7987
var h = '<p id="source">${source.name}${(item.creator!=null&&item.creator.length>0)?' / '+item.creator:''}</p>';
8088
h += '<p id="title">${item.title}</p>';
8189
h += '<p id="date">${DateFormat.yMd(Localizations.localeOf(context).toString()).add_Hm().format(item.date)}</p>';
@@ -87,20 +95,20 @@ class ArticlePageState extends State<ArticlePage> {
8795
var brightness = Global.currentBrightness(context);
8896
localUrl += "&t=${brightness.index}";
8997
}
90-
if (currId == requestId) _controller.loadUrl(localUrl);
98+
_controller.loadUrl(localUrl);
9199
}
92100

93101
void _onPageReady(_) async {
94102
if (Platform.isAndroid || Global.globalModel.getBrightness() != null) {
95103
await Future.delayed(Duration(milliseconds: 300));
96104
}
97-
setState(() { loaded = true; });
105+
setState(() { loaded = _ArticleLoadState.Success; });
98106
if (_target == SourceOpenTarget.Local || _target == SourceOpenTarget.FullContent) {
99107
navigated = true;
100108
}
101109
}
102110
void _onWebpageReady(_) {
103-
if (loaded) navigated = true;
111+
if (loaded == _ArticleLoadState.Success) navigated = true;
104112
}
105113

106114
void _setOpenTarget(RSSSource source, {SourceOpenTarget target}) {
@@ -112,7 +120,7 @@ class ArticlePageState extends State<ArticlePage> {
112120
void _loadOpenTarget(RSSItem item, RSSSource source) {
113121
setState(() {
114122
requestId += 1;
115-
loaded = false;
123+
loaded = _ArticleLoadState.Loading;
116124
navigated = false;
117125
});
118126
switch (_target) {
@@ -166,7 +174,7 @@ class ArticlePageState extends State<ArticlePage> {
166174
var source = tuple.item2;
167175
if (_target == null) _target = source.openTarget;
168176
final body = SafeArea(child: IndexedStack(
169-
index: !loaded ? 0 : 1,
177+
index: loaded.index,
170178
children: [
171179
Center(
172180
child: CupertinoActivityIndicator()
@@ -182,6 +190,21 @@ class ArticlePageState extends State<ArticlePage> {
182190
onPageFinished: _onWebpageReady,
183191
navigationDelegate: _onNavigate,
184192
),
193+
Center(
194+
child: Column(
195+
mainAxisAlignment: MainAxisAlignment.center,
196+
children: [
197+
Text(
198+
S.of(context).wentWrong,
199+
style: TextStyle(color: CupertinoColors.label.resolveFrom(context)),
200+
),
201+
CupertinoButton(
202+
child: Text(S.of(context).retry),
203+
onPressed: () { _loadOpenTarget(item, source); },
204+
),
205+
],
206+
),
207+
)
185208
],
186209
), bottom: false,);
187210
return CupertinoPageScaffold(
@@ -208,6 +231,7 @@ class ArticlePageState extends State<ArticlePage> {
208231
? S.of(context).markUnread
209232
: S.of(context).markRead,
210233
onPressed: () {
234+
HapticFeedback.mediumImpact();
211235
Global.itemsModel.updateItem(item.id, read: !item.hasRead);
212236
},
213237
),
@@ -219,13 +243,25 @@ class ArticlePageState extends State<ArticlePage> {
219243
? S.of(context).star
220244
: S.of(context).unstar,
221245
onPressed: () {
246+
HapticFeedback.mediumImpact();
222247
Global.itemsModel.updateItem(item.id, starred: !item.starred);
223248
},
224249
),
225250
CupertinoToolbarItem(
226251
icon: CupertinoIcons.share,
227252
semanticLabel: S.of(context).share,
228-
onPressed: () { Share.share(item.link); },
253+
onPressed: () {
254+
final media = MediaQuery.of(context);
255+
Share.share(
256+
item.link,
257+
sharePositionOrigin: Rect.fromLTWH(
258+
media.size.width - ArticlePage.state.currentContext.size.width / 2,
259+
media.size.height - media.padding.bottom - 54,
260+
0,
261+
0
262+
)
263+
);
264+
},
229265
),
230266
CupertinoToolbarItem(
231267
icon: CupertinoIcons.chevron_up,

lib/pages/error_log_page.dart

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import 'package:fluent_reader_lite/components/list_tile_group.dart';
2+
import 'package:fluent_reader_lite/generated/l10n.dart';
3+
import 'package:fluent_reader_lite/utils/colors.dart';
4+
import 'package:fluent_reader_lite/utils/store.dart';
5+
import 'package:flutter/cupertino.dart';
6+
import 'package:flutter/material.dart';
7+
import 'package:flutter/services.dart';
8+
9+
class ErrorLogPage extends StatelessWidget {
10+
@override
11+
Widget build(BuildContext context) {
12+
final errorLog = Store.getErrorLog();
13+
return CupertinoPageScaffold(
14+
backgroundColor: MyColors.background,
15+
navigationBar: CupertinoNavigationBar(
16+
middle: Text(S.of(context).errorLog),
17+
trailing: CupertinoButton(
18+
padding: EdgeInsets.zero,
19+
child: Text(S.of(context).copy),
20+
onPressed: () {
21+
Clipboard.setData(ClipboardData(text: errorLog));
22+
},
23+
),
24+
),
25+
child: ListView(children: [
26+
ListTileGroup([
27+
SelectableText(
28+
errorLog,
29+
style: TextStyle(color: CupertinoColors.label.resolveFrom(context)),
30+
),
31+
]),
32+
]),
33+
);
34+
}
35+
}

lib/pages/item_list_page.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,13 @@ class _ItemListPageState extends State<ItemListPage> {
241241
], mainAxisAlignment: MainAxisAlignment.spaceBetween),
242242
onPressed: () {
243243
Navigator.of(context, rootNavigator: true).pop();
244-
Share.share(item.link);
244+
final media = MediaQuery.of(context);
245+
Share.share(
246+
item.link,
247+
sharePositionOrigin: Rect.fromLTWH(
248+
160, media.size.height - media.padding.bottom, 0, 0
249+
),
250+
);
245251
},
246252
),
247253
],

lib/pages/settings/source_edit_page.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ class SourceEditPage extends StatelessWidget {
5858
final urlTile = ListTileGroup([
5959
MyListTile(
6060
title: Flexible(child: Text(source.url, style: urlStyle, overflow: TextOverflow.ellipsis)),
61-
trailing: Icon(CupertinoIcons.doc_on_clipboard),
61+
trailing: Icon(
62+
CupertinoIcons.doc_on_clipboard,
63+
semanticLabel: S.of(context).copy,
64+
),
6265
onTap: () { Clipboard.setData(ClipboardData(text: source.url)); },
6366
trailingChevron: false,
6467
withDivider: false,

lib/pages/subscription_list_page.dart

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import 'package:fluent_reader_lite/utils/colors.dart';
1313
import 'package:fluent_reader_lite/utils/global.dart';
1414
import 'package:flutter/cupertino.dart';
1515
import 'package:flutter/material.dart';
16+
import 'package:flutter/services.dart';
1617
import 'package:intl/intl.dart';
1718
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
1819
import 'package:provider/provider.dart';
@@ -98,6 +99,13 @@ class _SubscriptionListPageState extends State<SubscriptionListPage> {
9899
Navigator.of(context, rootNavigator: true).pushNamed("/settings");
99100
}
100101

102+
void _openErrorLog() {
103+
if (!Global.syncModel.lastSyncSuccess) {
104+
HapticFeedback.mediumImpact();
105+
Navigator.of(context, rootNavigator: true).pushNamed("/error-log");
106+
}
107+
}
108+
101109
@override
102110
Widget build(BuildContext context) {
103111
final navigationBar = CupertinoSliverNavigationBar(
@@ -166,23 +174,26 @@ class _SubscriptionListPageState extends State<SubscriptionListPage> {
166174
final syncInfo = Consumer<SyncModel>(
167175
builder: (context, syncModel, child) {
168176
return SliverToBoxAdapter(
169-
child: Container(
170-
padding: EdgeInsets.all(12),
171-
child: Column(
172-
children: [
173-
Text(
174-
syncModel.lastSyncSuccess
175-
? S.of(context).lastSyncSuccess
176-
: S.of(context).lastSyncFailure,
177-
style: syncStyle,
178-
),
179-
Text(
180-
DateFormat
181-
.Md(Localizations.localeOf(context).toString())
182-
.add_Hm().format(syncModel.lastSynced),
183-
style: syncStyle,
184-
),
185-
],
177+
child: GestureDetector(
178+
onLongPress: _openErrorLog,
179+
child: Container(
180+
padding: EdgeInsets.all(12),
181+
child: Column(
182+
children: [
183+
Text(
184+
syncModel.lastSyncSuccess
185+
? S.of(context).lastSyncSuccess
186+
: S.of(context).lastSyncFailure,
187+
style: syncStyle,
188+
),
189+
Text(
190+
DateFormat
191+
.Md(Localizations.localeOf(context).toString())
192+
.add_Hm().format(syncModel.lastSynced),
193+
style: syncStyle,
194+
),
195+
],
196+
),
186197
),
187198
),
188199
);

lib/utils/store.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:shared_preferences/shared_preferences.dart';
66

77
abstract class StoreKeys {
88
static const GROUPS = "groups";
9+
static const ERROR_LOG = "errorLog";
910

1011
// General
1112
static const THEME = "theme";
@@ -97,4 +98,12 @@ class Store {
9798
static void setArticleFontSize(int value) {
9899
sp.setInt(StoreKeys.ARTICLE_FONT_SIZE, value);
99100
}
101+
102+
static String getErrorLog() {
103+
return sp.getString(StoreKeys.ERROR_LOG) ?? "";
104+
}
105+
106+
static void setErrorLog(String value) {
107+
sp.setString(StoreKeys.ERROR_LOG, value);
108+
}
100109
}

0 commit comments

Comments
 (0)