This commit is contained in:
nyne
2024-11-02 18:59:41 +08:00
parent 98ae67a6a5
commit 877e2d5e63
3 changed files with 181 additions and 21 deletions

View File

@@ -147,7 +147,11 @@
"A cbz file" : "一个cbz文件", "A cbz file" : "一个cbz文件",
"Fullscreen": "全屏", "Fullscreen": "全屏",
"Exit": "退出", "Exit": "退出",
"View more": "查看更多" "View more": "查看更多",
"Sort": "排序",
"Name": "名称",
"Date": "日期",
"Date Desc": "日期降序"
}, },
"zh_TW": { "zh_TW": {
"Home": "首頁", "Home": "首頁",
@@ -297,6 +301,10 @@
"A cbz file" : "一個cbz文件", "A cbz file" : "一個cbz文件",
"Fullscreen": "全螢幕", "Fullscreen": "全螢幕",
"Exit": "退出", "Exit": "退出",
"View more": "查看更多" "View more": "查看更多",
"Sort": "排序",
"Name": "名稱",
"Date": "日期",
"Date Desc": "日期降序"
} }
} }

View File

@@ -261,8 +261,14 @@ class LocalManager with ChangeNotifier {
notifyListeners(); notifyListeners();
} }
List<LocalComic> getComics() { List<LocalComic> getComics(LocalSortType sortType) {
final res = _db.select('SELECT * FROM comics;'); var res = _db.select('''
SELECT * FROM comics
ORDER BY
${sortType.value == 'name' ? 'title' : 'created_at'}
${sortType.value == 'time_asc' ? 'ASC' : 'DESC'}
;
''');
return res.map((row) => LocalComic.fromRow(row)).toList(); return res.map((row) => LocalComic.fromRow(row)).toList();
} }
@@ -310,6 +316,15 @@ class LocalManager with ChangeNotifier {
return LocalComic.fromRow(res.first); return LocalComic.fromRow(res.first);
} }
List<LocalComic> search(String keyword) {
final res = _db.select('''
SELECT * FROM comics
WHERE title LIKE ? OR tags LIKE ? OR subtitle LIKE ?
ORDER BY created_at DESC;
''', ['%$keyword%', '%$keyword%', '%$keyword%']);
return res.map((row) => LocalComic.fromRow(row)).toList();
}
Future<List<String>> getImages(String id, ComicType type, Object ep) async { Future<List<String>> getImages(String id, ComicType type, Object ep) async {
if(ep is! String && ep is! int) { if(ep is! String && ep is! int) {
throw "Invalid ep"; throw "Invalid ep";
@@ -429,3 +444,22 @@ class LocalManager with ChangeNotifier {
notifyListeners(); notifyListeners();
} }
} }
enum LocalSortType {
name("name"),
timeAsc("time_asc"),
timeDesc("time_desc");
final String value;
const LocalSortType(this.value);
static LocalSortType fromString(String value) {
for (var type in values) {
if (type.value == value) {
return type;
}
}
return name;
}
}

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:venera/components/components.dart'; import 'package:venera/components/components.dart';
import 'package:venera/foundation/app.dart'; import 'package:venera/foundation/app.dart';
import 'package:venera/foundation/appdata.dart';
import 'package:venera/foundation/local.dart'; import 'package:venera/foundation/local.dart';
import 'package:venera/pages/downloading_page.dart'; import 'package:venera/pages/downloading_page.dart';
import 'package:venera/utils/cbz.dart'; import 'package:venera/utils/cbz.dart';
@@ -17,15 +18,29 @@ class LocalComicsPage extends StatefulWidget {
class _LocalComicsPageState extends State<LocalComicsPage> { class _LocalComicsPageState extends State<LocalComicsPage> {
late List<LocalComic> comics; late List<LocalComic> comics;
late LocalSortType sortType;
String keyword = "";
bool searchMode = false;
void update() { void update() {
setState(() { if(keyword.isEmpty) {
comics = LocalManager().getComics(); setState(() {
}); comics = LocalManager().getComics(sortType);
});
} else {
setState(() {
comics = LocalManager().search(keyword);
});
}
} }
@override @override
void initState() { void initState() {
comics = LocalManager().getComics(); var sort = appdata.implicitData["local_sort"] ?? "name";
sortType = LocalSortType.fromString(sort);
comics = LocalManager().getComics(sortType);
LocalManager().addListener(update); LocalManager().addListener(update);
super.initState(); super.initState();
} }
@@ -36,25 +51,129 @@ class _LocalComicsPageState extends State<LocalComicsPage> {
super.dispose(); super.dispose();
} }
void sort() {
showDialog(
context: context,
builder: (context) {
return StatefulBuilder(builder: (context, setState) {
return ContentDialog(
title: "Sort".tl,
content: Column(
children: [
RadioListTile<LocalSortType>(
title: Text("Name".tl),
value: LocalSortType.name,
groupValue: sortType,
onChanged: (v) {
setState(() {
sortType = v!;
});
},
),
RadioListTile<LocalSortType>(
title: Text("Date".tl),
value: LocalSortType.timeAsc,
groupValue: sortType,
onChanged: (v) {
setState(() {
sortType = v!;
});
},
),
RadioListTile<LocalSortType>(
title: Text("Date Desc".tl),
value: LocalSortType.timeDesc,
groupValue: sortType,
onChanged: (v) {
setState(() {
sortType = v!;
});
},
),
],
),
actions: [
FilledButton(
onPressed: () {
appdata.implicitData["local_sort"] =
sortType.value;
appdata.writeImplicitData();
Navigator.pop(context);
update();
},
child: Text("Confirm".tl),
),
],
);
});
},
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
body: SmoothCustomScrollView( body: SmoothCustomScrollView(
slivers: [ slivers: [
SliverAppbar( if(!searchMode)
title: Text("Local".tl), SliverAppbar(
actions: [ title: Text("Local".tl),
Tooltip( actions: [
message: "Downloading".tl, Tooltip(
child: IconButton( message: "Search".tl,
icon: const Icon(Icons.download), child: IconButton(
icon: const Icon(Icons.search),
onPressed: () {
setState(() {
searchMode = true;
});
},
),
),
Tooltip(
message: "Sort".tl,
child: IconButton(
icon: const Icon(Icons.sort),
onPressed: sort,
),
),
Tooltip(
message: "Downloading".tl,
child: IconButton(
icon: const Icon(Icons.download),
onPressed: () {
showPopUpWidget(context, const DownloadingPage());
},
),
)
],
)
else
SliverAppbar(
title: TextField(
autofocus: true,
decoration: InputDecoration(
hintText: "Search".tl,
border: InputBorder.none,
),
onChanged: (v) {
keyword = v;
update();
},
),
actions: [
IconButton(
icon: const Icon(Icons.close),
onPressed: () { onPressed: () {
showPopUpWidget(context, const DownloadingPage()); setState(() {
searchMode = false;
keyword = "";
update();
});
}, },
), ),
) ],
], ),
),
SliverGridComics( SliverGridComics(
comics: comics, comics: comics,
onTap: (c) { onTap: (c) {
@@ -80,8 +199,7 @@ class _LocalComicsPageState extends State<LocalComicsPage> {
var file = await CBZ.export(c as LocalComic); var file = await CBZ.export(c as LocalComic);
await saveFile(filename: file.name, file: file); await saveFile(filename: file.name, file: file);
await file.delete(); await file.delete();
} } catch (e) {
catch (e) {
context.showMessage(message: e.toString()); context.showMessage(message: e.toString());
} }
controller.close(); controller.close();