Improve the UI of comic source list.

This commit is contained in:
2025-04-24 17:20:16 +08:00
parent f38129133a
commit af456c52f1
4 changed files with 153 additions and 109 deletions

View File

@@ -387,9 +387,10 @@
"Screen center": "屏幕中心", "Screen center": "屏幕中心",
"Suggestions": "建议", "Suggestions": "建议",
"Do not report any issues related to sources to App repo.": "请不要向App仓库报告任何与源相关的问题", "Do not report any issues related to sources to App repo.": "请不要向App仓库报告任何与源相关的问题",
"Click the setting icon to change the source list url.": "点击设置图标更改源列表URL",
"Show single image on first page": "在首页显示单张图片", "Show single image on first page": "在首页显示单张图片",
"Click to select an image": "点击选择一张图片" "Click to select an image": "点击选择一张图片",
"Source URL": "源地址",
"The URL should point to a 'index.json' file": "该URL应指向一个'index.json'文件"
}, },
"zh_TW": { "zh_TW": {
"Home": "首頁", "Home": "首頁",
@@ -779,8 +780,9 @@
"Screen center": "螢幕中心", "Screen center": "螢幕中心",
"Suggestions": "建議", "Suggestions": "建議",
"Do not report any issues related to sources to App repo.": "請不要向App倉庫報告任何與源相關的問題", "Do not report any issues related to sources to App repo.": "請不要向App倉庫報告任何與源相關的問題",
"Click the setting icon to change the source list url.": "點擊設定圖示更改源列表URL",
"Show single image on first page": "在首頁顯示單張圖片", "Show single image on first page": "在首頁顯示單張圖片",
"Click to select an image": "點擊選擇一張圖片" "Click to select an image": "點擊選擇一張圖片",
"Source URL": "源地址",
"The URL should point to a 'index.json' file": "該URL應指向一個'index.json'文件"
} }
} }

View File

@@ -178,8 +178,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': defaultComicSourceUrl,
"https://cdn.jsdelivr.net/gh/venera-app/venera-configs@latest/index.json",
'preloadImageCount': 4, 'preloadImageCount': 4,
'followUpdatesFolder': null, 'followUpdatesFolder': null,
'initialPage': '0', 'initialPage': '0',
@@ -220,3 +219,5 @@ function processImage(image, cid, eid, page, sourceKey) {
return futureImage; return futureImage;
} }
'''; ''';
const defaultComicSourceUrl = "https://cdn.jsdelivr.net/gh/venera-app/venera-configs@latest/index.json";

View File

@@ -322,127 +322,168 @@ class _ComicSourceList extends StatefulWidget {
} }
class _ComicSourceListState extends State<_ComicSourceList> { class _ComicSourceListState extends State<_ComicSourceList> {
bool loading = true;
List? json; List? json;
bool changed = false;
var controller = TextEditingController();
void load() async { void load() async {
var dio = AppDio(); if (json != null) {
var res = await dio.get<String>(appdata.settings['comicSourceListUrl']); setState(() {
if (res.statusCode != 200) { json = null;
context.showMessage(message: "Network error".tl); });
return; }
var dio = AppDio();
try {
var res = await dio.get<String>(controller.text);
if (res.statusCode != 200) {
throw "error";
}
if (mounted) {
setState(() {
json = jsonDecode(res.data!);
});
}
}
catch(e) {
context.showMessage(message: "Network error".tl);
if (mounted) {
setState(() {
json = [];
});
}
}
}
@override
void initState() {
super.initState();
controller.text = appdata.settings['comicSourceListUrl'];
load();
}
@override
void dispose() {
super.dispose();
if (changed) {
appdata.settings['comicSourceListUrl'] = controller.text;
appdata.saveData();
} }
setState(() {
json = jsonDecode(res.data!);
loading = false;
});
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return PopUpWidgetScaffold( return PopUpWidgetScaffold(
title: "Comic Source".tl, title: "Comic Source".tl,
tailing: [
IconButton(
icon: Icon(Icons.settings),
onPressed: () async {
await showInputDialog(
context: context,
title: "Set comic source list url".tl,
initialValue: appdata.settings['comicSourceListUrl'],
onConfirm: (value) {
appdata.settings['comicSourceListUrl'] = value;
appdata.saveData();
setState(() {
loading = true;
json = null;
});
return null;
},
);
},
)
],
body: buildBody(), body: buildBody(),
); );
} }
Widget buildBody() { Widget buildBody() {
if (loading) { var currentKey = ComicSource.all().map((e) => e.key).toList();
load();
return const Center(child: CircularProgressIndicator()); return ListView.builder(
} else { itemCount: (json?.length ?? 1) + 1,
var currentKey = ComicSource.all().map((e) => e.key).toList(); itemBuilder: (context, index) {
return ListView.builder( if (index == 0) {
itemCount: json!.length + 1, return Container(
itemBuilder: (context, index) { margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 8),
if (index == 0) { decoration: BoxDecoration(
return Container( border: Border.all(
margin: const EdgeInsets.symmetric(horizontal: 12), color: Theme.of(context).colorScheme.outlineVariant,
padding: const EdgeInsets.all(8), width: 0.6,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: context.colorScheme.primaryContainer,
), ),
child: Row( borderRadius: BorderRadius.circular(8),
children: [ ),
const Icon(Icons.info_outline), child: Column(
const SizedBox(width: 8), crossAxisAlignment: CrossAxisAlignment.start,
Expanded( children: [
child: Column( ListTile(
crossAxisAlignment: CrossAxisAlignment.start, leading: Icon(Icons.source_outlined),
children: [ title: Text("Source URL".tl),
Text("Do not report any issues related to sources to App repo.".tl), ),
Text("Click the setting icon to change the source list url.".tl), TextField(
], controller: controller,
), decoration: InputDecoration(
hintText: "URL",
border: const UnderlineInputBorder(),
contentPadding:
const EdgeInsets.symmetric(horizontal: 12),
), ),
], onChanged: (value) {
), changed = true;
);
}
index--;
var key = json![index]["key"];
var action = currentKey.contains(key)
? const Icon(Icons.check, size: 20).paddingRight(8)
: Button.filled(
child: Text("Add".tl),
onPressed: () async {
var fileName = json![index]["fileName"];
var url = json![index]["url"];
if (url == null || !(url.toString()).isURL) {
var listUrl =
appdata.settings['comicSourceListUrl'] as String;
if (listUrl
.replaceFirst("https://", "")
.replaceFirst("http://", "")
.contains("/")) {
url =
listUrl.substring(0, listUrl.lastIndexOf("/") + 1) +
fileName;
} else {
url = '$listUrl/$fileName';
}
}
await widget.onAdd(url);
setState(() {});
}, },
).fixHeight(32); ).paddingHorizontal(16).paddingBottom(8),
Text("The URL should point to a 'index.json' file".tl).paddingLeft(16),
var description = json![index]["version"]; Text("Do not report any issues related to sources to App repo.".tl).paddingLeft(16),
if (json![index]["description"] != null) { const SizedBox(height: 8),
description = "$description\n${json![index]["description"]}"; Row(
} mainAxisAlignment: MainAxisAlignment.end,
children: [
return ListTile( TextButton(
title: Text(json![index]["name"]), onPressed: () {
subtitle: Text(description), controller.text = defaultComicSourceUrl;
trailing: action, changed = true;
},
child: Text("Reset".tl),
),
FilledButton.tonal(
onPressed: load,
child: Text("Refresh".tl),
),
const SizedBox(width: 16),
],
),
const SizedBox(height: 16),
],
),
); );
}, }
);
} if (index == 1 && json == null) {
return Center(child: CircularProgressIndicator());
}
index--;
var key = json![index]["key"];
var action = currentKey.contains(key)
? const Icon(Icons.check, size: 20).paddingRight(8)
: Button.filled(
child: Text("Add".tl),
onPressed: () async {
var fileName = json![index]["fileName"];
var url = json![index]["url"];
if (url == null || !(url.toString()).isURL) {
var listUrl =
appdata.settings['comicSourceListUrl'] as String;
if (listUrl
.replaceFirst("https://", "")
.replaceFirst("http://", "")
.contains("/")) {
url =
listUrl.substring(0, listUrl.lastIndexOf("/") + 1) +
fileName;
} else {
url = '$listUrl/$fileName';
}
}
await widget.onAdd(url);
setState(() {});
},
).fixHeight(32);
var description = json![index]["version"];
if (json![index]["description"] != null) {
description = "$description\n${json![index]["description"]}";
}
return ListTile(
title: Text(json![index]["name"]),
subtitle: Text(description),
trailing: action,
);
},
);
} }
} }

View File

@@ -1100,4 +1100,4 @@ packages:
version: "0.0.12" version: "0.0.12"
sdks: sdks:
dart: ">=3.7.0 <4.0.0" dart: ">=3.7.0 <4.0.0"
flutter: ">=3.29.2" flutter: ">=3.29.3"