This commit is contained in:
2023-09-04 15:42:36 +08:00
parent 4b7ad8161a
commit 20b38ba6da
12 changed files with 868 additions and 10 deletions

View File

@@ -0,0 +1,46 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import '../api/gallery.dart';
import 'thumbnail.dart';
class GalleryBasicInfo extends StatelessWidget {
const GalleryBasicInfo(this.gMeta, this.firstPage, {Key? key, this.fileId})
: super(key: key);
final GMeta gMeta;
final ExtendedPMeta firstPage;
final int? fileId;
@override
Widget build(BuildContext context) {
return SizedBox(
height: 300,
child: Column(children: [
Expanded(
child: Row(children: [
Expanded(flex: 2, child: Thumbnail(firstPage, fileId: fileId)),
Expanded(
flex: 3,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SelectableText(gMeta.preferredTitle),
SelectableText(gMeta.uploader),
SelectableText(gMeta.category),
],
))
])),
Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton(
onPressed: null,
child: Text(AppLocalizations.of(context)!.read)),
ElevatedButton(
onPressed: null,
child: Text(AppLocalizations.of(context)!.download)),
]))
]));
}
}

View File

@@ -0,0 +1,30 @@
import 'package:flutter/material.dart';
import '../api/gallery.dart';
import 'gallery_basic_info.dart';
import 'gallery_info_desktop.dart';
class GalleryInfo extends StatefulWidget {
const GalleryInfo(this.gData, {Key? key}) : super(key: key);
final GalleryData gData;
@override
State<GalleryInfo> createState() => _GalleryInfo();
}
class _GalleryInfo extends State<GalleryInfo> {
@override
Widget build(BuildContext context) {
bool useMobile = MediaQuery.of(context).size.width <= 810;
return LayoutBuilder(builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(minHeight: constraints.maxHeight),
child: useMobile ? Column(children: [
GalleryBasicInfo(widget.gData.meta, widget.gData.pages.first),
],
) : Column(children: [
GalleryInfoDesktop(widget.gData),
],)));
});
}
}

View File

@@ -0,0 +1,56 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import '../api/gallery.dart';
import 'thumbnail.dart';
class GalleryInfoDesktop extends StatelessWidget {
const GalleryInfoDesktop(this.gData, {Key? key, this.fileId})
: super(key: key);
final GalleryData gData;
final int? fileId;
@override
Widget build(BuildContext context) {
final cs = Theme.of(context).colorScheme;
return Container(
alignment: Alignment.topCenter,
child: SizedBox(
height: 400,
width: 1280,
child: Row(children: [
Expanded(
flex: 3, child: Thumbnail(gData.pages.first, fileId: fileId)),
Expanded(
flex: 7,
child: Column(
children: [
SelectableText(gData.meta.title,
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
color: cs.primary)),
gData.meta.titleJpn.isEmpty
? Container()
: SelectableText(gData.meta.titleJpn,
textAlign: TextAlign.center,
style: TextStyle(color: cs.secondary)),
const Divider(indent: 20, endIndent: 20),
Expanded(
child: Row(children: [
SizedBox(
width: 170,
child: Column(children: [
SelectableText(gData.meta.category),
SelectableText(gData.meta.uploader),
])),
const VerticalDivider(indent: 10, endIndent: 10),
Expanded(child: Column(children: [])),
const VerticalDivider(indent: 10, endIndent: 10),
SizedBox(width: 150, child: Column(children: [])),
])),
],
))
])));
}
}

View File

@@ -106,8 +106,10 @@ class _Thumbnail extends State<Thumbnail> {
width: widget.width.toDouble(),
height: widget.height.toDouble(),
child: ImageFiltered(
imageFilter:
ImageFilter.blur(sigmaX: 10, sigmaY: 10),
imageFilter: ImageFilter.blur(
sigmaX: 10,
sigmaY: 10,
tileMode: TileMode.decal),
child: Image.memory(_data!))),
SizedBox(
width: widget.width.toDouble(),

View File

@@ -3,6 +3,7 @@ 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 'components/gallery_info.dart';
import 'components/thumbnail.dart';
import 'globals.dart';
@@ -70,7 +71,9 @@ class _GalleryPage extends State<GalleryPage> with ThemeModeWidget {
context.canPop() ? context.pop() : context.go("/");
},
),
title: _data != null ? SelectableText(title) : Text(title),
title: _data != null
? SelectableText(maxLines: 2, minLines: 1, title)
: Text(title),
actions: [
buildThemeModeIcon(context),
buildMoreVertSettingsButon(context),
@@ -79,9 +82,7 @@ class _GalleryPage extends State<GalleryPage> with ThemeModeWidget {
body: isLoading
? const Center(child: CircularProgressIndicator())
: _data != null
? Center(
child: Thumbnail(_data!.pages[0]!),
)
? GalleryInfo(_data!)
: Center(
child: Text("Error: $_error"),
));

View File

@@ -22,5 +22,8 @@
"galleries": "Galleries",
"loading": "Loading...",
"gallery": "Gallery",
"useTitleJpn": "Use Japanese title first"
"useTitleJpn": "Use Japanese title first",
"showNsfw": "Show NSFW image by default",
"read": "Read",
"download": "Download"
}

View File

@@ -22,5 +22,8 @@
"galleries": "画廊",
"loading": "加载中…",
"gallery": "画廊",
"useTitleJpn": "优先使用日语标题"
"useTitleJpn": "优先使用日语标题",
"showNsfw": "默认显示NSFW图片",
"read": "阅读",
"download": "下载"
}

View File

@@ -126,8 +126,8 @@ class MainApp extends StatefulWidget {
class _MainApp extends State<MainApp> {
ThemeMode _themeMode = ThemeMode.system;
ThemeData _themeData = ThemeData();
ThemeData _darkThemeData = ThemeData.dark();
ThemeData _themeData = ThemeData(useMaterial3: true);
ThemeData _darkThemeData = ThemeData.dark(useMaterial3: true);
ThemeMode get themeMode => _themeMode;
Lang _lang = Lang.system;
Lang get lang => _lang;

View File

@@ -18,8 +18,10 @@ class SettingsPage extends StatefulWidget {
class _SettingsPage extends State<SettingsPage> with ThemeModeWidget {
Lang _oriLang = Lang.system;
bool _oriShowNsfw = false;
bool _oriUseTitleJpn = false;
Lang _lang = Lang.system;
bool _showNsfw = false;
bool _useTitleJpn = false;
@override
void initState() {
@@ -40,6 +42,14 @@ class _SettingsPage extends State<SettingsPage> with ThemeModeWidget {
_oriUseTitleJpn = false;
_useTitleJpn = false;
}
try {
_oriShowNsfw = prefs.getBool("showNsfw") ?? false;
_showNsfw = _oriShowNsfw;
} catch (e) {
_log.warning("Failed to get showNsfw:", e);
_oriShowNsfw = false;
_showNsfw = false;
}
}
void fallback(BuildContext context) {
@@ -53,6 +63,7 @@ class _SettingsPage extends State<SettingsPage> with ThemeModeWidget {
setState(() {
_lang = Lang.system;
_useTitleJpn = false;
_showNsfw = false;
});
}
@@ -72,6 +83,14 @@ class _SettingsPage extends State<SettingsPage> with ThemeModeWidget {
_oriUseTitleJpn = _useTitleJpn;
}
}
if (_oriShowNsfw != _showNsfw) {
if (!await prefs.setBool("showNsfw", _showNsfw)) {
re = false;
_log.warning("Failed to save showNsfw.");
} else {
_oriShowNsfw = _showNsfw;
}
}
return re;
}
@@ -145,6 +164,21 @@ class _SettingsPage extends State<SettingsPage> with ThemeModeWidget {
child: Text(AppLocalizations.of(context)!
.useTitleJpn),
)),
Container(
padding: const EdgeInsets.symmetric(vertical: 8),
child: CheckboxMenuButton(
value: _showNsfw,
onChanged: (bool? value) {
if (value != null) {
setState(() {
_showNsfw = value;
});
}
},
child: Text(
AppLocalizations.of(context)!.showNsfw),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [