mirror of
https://github.com/lifegpc/eh_downloader_flutter.git
synced 2026-06-06 05:49:03 +08:00
Update
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import '../globals.dart';
|
||||
|
||||
part 'gallery.g.dart';
|
||||
|
||||
@@ -48,6 +49,11 @@ class GMeta {
|
||||
static int _toJson(DateTime posted) => posted.millisecondsSinceEpoch ~/ 1000;
|
||||
factory GMeta.fromJson(Map<String, dynamic> json) => _$GMetaFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$GMetaToJson(this);
|
||||
String get preferredTitle => prefs.getBool("useTitleJpn") == true
|
||||
? titleJpn.isEmpty
|
||||
? title
|
||||
: titleJpn
|
||||
: title;
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
|
||||
@@ -50,6 +50,7 @@ class _GalleriesPage extends State<GalleriesPage> with ThemeModeWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
tryInitApi(context);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: IconButton(
|
||||
@@ -69,7 +70,7 @@ class _GalleriesPage extends State<GalleriesPage> with ThemeModeWidget {
|
||||
builderDelegate: PagedChildBuilderDelegate<GMeta>(
|
||||
itemBuilder: (context, item, index) {
|
||||
return ListTile(
|
||||
title: SelectableText(item.title),
|
||||
title: Text(item.preferredTitle),
|
||||
onTap: () {
|
||||
context.push("/gallery/${item.gid}");
|
||||
},
|
||||
|
||||
88
lib/gallery.dart
Normal file
88
lib/gallery.dart
Normal file
@@ -0,0 +1,88 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'api/gallery.dart';
|
||||
import 'globals.dart';
|
||||
|
||||
final _log = Logger("GalleryPage");
|
||||
|
||||
class GalleryPage extends StatefulWidget {
|
||||
const GalleryPage(int gid, {Key? key})
|
||||
: _gid = gid,
|
||||
super(key: key);
|
||||
|
||||
final int _gid;
|
||||
static const String routeName = '/gallery/:gid';
|
||||
|
||||
@override
|
||||
State<GalleryPage> createState() => _GalleryPage();
|
||||
}
|
||||
|
||||
class _GalleryPage extends State<GalleryPage> with ThemeModeWidget {
|
||||
_GalleryPage();
|
||||
int _gid = 0;
|
||||
GalleryData? _data;
|
||||
Object? _error;
|
||||
bool _isLoading = false;
|
||||
|
||||
Future<void> _fetchData() async {
|
||||
try {
|
||||
_isLoading = true;
|
||||
final data = (await api.getGallery(_gid)).unwrap();
|
||||
setState(() {
|
||||
_data = data;
|
||||
_isLoading = false;
|
||||
});
|
||||
} catch (e) {
|
||||
_log.severe("Failed to load gallery $_gid:", e);
|
||||
setState(() {
|
||||
_error = e;
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_gid = widget._gid;
|
||||
_data = null;
|
||||
_error = null;
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
tryInitApi(context);
|
||||
final isLoading = _data == null && _error == null;
|
||||
if (isLoading && !_isLoading) _fetchData();
|
||||
final title = isLoading
|
||||
? AppLocalizations.of(context)!.loading
|
||||
: _data != null
|
||||
? _data!.meta.preferredTitle
|
||||
: AppLocalizations.of(context)!.gallery;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () {
|
||||
context.canPop() ? context.pop() : context.go("/");
|
||||
},
|
||||
),
|
||||
title: _data != null ? SelectableText(title) : Text(title),
|
||||
actions: [
|
||||
buildThemeModeIcon(context),
|
||||
buildMoreVertSettingsButon(context),
|
||||
],
|
||||
),
|
||||
body: isLoading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: _data != null
|
||||
? Center(
|
||||
child: Text("Gallery $_gid"),
|
||||
)
|
||||
: Center(
|
||||
child: Text("Error: $_error"),
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -19,5 +19,8 @@
|
||||
"lang": "Language",
|
||||
"systemLang": "System Language",
|
||||
"reset": "Reset",
|
||||
"galleries": "Galleries"
|
||||
"galleries": "Galleries",
|
||||
"loading": "Loading...",
|
||||
"gallery": "Gallery",
|
||||
"useTitleJpn": "Use Japanese title first"
|
||||
}
|
||||
|
||||
@@ -19,5 +19,8 @@
|
||||
"lang": "语言",
|
||||
"systemLang": "系统语言",
|
||||
"reset": "重置",
|
||||
"galleries": "画廊"
|
||||
"galleries": "画廊",
|
||||
"loading": "加载中…",
|
||||
"gallery": "画廊",
|
||||
"useTitleJpn": "优先使用日语标题"
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import 'package:logging/logging.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
import 'create_root_user.dart';
|
||||
import 'galleries.dart';
|
||||
import 'gallery.dart';
|
||||
import 'globals.dart';
|
||||
import 'home.dart';
|
||||
import 'login.dart';
|
||||
@@ -16,6 +17,8 @@ import 'set_server.dart';
|
||||
import 'settings.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
final _routerLog = Logger("Router");
|
||||
|
||||
final _router = GoRouter(
|
||||
routes: [
|
||||
GoRoute(
|
||||
@@ -41,6 +44,24 @@ final _router = GoRouter(
|
||||
GoRoute(
|
||||
path: GalleriesPage.routeName,
|
||||
builder: (context, state) => const GalleriesPage(),
|
||||
),
|
||||
GoRoute(
|
||||
path: GalleryPage.routeName,
|
||||
builder: (context, state) => GalleryPage(
|
||||
int.parse(state.pathParameters["gid"]!),
|
||||
),
|
||||
redirect: (context, state) {
|
||||
try {
|
||||
int.parse(state.pathParameters["gid"]!);
|
||||
return null;
|
||||
} catch (e) {
|
||||
_routerLog.warning("Failed to parse gid:", e);
|
||||
return "/";
|
||||
}
|
||||
}),
|
||||
GoRoute(
|
||||
path: "/gallery",
|
||||
redirect: (context, state) => "/galleries",
|
||||
)
|
||||
],
|
||||
);
|
||||
@@ -87,6 +108,7 @@ void main() async {
|
||||
await windowManager.ensureInitialized();
|
||||
}
|
||||
await initLogger();
|
||||
GoRouter.optionURLReflectsImperativeAPIs = true;
|
||||
runApp(const MainApp());
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,9 @@ class SettingsPage extends StatefulWidget {
|
||||
|
||||
class _SettingsPage extends State<SettingsPage> with ThemeModeWidget {
|
||||
Lang _oriLang = Lang.system;
|
||||
bool _oriUseTitleJpn = false;
|
||||
Lang _lang = Lang.system;
|
||||
bool _useTitleJpn = false;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -30,6 +32,14 @@ class _SettingsPage extends State<SettingsPage> with ThemeModeWidget {
|
||||
_oriLang = Lang.system;
|
||||
_lang = Lang.system;
|
||||
}
|
||||
try {
|
||||
_oriUseTitleJpn = prefs.getBool("useTitleJpn") ?? false;
|
||||
_useTitleJpn = _oriUseTitleJpn;
|
||||
} catch (e) {
|
||||
_log.warning("Failed to get useTitleJpn:", e);
|
||||
_oriUseTitleJpn = false;
|
||||
_useTitleJpn = false;
|
||||
}
|
||||
}
|
||||
|
||||
void fallback(BuildContext context) {
|
||||
@@ -42,17 +52,26 @@ class _SettingsPage extends State<SettingsPage> with ThemeModeWidget {
|
||||
if (_lang != Lang.system) MainApp.of(context).changeLang(Lang.system);
|
||||
setState(() {
|
||||
_lang = Lang.system;
|
||||
_useTitleJpn = false;
|
||||
});
|
||||
}
|
||||
|
||||
Future<bool> save() async {
|
||||
bool re = true;
|
||||
if (!await prefs.setInt("lang", _lang.index)) {
|
||||
if (_lang != _oriLang && !await prefs.setInt("lang", _lang.index)) {
|
||||
re = false;
|
||||
_log.warning("Failed to save lang.");
|
||||
} else {
|
||||
_oriLang = _lang;
|
||||
}
|
||||
if (_oriUseTitleJpn != _useTitleJpn) {
|
||||
if (!await prefs.setBool("useTitleJpn", _useTitleJpn)) {
|
||||
re = false;
|
||||
_log.warning("Failed to save useTitleJpn.");
|
||||
} else {
|
||||
_oriUseTitleJpn = _useTitleJpn;
|
||||
}
|
||||
}
|
||||
return re;
|
||||
}
|
||||
|
||||
@@ -111,6 +130,21 @@ class _SettingsPage extends State<SettingsPage> with ThemeModeWidget {
|
||||
.toList(),
|
||||
leadingIcon: const Icon(Icons.language),
|
||||
)),
|
||||
Container(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 8),
|
||||
child: CheckboxMenuButton(
|
||||
value: _useTitleJpn,
|
||||
onChanged: (bool? value) {
|
||||
if (value != null) {
|
||||
setState(() {
|
||||
_useTitleJpn = value;
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Text(AppLocalizations.of(context)!
|
||||
.useTitleJpn),
|
||||
)),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
|
||||
@@ -298,7 +298,7 @@ packages:
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_web_plugins:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
|
||||
@@ -19,6 +19,8 @@ dependencies:
|
||||
flutter_hooks: ^0.20.0
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
flutter_web_plugins:
|
||||
sdk: flutter
|
||||
go_router: ^10.1.0
|
||||
infinite_scroll_pagination: ^4.0.0
|
||||
intl: any
|
||||
|
||||
Reference in New Issue
Block a user