Skip to content

Commit bc03074

Browse files
appdevelpoMiaoMint
andauthored
feat: error logging for desktop and android (#180)
* feat: error loging for desktop and android * change route from home to setting-bugreport * delete conflict files * feat: extension search and separation by types (#192) * feat: extension search and separation by types * Refactor extensionCards filtering logic * perf: extension load optimisation (#193) * Add logging and share_plus dependencies --------- Co-authored-by: MiaoMint <44718819+MiaoMint@users.noreply.github.com> Co-authored-by: MiaoMint <miaomint@0u0.ren>
1 parent d391ae8 commit bc03074

File tree

13 files changed

+190
-15
lines changed

13 files changed

+190
-15
lines changed

assets/i18n/en.json

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@
4444
"logout": "Logout",
4545
"login": "Login",
4646
"no-data": "No data",
47-
"clear": "Clear"
47+
"clear": "Clear",
48+
"export": "Export"
4849
},
4950
"home": {
5051
"continue-watching": "Continue",
@@ -133,7 +134,13 @@
133134
"proxy-type-socks5": "Socks5",
134135
"proxy-type-http": "HTTP",
135136
"proxy": "Proxy",
136-
"proxy-subtitle": "Proxy address (e.g. username:password@host:port)"
137+
"proxy-subtitle": "Proxy address (e.g. username:password@host:port)",
138+
"log": "Log",
139+
"log-subtitle": "Save log, export log...",
140+
"save-log": "Save Log",
141+
"save-log-subtitle": "Auto save log file",
142+
"export-log": "Export Log",
143+
"export-log-subtitle": "Export log file"
137144
},
138145
"external-player-launching": "Launching {player}",
139146
"detail": {
@@ -186,6 +193,11 @@
186193
"novel-settings": {
187194
"font-size": "Font size"
188195
},
196+
"bugreport": {
197+
"auto-remove-subtitle": "delete in ~ days",
198+
"show-report-dialog": "Show Report Dialog",
199+
"show-report-dialog-subtitle": "Show error report dialog when app starts"
200+
},
189201
"reader": {
190202
"chapters": "Chapters",
191203
"read-now": "Read Now",
@@ -240,6 +252,13 @@
240252
"upgrade": "Upgrade",
241253
"start": "Start"
242254
},
255+
"report": {
256+
"copied": "Copied to clipboard",
257+
"github-bug-report": "Report to Github issue",
258+
"title": "Bug Report",
259+
"copy-message": "Copy error message",
260+
"show-report-checkbox": "Show report dialog when app starts"
261+
},
243262
"anilist": {
244263
"title": "Anilist Tracking",
245264
"login-hint-1": "Seems you haven't login into AniList yet",

assets/i18n/zh.json

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
"save": "保存",
3030
"save-success": "保存成功",
3131
"logout": "登出",
32-
"clear": "清除"
32+
"clear": "清除",
33+
"export": "导出"
3334
},
3435
"home": {
3536
"continue-watching": "继续观看",
@@ -98,15 +99,31 @@
9899
"theme-black": "黑色",
99100
"nsfw": "NSFW",
100101
"nsfw-subtitle": "显示 NSFW 内容",
101-
"network-ua": "Webview User-Agent",
102-
"network-ua-subtitle": "修改 Webview 和扩展的请求头的 User-Agent",
103102
"external-player": "优先使用的视频播放器",
104103
"external-player-subtitle": "当前优先使用的是 {player}",
105104
"external-player-builtin": "内置播放器",
106105
"language-subtitle": "选择软件的语言",
107106
"extension-log": "扩展日志窗口",
108107
"extension-log-subtitle": "用于调试扩展",
109-
"default-reader-mode": "默认漫画阅读模式"
108+
"default-reader-mode": "默认漫画阅读模式",
109+
"network": "网络",
110+
"network-subtitle": "代理, User-Agent...",
111+
"network-ua": "Webview User-Agent",
112+
"network-ua-subtitle": "修改 Webview 和扩展的请求头的 User-Agent",
113+
"proxy-type": "代理类型",
114+
"proxy-type-subtitle": "设置请求时的代理类型",
115+
"proxy-type-direct": "不代理",
116+
"proxy-type-socks4": "Socks4",
117+
"proxy-type-socks5": "Socks5",
118+
"proxy-type-http": "HTTP",
119+
"proxy": "代理",
120+
"proxy-subtitle": "代理地址 (例如 username:password@host:port)",
121+
"log": "日志",
122+
"log-subtitle": "保存日志, 导出日志...",
123+
"save-log": "保存日志",
124+
"save-log-subtitle": "自动保存日志文件",
125+
"export-log": "导出日志",
126+
"export-log-subtitle": "导出日志文件到本地"
110127
},
111128
"external-player-launching": "正在启动 {player}",
112129
"detail": {

lib/main.dart

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'dart:async';
12
import 'dart:convert';
23
import 'dart:io';
34
import 'package:desktop_multi_window/desktop_multi_window.dart';
@@ -7,6 +8,7 @@ import 'package:flutter/services.dart';
78
import 'package:get/get.dart';
89
import 'package:media_kit/media_kit.dart';
910
import 'package:miru_app/controllers/application_controller.dart';
11+
import 'package:miru_app/utils/log.dart';
1012
import 'package:miru_app/utils/miru_directory.dart';
1113
import 'package:miru_app/utils/request.dart';
1214
import 'package:miru_app/views/pages/debug_page.dart';
@@ -20,6 +22,10 @@ import 'package:miru_app/views/widgets/platform_widget.dart';
2022
import 'package:window_manager/window_manager.dart';
2123

2224
void main(List<String> args) async {
25+
FlutterError.onError = (FlutterErrorDetails details) {
26+
logger.severe("", details.exception, details.stack);
27+
};
28+
2329
WidgetsFlutterBinding.ensureInitialized();
2430

2531
// 多窗口
@@ -41,6 +47,7 @@ void main(List<String> args) async {
4147
// 主窗口
4248
await MiruDirectory.ensureInitialized();
4349
await MiruStorage.ensureInitialized();
50+
MiruLog.ensureInitialized();
4451
await ApplicationUtils.ensureInitialized();
4552
await MiruRequest.ensureInitialized();
4653
ExtensionUtils.ensureInitialized();
@@ -81,17 +88,19 @@ void main(List<String> args) async {
8188
);
8289
SystemChrome.setSystemUIOverlayStyle(style);
8390
}
84-
runApp(const MainApp());
91+
runZonedGuarded(() => runApp(const MainApp()), (error, stack) {
92+
logger.severe("", error, stack);
93+
});
8594
}
8695

87-
class MainApp extends fluent.StatefulWidget {
96+
class MainApp extends StatefulWidget {
8897
const MainApp({super.key});
8998

9099
@override
91-
fluent.State<MainApp> createState() => _MainAppState();
100+
State<MainApp> createState() => _MainAppState();
92101
}
93102

94-
class _MainAppState extends fluent.State<MainApp> {
103+
class _MainAppState extends State<MainApp> {
95104
late ApplicationController c;
96105

97106
@override

lib/utils/log.dart

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import 'dart:io';
2+
3+
import 'package:flutter/foundation.dart';
4+
import 'package:logging/logging.dart';
5+
import 'package:miru_app/utils/miru_directory.dart';
6+
import 'package:miru_app/utils/miru_storage.dart';
7+
import 'package:path/path.dart' as path;
8+
9+
final logger = Logger('Miru');
10+
11+
class MiruLog {
12+
static final logFilePath = path.join(MiruDirectory.getDirectory, 'miru.log');
13+
14+
static void ensureInitialized() {
15+
Logger.root.level = Level.ALL;
16+
Logger.root.onRecord.listen((record) {
17+
final log =
18+
'${record.loggerName} ${record.level.name} ${record.time}: ${record.message} ${record.error ?? ''} ${record.stackTrace ?? ''}';
19+
// 如果是开发环境则打印到控制台
20+
if (kReleaseMode) {
21+
writeLogToFile(log);
22+
return;
23+
}
24+
25+
debugPrint(log);
26+
});
27+
}
28+
29+
// 写入日志到文件
30+
static void writeLogToFile(String log) {
31+
if (!MiruStorage.getSetting(SettingKey.saveLog)) {
32+
return;
33+
}
34+
final file = File(logFilePath);
35+
file.writeAsStringSync('$log\n', mode: FileMode.append);
36+
if (file.lengthSync() > 1024 * 1024 * 10) {
37+
file.deleteSync();
38+
}
39+
}
40+
}

lib/utils/miru_storage.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ class MiruStorage {
128128
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0");
129129
await _initSetting(SettingKey.proxy, '');
130130
await _initSetting(SettingKey.proxyType, 'DIRECT');
131+
await _initSetting(SettingKey.saveLog, true);
131132
}
132133

133134
static _initSetting(String key, dynamic value) async {
@@ -185,4 +186,5 @@ class SettingKey {
185186
static String windowsWebviewUA = "WindowsWebviewUA";
186187
static String proxy = "Proxy";
187188
static String proxyType = "ProxyType";
189+
static String saveLog = "SaveLog";
188190
}

lib/views/pages/detail_page.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ class _DetailPageState extends State<DetailPage> {
326326
tag: widget.tag,
327327
),
328328
const SizedBox(width: 8),
329+
329330
if (c.tmdbDetail != null)
330331
fluent.Button(
331332
child: const Padding(

lib/views/pages/settings/settings_page.dart

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import 'dart:io';
22

3+
import 'package:file_picker/file_picker.dart';
34
import 'package:fluent_ui/fluent_ui.dart' as fluent;
45
import 'package:flutter/material.dart';
56
import 'package:flutter_i18n/flutter_i18n.dart';
67
import 'package:get/get.dart';
78
import 'package:miru_app/data/providers/tmdb_provider.dart';
89
import 'package:miru_app/controllers/application_controller.dart';
910
import 'package:miru_app/router/router.dart';
11+
import 'package:miru_app/utils/log.dart';
1012
import 'package:miru_app/utils/request.dart';
1113
import 'package:miru_app/views/dialogs/bt_dialog.dart';
1214
import 'package:miru_app/controllers/extension/extension_repo_controller.dart';
@@ -23,6 +25,7 @@ import 'package:miru_app/utils/miru_storage.dart';
2325
import 'package:miru_app/utils/application.dart';
2426
import 'package:miru_app/views/widgets/list_title.dart';
2527
import 'package:miru_app/views/widgets/platform_widget.dart';
28+
import 'package:share_plus/share_plus.dart';
2629
import 'package:tmdb_api/tmdb_api.dart';
2730
import 'package:url_launcher/url_launcher.dart';
2831

@@ -398,7 +401,10 @@ class _SettingsPageState extends State<SettingsPage> {
398401
title: 'settings.tracking'.i18n,
399402
subTitle: 'settings.tracking-subtitle'.i18n,
400403
),
401-
const SizedBox(height: 10),
404+
const SizedBox(height: 20),
405+
// 高级
406+
ListTitle(title: '高级'.i18n),
407+
const SizedBox(height: 20),
402408
// 网络设置
403409
SettingsExpanderTile(
404410
content: Column(
@@ -453,7 +459,55 @@ class _SettingsPageState extends State<SettingsPage> {
453459
),
454460
const SizedBox(height: 10),
455461
// Debug
456-
if (!Platform.isAndroid)
462+
SettingsExpanderTile(
463+
title: "settings.log".i18n,
464+
subTitle: 'settings.log-subtitle'.i18n,
465+
androidIcon: Icons.report,
466+
icon: fluent.FluentIcons.report_alert,
467+
content: Column(
468+
children: [
469+
SettingsSwitchTile(
470+
title: 'settings.save-log'.i18n,
471+
buildSubtitle: () => 'settings.save-log-subtitle'.i18n,
472+
buildValue: () {
473+
return MiruStorage.getSetting(SettingKey.saveLog);
474+
},
475+
onChanged: (value) {
476+
MiruStorage.setSetting(SettingKey.saveLog, value);
477+
},
478+
),
479+
const SizedBox(height: 10),
480+
// 导出日志
481+
SettingsTile(
482+
title: 'settings.export-log'.i18n,
483+
buildSubtitle: () => 'settings.export-log-subtitle'.i18n,
484+
trailing: PlatformWidget(
485+
androidWidget: TextButton(
486+
onPressed: () {
487+
Share.shareXFiles([XFile(MiruLog.logFilePath)]);
488+
},
489+
child: Text('common.export'.i18n),
490+
),
491+
desktopWidget: fluent.FilledButton(
492+
onPressed: () async {
493+
final path = await FilePicker.platform.saveFile(
494+
type: FileType.custom,
495+
allowedExtensions: ['log'],
496+
fileName: 'miru.log',
497+
);
498+
if (path != null) {
499+
File(MiruLog.logFilePath).copy(path);
500+
}
501+
},
502+
child: Text('common.export'.i18n),
503+
),
504+
),
505+
),
506+
],
507+
),
508+
),
509+
if (!Platform.isAndroid) ...[
510+
const SizedBox(height: 10),
457511
Obx(
458512
() {
459513
final value = c.extensionLogWindowId.value != -1;
@@ -471,7 +525,8 @@ class _SettingsPageState extends State<SettingsPage> {
471525
isCard: true,
472526
);
473527
},
474-
),
528+
)
529+
],
475530
// 关于
476531
const SizedBox(height: 20),
477532
ListTitle(title: 'settings.about'.i18n),

lib/views/widgets/settings/settings_expander_tile.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class SettingsExpanderTile extends StatelessWidget {
6262
buildSubtitle: () => subTitle,
6363
onTap: () {
6464
Get.to(
65-
Scaffold(
65+
() => Scaffold(
6666
appBar: AppBar(
6767
title: Text(title),
6868
),

macos/Flutter/GeneratedPluginRegistrant.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import package_info_plus
1515
import path_provider_foundation
1616
import screen_brightness_macos
1717
import screen_retriever
18+
import share_plus
1819
import url_launcher_macos
1920
import wakelock_plus
2021
import window_manager
@@ -30,6 +31,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
3031
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
3132
ScreenBrightnessMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenBrightnessMacosPlugin"))
3233
ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin"))
34+
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
3335
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
3436
WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))
3537
WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin"))

pubspec.lock

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,14 @@ packages:
201201
url: "https://pub.dev"
202202
source: hosted
203203
version: "4.0.8"
204+
cross_file:
205+
dependency: transitive
206+
description:
207+
name: cross_file
208+
sha256: fedaadfa3a6996f75211d835aaeb8fede285dae94262485698afd832371b9a5e
209+
url: "https://pub.dev"
210+
source: hosted
211+
version: "0.3.3+8"
204212
crypto:
205213
dependency: "direct main"
206214
description:
@@ -687,7 +695,7 @@ packages:
687695
source: hosted
688696
version: "3.0.0"
689697
logging:
690-
dependency: transitive
698+
dependency: "direct main"
691699
description:
692700
name: logging
693701
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
@@ -1078,6 +1086,22 @@ packages:
10781086
url: "https://pub.dev"
10791087
source: hosted
10801088
version: "0.3.8"
1089+
share_plus:
1090+
dependency: "direct main"
1091+
description:
1092+
name: share_plus
1093+
sha256: f74fc3f1cbd99f39760182e176802f693fa0ec9625c045561cfad54681ea93dd
1094+
url: "https://pub.dev"
1095+
source: hosted
1096+
version: "7.2.1"
1097+
share_plus_platform_interface:
1098+
dependency: transitive
1099+
description:
1100+
name: share_plus_platform_interface
1101+
sha256: df08bc3a07d01f5ea47b45d03ffcba1fa9cd5370fb44b3f38c70e42cced0f956
1102+
url: "https://pub.dev"
1103+
source: hosted
1104+
version: "3.3.1"
10811105
shelf:
10821106
dependency: transitive
10831107
description:

pubspec.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ dependencies:
6363
flutter_hls_parser: ^2.0.1
6464
image_gallery_saver: ^2.0.3
6565
flutter_socks_proxy: ^0.0.3
66+
logging: ^1.2.0
67+
share_plus: ^7.2.1
6668

6769
dev_dependencies:
6870
flutter_test:

0 commit comments

Comments
 (0)