mirror of
https://github.com/venera-app/venera.git
synced 2025-09-27 15:57:25 +00:00
Compare commits
3 Commits
f822e198ea
...
9d8ade6fe0
Author | SHA1 | Date | |
---|---|---|---|
9d8ade6fe0 | |||
6245399810 | |||
c074e7f9d1 |
@@ -404,7 +404,8 @@
|
|||||||
"Reload": "重载",
|
"Reload": "重载",
|
||||||
"Disable Length Limitation": "禁用长度限制",
|
"Disable Length Limitation": "禁用长度限制",
|
||||||
"Only valid for this run": "仅对本次运行有效",
|
"Only valid for this run": "仅对本次运行有效",
|
||||||
"Logs": "日志"
|
"Logs": "日志",
|
||||||
|
"Export logs": "导出日志"
|
||||||
},
|
},
|
||||||
"zh_TW": {
|
"zh_TW": {
|
||||||
"Home": "首頁",
|
"Home": "首頁",
|
||||||
@@ -811,6 +812,7 @@
|
|||||||
"Reload": "重載",
|
"Reload": "重載",
|
||||||
"Disable Length Limitation": "禁用長度限制",
|
"Disable Length Limitation": "禁用長度限制",
|
||||||
"Only valid for this run": "僅對本次運行有效",
|
"Only valid for this run": "僅對本次運行有效",
|
||||||
"Logs": "日誌"
|
"Logs": "日誌",
|
||||||
|
"Export logs": "匯出日誌"
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,5 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
import 'dart:convert';
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
import 'dart:ui' as ui;
|
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/history_image_provider.dart';
|
||||||
import 'package:venera/foundation/image_provider/local_comic_image.dart';
|
import 'package:venera/foundation/image_provider/local_comic_image.dart';
|
||||||
import 'package:venera/foundation/local.dart';
|
import 'package:venera/foundation/local.dart';
|
||||||
|
import 'package:venera/foundation/log.dart';
|
||||||
import 'package:venera/foundation/res.dart';
|
import 'package:venera/foundation/res.dart';
|
||||||
import 'package:venera/network/cloudflare.dart';
|
import 'package:venera/network/cloudflare.dart';
|
||||||
import 'package:venera/pages/comic_details_page/comic_page.dart';
|
import 'package:venera/pages/comic_details_page/comic_page.dart';
|
||||||
import 'package:venera/pages/favorites/favorites_page.dart';
|
import 'package:venera/pages/favorites/favorites_page.dart';
|
||||||
import 'package:venera/utils/ext.dart';
|
import 'package:venera/utils/ext.dart';
|
||||||
|
import 'package:venera/utils/io.dart';
|
||||||
import 'package:venera/utils/tags_translation.dart';
|
import 'package:venera/utils/tags_translation.dart';
|
||||||
import 'package:venera/utils/translations.dart';
|
import 'package:venera/utils/translations.dart';
|
||||||
|
|
||||||
|
@@ -41,18 +41,22 @@ class NetworkError extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(height: 8),
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
Text(
|
Text(
|
||||||
cfe == null ? message : "Cloudflare verification required".tl,
|
cfe == null ? message : "Cloudflare verification required".tl,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
maxLines: 3,
|
maxLines: 3,
|
||||||
),
|
),
|
||||||
if (retry != null)
|
TextButton(
|
||||||
const SizedBox(
|
onPressed: () {
|
||||||
height: 12,
|
saveFile(
|
||||||
|
data: utf8.encode(Log().toString()),
|
||||||
|
filename: 'log.txt',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Text("Export logs".tl),
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
if (retry != null)
|
if (retry != null)
|
||||||
if (cfe != null)
|
if (cfe != null)
|
||||||
FilledButton(
|
FilledButton(
|
||||||
@@ -74,15 +78,11 @@ class NetworkError extends StatelessWidget {
|
|||||||
body = Column(
|
body = Column(
|
||||||
children: [
|
children: [
|
||||||
const Appbar(title: Text("")),
|
const Appbar(title: Text("")),
|
||||||
Expanded(
|
Expanded(child: body),
|
||||||
child: body,
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return Material(
|
return Material(child: body);
|
||||||
child: body,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,9 +94,7 @@ class ListLoadingIndicator extends StatelessWidget {
|
|||||||
return const SizedBox(
|
return const SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: 80,
|
height: 80,
|
||||||
child: Center(
|
child: Center(child: FiveDotLoadingAnimation()),
|
||||||
child: FiveDotLoadingAnimation(),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,10 +106,9 @@ class SliverListLoadingIndicator extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// SliverToBoxAdapter can not been lazy loaded.
|
// SliverToBoxAdapter can not been lazy loaded.
|
||||||
// Use SliverList to make sure the animation can be lazy loaded.
|
// Use SliverList to make sure the animation can be lazy loaded.
|
||||||
return SliverList.list(children: const [
|
return SliverList.list(
|
||||||
SizedBox(),
|
children: const [SizedBox(), ListLoadingIndicator()],
|
||||||
ListLoadingIndicator(),
|
);
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,10 +175,7 @@ abstract class LoadingState<T extends StatefulWidget, S extends Object>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget buildError() {
|
Widget buildError() {
|
||||||
return NetworkError(
|
return NetworkError(message: error!, retry: retry);
|
||||||
message: error!,
|
|
||||||
retry: retry,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -323,11 +317,7 @@ abstract class MultiPageLoadingState<T extends StatefulWidget, S extends Object>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget buildError(BuildContext context, String error) {
|
Widget buildError(BuildContext context, String error) {
|
||||||
return NetworkError(
|
return NetworkError(withAppbar: false, message: error, retry: reset);
|
||||||
withAppbar: false,
|
|
||||||
message: error,
|
|
||||||
retry: reset,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -388,7 +378,7 @@ class _FiveDotLoadingAnimationState extends State<FiveDotLoadingAnimation>
|
|||||||
Colors.green,
|
Colors.green,
|
||||||
Colors.blue,
|
Colors.blue,
|
||||||
Colors.yellow,
|
Colors.yellow,
|
||||||
Colors.purple
|
Colors.purple,
|
||||||
];
|
];
|
||||||
|
|
||||||
static const _padding = 12.0;
|
static const _padding = 12.0;
|
||||||
@@ -405,11 +395,10 @@ class _FiveDotLoadingAnimationState extends State<FiveDotLoadingAnimation>
|
|||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: _dotSize * 5 + _padding * 6,
|
width: _dotSize * 5 + _padding * 6,
|
||||||
height: _height,
|
height: _height,
|
||||||
child: Stack(
|
child: Stack(children: List.generate(5, (index) => buildDot(index))),
|
||||||
children: List.generate(5, (index) => buildDot(index)),
|
);
|
||||||
),
|
},
|
||||||
);
|
);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildDot(int index) {
|
Widget buildDot(int index) {
|
||||||
@@ -417,7 +406,8 @@ class _FiveDotLoadingAnimationState extends State<FiveDotLoadingAnimation>
|
|||||||
var startValue = index * 0.8;
|
var startValue = index * 0.8;
|
||||||
return Positioned(
|
return Positioned(
|
||||||
left: index * _dotSize + (index + 1) * _padding,
|
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),
|
(_height - _dotSize),
|
||||||
child: Container(
|
child: Container(
|
||||||
width: _dotSize,
|
width: _dotSize,
|
||||||
|
@@ -189,7 +189,7 @@ class Settings with ChangeNotifier {
|
|||||||
'customImageProcessing': defaultCustomImageProcessing,
|
'customImageProcessing': defaultCustomImageProcessing,
|
||||||
'sni': true,
|
'sni': true,
|
||||||
'autoAddLanguageFilter': 'none', // none, chinese, english, japanese
|
'autoAddLanguageFilter': 'none', // none, chinese, english, japanese
|
||||||
'comicSourceListUrl': '',
|
'comicSourceListUrl': _defaultSourceListUrl,
|
||||||
'preloadImageCount': 4,
|
'preloadImageCount': 4,
|
||||||
'followUpdatesFolder': null,
|
'followUpdatesFolder': null,
|
||||||
'initialPage': '0',
|
'initialPage': '0',
|
||||||
@@ -235,3 +235,5 @@ function processImage(image, cid, eid, page, sourceKey) {
|
|||||||
return futureImage;
|
return futureImage;
|
||||||
}
|
}
|
||||||
''';
|
''';
|
||||||
|
|
||||||
|
const _defaultSourceListUrl = "https://git.nyne.dev/nyne/venera-configs/raw/branch/main/index.json";
|
||||||
|
@@ -191,13 +191,6 @@ class _BodyState extends State<_Body> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget buildCard(BuildContext context) {
|
Widget buildCard(BuildContext context) {
|
||||||
Widget buildButton({
|
|
||||||
required Widget child,
|
|
||||||
required VoidCallback onPressed,
|
|
||||||
}) {
|
|
||||||
return Button.normal(onPressed: onPressed, child: child).fixHeight(32);
|
|
||||||
}
|
|
||||||
|
|
||||||
return SliverToBoxAdapter(
|
return SliverToBoxAdapter(
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
@@ -224,10 +217,13 @@ class _BodyState extends State<_Body> {
|
|||||||
},
|
},
|
||||||
onSubmitted: handleAddSource,
|
onSubmitted: handleAddSource,
|
||||||
).paddingHorizontal(16).paddingBottom(8),
|
).paddingHorizontal(16).paddingBottom(8),
|
||||||
ListTile(
|
Wrap(
|
||||||
title: Text("Comic Source list".tl),
|
spacing: 8,
|
||||||
trailing: buildButton(
|
runSpacing: 8,
|
||||||
child: Text("View".tl),
|
children: [
|
||||||
|
FilledButton.tonalIcon(
|
||||||
|
icon: Icon(Icons.article_outlined),
|
||||||
|
label: Text("Comic Source list".tl),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showPopUpWidget(
|
showPopUpWidget(
|
||||||
App.rootContext,
|
App.rootContext,
|
||||||
@@ -235,22 +231,19 @@ class _BodyState extends State<_Body> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
FilledButton.tonalIcon(
|
||||||
ListTile(
|
icon: Icon(Icons.file_open_outlined),
|
||||||
title: Text("Use a config file".tl),
|
label: Text("Use a config file".tl),
|
||||||
trailing: buildButton(
|
|
||||||
onPressed: _selectFile,
|
onPressed: _selectFile,
|
||||||
child: Text("Select".tl),
|
|
||||||
),
|
),
|
||||||
|
FilledButton.tonalIcon(
|
||||||
|
icon: Icon(Icons.help_outline),
|
||||||
|
label: Text("Help".tl),
|
||||||
|
onPressed: help,
|
||||||
),
|
),
|
||||||
ListTile(
|
_CheckUpdatesButton(),
|
||||||
title: Text("Help".tl),
|
],
|
||||||
trailing: buildButton(onPressed: help, child: Text("Open".tl)),
|
).paddingHorizontal(12).paddingVertical(8),
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
title: Text("Check updates".tl),
|
|
||||||
trailing: _CheckUpdatesButton(),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -699,11 +692,15 @@ class _CheckUpdatesButtonState extends State<_CheckUpdatesButton> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Button.normal(
|
return FilledButton.tonalIcon(
|
||||||
|
icon: isLoading ? SizedBox(
|
||||||
|
width: 18,
|
||||||
|
height: 18,
|
||||||
|
child: CircularProgressIndicator(strokeWidth: 2),
|
||||||
|
) : Icon(Icons.update),
|
||||||
|
label: Text("Check updates".tl),
|
||||||
onPressed: check,
|
onPressed: check,
|
||||||
isLoading: isLoading,
|
);
|
||||||
child: Text("Check".tl),
|
|
||||||
).fixHeight(32);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user