From af456c52f1cce848abee43b6bbdda9739c9f39ae Mon Sep 17 00:00:00 2001 From: nyne Date: Thu, 24 Apr 2025 17:20:16 +0800 Subject: [PATCH] Improve the UI of comic source list. --- assets/translation.json | 10 +- lib/foundation/appdata.dart | 5 +- lib/pages/comic_source_page.dart | 245 ++++++++++++++++++------------- pubspec.lock | 2 +- 4 files changed, 153 insertions(+), 109 deletions(-) diff --git a/assets/translation.json b/assets/translation.json index 2d24de1..dc9b37d 100644 --- a/assets/translation.json +++ b/assets/translation.json @@ -387,9 +387,10 @@ "Screen center": "屏幕中心", "Suggestions": "建议", "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": "在首页显示单张图片", - "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": { "Home": "首頁", @@ -779,8 +780,9 @@ "Screen center": "螢幕中心", "Suggestions": "建議", "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": "在首頁顯示單張圖片", - "Click to select an image": "點擊選擇一張圖片" + "Click to select an image": "點擊選擇一張圖片", + "Source URL": "源地址", + "The URL should point to a 'index.json' file": "該URL應指向一個'index.json'文件" } } diff --git a/lib/foundation/appdata.dart b/lib/foundation/appdata.dart index 434681b..7b1a898 100644 --- a/lib/foundation/appdata.dart +++ b/lib/foundation/appdata.dart @@ -178,8 +178,7 @@ class Settings with ChangeNotifier { 'customImageProcessing': defaultCustomImageProcessing, 'sni': true, 'autoAddLanguageFilter': 'none', // none, chinese, english, japanese - 'comicSourceListUrl': - "https://cdn.jsdelivr.net/gh/venera-app/venera-configs@latest/index.json", + 'comicSourceListUrl': defaultComicSourceUrl, 'preloadImageCount': 4, 'followUpdatesFolder': null, 'initialPage': '0', @@ -220,3 +219,5 @@ function processImage(image, cid, eid, page, sourceKey) { return futureImage; } '''; + +const defaultComicSourceUrl = "https://cdn.jsdelivr.net/gh/venera-app/venera-configs@latest/index.json"; diff --git a/lib/pages/comic_source_page.dart b/lib/pages/comic_source_page.dart index 49dd89f..81b9622 100644 --- a/lib/pages/comic_source_page.dart +++ b/lib/pages/comic_source_page.dart @@ -322,127 +322,168 @@ class _ComicSourceList extends StatefulWidget { } class _ComicSourceListState extends State<_ComicSourceList> { - bool loading = true; List? json; + bool changed = false; + var controller = TextEditingController(); void load() async { - var dio = AppDio(); - var res = await dio.get(appdata.settings['comicSourceListUrl']); - if (res.statusCode != 200) { - context.showMessage(message: "Network error".tl); - return; + if (json != null) { + setState(() { + json = null; + }); + } + var dio = AppDio(); + try { + var res = await dio.get(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 Widget build(BuildContext context) { return PopUpWidgetScaffold( 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(), ); } Widget buildBody() { - if (loading) { - load(); - return const Center(child: CircularProgressIndicator()); - } else { - var currentKey = ComicSource.all().map((e) => e.key).toList(); - return ListView.builder( - itemCount: json!.length + 1, - itemBuilder: (context, index) { - if (index == 0) { - return Container( - margin: const EdgeInsets.symmetric(horizontal: 12), - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - color: context.colorScheme.primaryContainer, + var currentKey = ComicSource.all().map((e) => e.key).toList(); + + return ListView.builder( + itemCount: (json?.length ?? 1) + 1, + itemBuilder: (context, index) { + if (index == 0) { + return Container( + margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), + decoration: BoxDecoration( + border: Border.all( + color: Theme.of(context).colorScheme.outlineVariant, + width: 0.6, ), - child: Row( - children: [ - const Icon(Icons.info_outline), - const SizedBox(width: 8), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - 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), - ], - ), + borderRadius: BorderRadius.circular(8), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ListTile( + leading: Icon(Icons.source_outlined), + title: Text("Source URL".tl), + ), + TextField( + controller: controller, + decoration: InputDecoration( + hintText: "URL", + border: const UnderlineInputBorder(), + contentPadding: + const EdgeInsets.symmetric(horizontal: 12), ), - ], - ), - ); - } - 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(() {}); + onChanged: (value) { + changed = true; }, - ).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, + ).paddingHorizontal(16).paddingBottom(8), + Text("The URL should point to a 'index.json' file".tl).paddingLeft(16), + Text("Do not report any issues related to sources to App repo.".tl).paddingLeft(16), + const SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () { + controller.text = defaultComicSourceUrl; + 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, + ); + }, + ); } } diff --git a/pubspec.lock b/pubspec.lock index 94085e8..8677953 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1100,4 +1100,4 @@ packages: version: "0.0.12" sdks: dart: ">=3.7.0 <4.0.0" - flutter: ">=3.29.2" + flutter: ">=3.29.3"