From 9d8ade6fe0a8ec9a732e1ae1ae92f01c988e25ad Mon Sep 17 00:00:00 2001 From: nyne Date: Wed, 23 Jul 2025 14:35:27 +0800 Subject: [PATCH] Add log export functionality. --- assets/translation.json | 6 ++- lib/components/components.dart | 3 ++ lib/components/loading.dart | 72 +++++++++++++++------------------- 3 files changed, 38 insertions(+), 43 deletions(-) diff --git a/assets/translation.json b/assets/translation.json index f8b058e..91cd404 100644 --- a/assets/translation.json +++ b/assets/translation.json @@ -404,7 +404,8 @@ "Reload": "重载", "Disable Length Limitation": "禁用长度限制", "Only valid for this run": "仅对本次运行有效", - "Logs": "日志" + "Logs": "日志", + "Export logs": "导出日志" }, "zh_TW": { "Home": "首頁", @@ -811,6 +812,7 @@ "Reload": "重載", "Disable Length Limitation": "禁用長度限制", "Only valid for this run": "僅對本次運行有效", - "Logs": "日誌" + "Logs": "日誌", + "Export logs": "匯出日誌" } } \ No newline at end of file diff --git a/lib/components/components.dart b/lib/components/components.dart index 200c4d5..30350a5 100644 --- a/lib/components/components.dart +++ b/lib/components/components.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:collection'; +import 'dart:convert'; import 'dart:math' as math; import 'dart:ui' as ui; @@ -21,11 +22,13 @@ import 'package:venera/foundation/image_provider/cached_image.dart'; import 'package:venera/foundation/image_provider/history_image_provider.dart'; import 'package:venera/foundation/image_provider/local_comic_image.dart'; import 'package:venera/foundation/local.dart'; +import 'package:venera/foundation/log.dart'; import 'package:venera/foundation/res.dart'; import 'package:venera/network/cloudflare.dart'; import 'package:venera/pages/comic_details_page/comic_page.dart'; import 'package:venera/pages/favorites/favorites_page.dart'; import 'package:venera/utils/ext.dart'; +import 'package:venera/utils/io.dart'; import 'package:venera/utils/tags_translation.dart'; import 'package:venera/utils/translations.dart'; diff --git a/lib/components/loading.dart b/lib/components/loading.dart index 234d0ef..fd65b5c 100644 --- a/lib/components/loading.dart +++ b/lib/components/loading.dart @@ -41,18 +41,22 @@ class NetworkError extends StatelessWidget { ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), Text( cfe == null ? message : "Cloudflare verification required".tl, textAlign: TextAlign.center, maxLines: 3, ), - if (retry != null) - const SizedBox( - height: 12, - ), + TextButton( + onPressed: () { + saveFile( + data: utf8.encode(Log().toString()), + filename: 'log.txt', + ); + }, + child: Text("Export logs".tl), + ), + const SizedBox(height: 8), if (retry != null) if (cfe != null) FilledButton( @@ -74,15 +78,11 @@ class NetworkError extends StatelessWidget { body = Column( children: [ const Appbar(title: Text("")), - Expanded( - child: body, - ) + Expanded(child: body), ], ); } - return Material( - child: body, - ); + return Material(child: body); } } @@ -94,9 +94,7 @@ class ListLoadingIndicator extends StatelessWidget { return const SizedBox( width: double.infinity, height: 80, - child: Center( - child: FiveDotLoadingAnimation(), - ), + child: Center(child: FiveDotLoadingAnimation()), ); } } @@ -108,10 +106,9 @@ class SliverListLoadingIndicator extends StatelessWidget { Widget build(BuildContext context) { // SliverToBoxAdapter can not been lazy loaded. // Use SliverList to make sure the animation can be lazy loaded. - return SliverList.list(children: const [ - SizedBox(), - ListLoadingIndicator(), - ]); + return SliverList.list( + children: const [SizedBox(), ListLoadingIndicator()], + ); } } @@ -178,10 +175,7 @@ abstract class LoadingState } Widget buildError() { - return NetworkError( - message: error!, - retry: retry, - ); + return NetworkError(message: error!, retry: retry); } @override @@ -323,11 +317,7 @@ abstract class MultiPageLoadingState } Widget buildError(BuildContext context, String error) { - return NetworkError( - withAppbar: false, - message: error, - retry: reset, - ); + return NetworkError(withAppbar: false, message: error, retry: reset); } @override @@ -388,7 +378,7 @@ class _FiveDotLoadingAnimationState extends State Colors.green, Colors.blue, Colors.yellow, - Colors.purple + Colors.purple, ]; static const _padding = 12.0; @@ -400,16 +390,15 @@ class _FiveDotLoadingAnimationState extends State @override Widget build(BuildContext context) { return AnimatedBuilder( - animation: _controller, - builder: (context, child) { - return SizedBox( - width: _dotSize * 5 + _padding * 6, - height: _height, - child: Stack( - children: List.generate(5, (index) => buildDot(index)), - ), - ); - }); + animation: _controller, + builder: (context, child) { + return SizedBox( + width: _dotSize * 5 + _padding * 6, + height: _height, + child: Stack(children: List.generate(5, (index) => buildDot(index))), + ); + }, + ); } Widget buildDot(int index) { @@ -417,7 +406,8 @@ class _FiveDotLoadingAnimationState extends State var startValue = index * 0.8; return Positioned( left: index * _dotSize + (index + 1) * _padding, - bottom: (math.sin(math.pi / 2 * (value - startValue).clamp(0, 2))) * + bottom: + (math.sin(math.pi / 2 * (value - startValue).clamp(0, 2))) * (_height - _dotSize), child: Container( width: _dotSize,