From 9872a3e24282756396f78706ca72a334b97c1efa Mon Sep 17 00:00:00 2001 From: MiaoMint <1981324730@qq.com> Date: Sat, 12 Aug 2023 21:36:12 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/api/tmdb.dart | 4 +- lib/pages/detail/controller.dart | 84 ++++++++-- lib/pages/detail/view.dart | 56 ++----- .../detail/widgets/detail_extension_tile.dart | 9 +- lib/pages/extension/controller.dart | 6 +- lib/pages/extension/view.dart | 13 +- .../widgets/extension_card.dart | 4 +- lib/pages/extension_settings/controller.dart | 2 +- lib/pages/home/widgets/home_resent_card.dart | 2 +- lib/pages/main/view.dart | 154 +++++++++--------- lib/pages/search/controller.dart | 2 +- lib/pages/search/pages/search_extension.dart | 2 +- lib/pages/settings/view.dart | 1 - lib/pages/watch/view.dart | 26 +-- lib/utils/database.dart | 14 +- lib/utils/extension.dart | 4 +- lib/widgets/extension_item_card.dart | 3 +- 17 files changed, 198 insertions(+), 188 deletions(-) diff --git a/lib/api/tmdb.dart b/lib/api/tmdb.dart index 88444acf..67c696e6 100644 --- a/lib/api/tmdb.dart +++ b/lib/api/tmdb.dart @@ -8,7 +8,7 @@ class TmdbApi { defaultLanguage: MiruStorage.getSetting(SettingKey.language), ); - static Future getDetail(String keyword, + static Future getDetail(String keyword, {int page = 1}) async { final result = await tmdb.v3.search.queryMulti( keyword, @@ -17,7 +17,7 @@ class TmdbApi { // print(result); final results = result["results"] as List; if (results.isEmpty) { - throw Exception("No results"); + return null; } late Map data; final mediaType = results[0]["media_type"]; diff --git a/lib/pages/detail/controller.dart b/lib/pages/detail/controller.dart index 4b256b9b..e9f5d4f0 100644 --- a/lib/pages/detail/controller.dart +++ b/lib/pages/detail/controller.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:fluent_ui/fluent_ui.dart' as fluent; import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:get/get.dart'; import 'package:miru_app/api/tmdb.dart'; import 'package:miru_app/models/index.dart'; @@ -49,7 +50,7 @@ class DetailPageController extends GetxController { if (tmdbDetail != null && tmdbDetail!.backdrop != null) { bg = TmdbApi.getImageUrl(tmdbDetail!.backdrop!) ?? ''; } else { - bg = detail!.cover; + bg = detail?.cover ?? ''; } return bg; } @@ -64,11 +65,9 @@ class DetailPageController extends GetxController { } onRefresh() async { - // 获取收藏状态 + runtime.value = ExtensionUtils.runtimes[package]; await refreshFavorite(); try { - // 获取扩展类型 - runtime.value = ExtensionUtils.extensions[package]; _miruDetail = await DatabaseUtils.getMiruDetail(package, url); _tmdbID = _miruDetail?.tmdbID ?? -1; await getDetail(); @@ -95,27 +94,50 @@ class DetailPageController extends GetxController { getRemoteDeatil() async { try { - detail = await ExtensionUtils.extensions[package]?.detail(url); + detail = await runtime.value!.detail(url); await DatabaseUtils.putMiruDetail(package, url, detail!, tmdbID: _tmdbID); } catch (e) { // 弹出错误信息 - showPlatformSnackbar( - context: cuurentContext, - title: 'detail.get-lastest-data-error'.i18n, - content: e.toString().split('\n')[0], - severity: fluent.InfoBarSeverity.error, - ); + if (runtime.value == null) { + final content = FlutterI18n.translate( + cuurentContext, + 'common.extension-missing', + translationParams: { + 'package': package, + }, + ); + showPlatformSnackbar( + context: cuurentContext, + title: '', + content: content, + severity: fluent.InfoBarSeverity.error, + ); + throw content; + } else { + showPlatformSnackbar( + context: cuurentContext, + title: 'detail.get-lastest-data-error'.i18n, + content: e.toString().split('\n')[0], + severity: fluent.InfoBarSeverity.error, + ); + } rethrow; } } getTMDBDetail() async { tmdbDetail = await DatabaseUtils.getTMDBDetail(_tmdbID); + if (detail == null) { + return; + } getRemoteTMDBDetail(); } getRemoteTMDBDetail() async { tmdbDetail = await TmdbApi.getDetail(detail!.title); + if (tmdbDetail == null) { + return; + } _tmdbID = tmdbDetail!.id; DatabaseUtils.putTMDBDetail( tmdbDetail!.id, @@ -151,15 +173,25 @@ class DetailPageController extends GetxController { } toggleFavorite() async { - if (isLoading.value) { + if (detail == null) { return; } - await DatabaseUtils.toggleFavorite( - package: package, - url: url, - cover: detail!.cover, - name: detail!.title, - ); + try { + await DatabaseUtils.toggleFavorite( + package: package, + url: url, + cover: detail!.cover, + name: detail!.title, + ); + } catch (e) { + showPlatformSnackbar( + context: cuurentContext, + title: '', + content: e.toString().split('\n')[0], + severity: fluent.InfoBarSeverity.error, + ); + rethrow; + } await refreshFavorite(); Get.find().onRefresh(); } @@ -170,6 +202,22 @@ class DetailPageController extends GetxController { int index, int selectEpGroup, ) { + if (runtime.value == null) { + showPlatformSnackbar( + context: cuurentContext, + title: '', + content: FlutterI18n.translate( + cuurentContext, + 'common.extension-missing', + translationParams: { + 'package': package, + }, + ), + severity: fluent.InfoBarSeverity.error, + ); + return; + } + Navigator.of(context, rootNavigator: true).push( PageRouteBuilder( transitionDuration: const Duration(milliseconds: 600), diff --git a/lib/pages/detail/view.dart b/lib/pages/detail/view.dart index 8781ccc7..045d1d12 100644 --- a/lib/pages/detail/view.dart +++ b/lib/pages/detail/view.dart @@ -1,7 +1,6 @@ import 'package:fluent_ui/fluent_ui.dart' as fluent; import 'package:flutter/material.dart'; import 'package:flutter_animate/flutter_animate.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:get/get.dart'; import 'package:miru_app/api/tmdb.dart'; import 'package:miru_app/models/extension.dart'; @@ -13,7 +12,6 @@ import 'package:miru_app/pages/detail/widgets/detail_episodes.dart'; import 'package:miru_app/pages/detail/widgets/detail_extension_tile.dart'; import 'package:miru_app/pages/detail/widgets/detail_favorite_button.dart'; import 'package:miru_app/pages/detail/widgets/detail_overview.dart'; -import 'package:miru_app/utils/extension.dart'; import 'package:miru_app/utils/i18n.dart'; import 'package:miru_app/widgets/cache_network_image.dart'; import 'package:miru_app/widgets/card_tile.dart'; @@ -58,19 +56,6 @@ class _DetailPageState extends State { } Widget _buildAndroidDetail(BuildContext context) { - if (!ExtensionUtils.extensions.containsKey(widget.package)) { - return Scaffold( - body: Center( - child: Text(FlutterI18n.translate( - context, - 'common.extension-missing', - translationParams: { - 'package': widget.package, - }, - )), - ), - ); - } return Scaffold( body: Obx(() { late String episodesString; @@ -169,19 +154,6 @@ class _DetailPageState extends State { } Widget _buildDesktopDetail(BuildContext context) { - if (!ExtensionUtils.extensions.containsKey(widget.package)) { - return Center( - child: Text( - FlutterI18n.translate( - context, - 'common.extension-missing', - translationParams: { - 'package': widget.package, - }, - ), - ), - ); - } return Obx(() { if (c.error.value.isNotEmpty) { return Center( @@ -226,15 +198,18 @@ class _DetailPageState extends State { child: Row( children: [ if (constraints.maxWidth > 600) ...[ - Container( - width: 230, - height: double.infinity, - clipBehavior: Clip.antiAlias, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - ), - child: CacheNetWorkImage( - c.detail!.cover, + Hero( + tag: c.heroTag ?? '', + child: Container( + width: 230, + height: double.infinity, + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + ), + child: CacheNetWorkImage( + c.detail?.cover ?? '', + ), ), ), const SizedBox(width: 30), @@ -245,7 +220,7 @@ class _DetailPageState extends State { mainAxisAlignment: MainAxisAlignment.end, children: [ SelectableText( - c.detail!.title, + c.detail?.title ?? '', style: const TextStyle( fontSize: 30, fontWeight: FontWeight.bold, @@ -292,7 +267,7 @@ class _DetailPageState extends State { ), ), const SizedBox(height: 30), - if (c.detail!.episodes != null) const DetailEpisodes(), + if (c.detail?.episodes != null) const DetailEpisodes(), const SizedBox(height: 16), Obx( () { @@ -418,6 +393,9 @@ class _DetailPageState extends State { padding: const EdgeInsets.symmetric(vertical: 8), child: SelectableText( c.tmdbDetail?.overview ?? c.detail?.desc ?? '', + style: const TextStyle( + height: 2, + ), ), ), ), diff --git a/lib/pages/detail/widgets/detail_extension_tile.dart b/lib/pages/detail/widgets/detail_extension_tile.dart index fc9dacf5..f3673101 100644 --- a/lib/pages/detail/widgets/detail_extension_tile.dart +++ b/lib/pages/detail/widgets/detail_extension_tile.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:get/get.dart'; import 'package:miru_app/pages/detail/controller.dart'; import 'package:miru_app/utils/extension.dart'; @@ -12,7 +13,13 @@ class DetailExtensionTile extends StatelessWidget { final c = Get.find(); return Obx(() { if (c.extension == null) { - return const SizedBox.shrink(); + return Text(FlutterI18n.translate( + context, + 'common.extension-missing', + translationParams: { + 'package': c.package, + }, + )); } return Row( children: [ diff --git a/lib/pages/extension/controller.dart b/lib/pages/extension/controller.dart index 07adeb75..a57a20cf 100644 --- a/lib/pages/extension/controller.dart +++ b/lib/pages/extension/controller.dart @@ -3,7 +3,7 @@ import 'package:miru_app/utils/extension.dart'; import 'package:miru_app/utils/extension_runtime.dart'; class ExtensionPageController extends GetxController { - RxMap extensions = {}.obs; + RxMap runtimes = {}.obs; RxMap errors = {}.obs; RxBool isInstallloading = false.obs; @@ -14,9 +14,9 @@ class ExtensionPageController extends GetxController { } onRefresh() async { - extensions.clear(); + runtimes.clear(); errors.clear(); - extensions.addAll(ExtensionUtils.extensions); + runtimes.addAll(ExtensionUtils.runtimes); errors.addAll(ExtensionUtils.extensionErrorMap); } } diff --git a/lib/pages/extension/view.dart b/lib/pages/extension/view.dart index 5b34cbfe..d0bf5fb4 100644 --- a/lib/pages/extension/view.dart +++ b/lib/pages/extension/view.dart @@ -85,9 +85,10 @@ class _ExtensionPageState extends State { // 定位目录 final dir = await ExtensionUtils.getExtensionsDir; if (Platform.isAndroid) { - // 复制 dir Clipboard.setData(ClipboardData(text: dir)); - // ignore: use_build_context_synchronously + if (!mounted) { + return; + } showPlatformSnackbar( context: context, title: 'extension.import.extension-dir'.i18n, @@ -185,7 +186,7 @@ class _ExtensionPageState extends State { body: TabBarView(children: [ ListView( children: [ - if (c.extensions.isEmpty) + if (c.runtimes.isEmpty) SizedBox( height: 300, child: Column( @@ -195,7 +196,7 @@ class _ExtensionPageState extends State { ], ), ), - for (final ext in c.extensions.values) + for (final ext in c.runtimes.values) ExtensionTile(ext.extension), ], ), @@ -240,7 +241,7 @@ class _ExtensionPageState extends State { ], ), const SizedBox(height: 16), - if (c.extensions.isEmpty) + if (c.runtimes.isEmpty) Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -261,7 +262,7 @@ class _ExtensionPageState extends State { Expanded( child: ListView( children: [ - for (final ext in c.extensions.values) + for (final ext in c.runtimes.values) Container( margin: const EdgeInsets.only(bottom: 8), child: ExtensionTile(ext.extension), diff --git a/lib/pages/extension_repo/widgets/extension_card.dart b/lib/pages/extension_repo/widgets/extension_card.dart index 3e9c6328..1f991fb7 100644 --- a/lib/pages/extension_repo/widgets/extension_card.dart +++ b/lib/pages/extension_repo/widgets/extension_card.dart @@ -33,9 +33,9 @@ class _ExtensionCardState extends State { @override void initState() { setState(() { - isInstall = ExtensionUtils.extensions.containsKey(widget.package); + isInstall = ExtensionUtils.runtimes.containsKey(widget.package); hasUpgrade = isInstall && - ExtensionUtils.extensions[widget.package]!.extension.version != + ExtensionUtils.runtimes[widget.package]!.extension.version != widget.version; }); super.initState(); diff --git a/lib/pages/extension_settings/controller.dart b/lib/pages/extension_settings/controller.dart index e9c0a939..9360ed9a 100644 --- a/lib/pages/extension_settings/controller.dart +++ b/lib/pages/extension_settings/controller.dart @@ -19,7 +19,7 @@ class ExtensionSettingsPageController extends GetxController { } onRefresh() async { - runtime.value = ExtensionUtils.extensions[package]; + runtime.value = ExtensionUtils.runtimes[package]; settings.clear(); settings.addAll(await DatabaseUtils.getExtensionSettings(package)); } diff --git a/lib/pages/home/widgets/home_resent_card.dart b/lib/pages/home/widgets/home_resent_card.dart index 6c362943..2f21b294 100644 --- a/lib/pages/home/widgets/home_resent_card.dart +++ b/lib/pages/home/widgets/home_resent_card.dart @@ -41,7 +41,7 @@ class _HomeRecentCardState extends State { } _getUpdate() async { - _runtime = ExtensionUtils.extensions[widget.history.package]; + _runtime = ExtensionUtils.runtimes[widget.history.package]; if (_runtime == null) { return; } diff --git a/lib/pages/main/view.dart b/lib/pages/main/view.dart index 4332e450..56b7b52a 100644 --- a/lib/pages/main/view.dart +++ b/lib/pages/main/view.dart @@ -58,85 +58,85 @@ class _DesktopMainPageState extends State { @override Widget build(BuildContext context) { - return Obx(() => fluent.NavigationView( - appBar: fluent.NavigationAppBar( - leading: () { - return fluent.IconButton( - icon: const Icon(fluent.FluentIcons.back, size: 12.0), - onPressed: () { - if (router.canPop()) { - context.pop(); - setState(() {}); - } - }, - ); - }(), - title: _title(), - actions: SizedBox( - width: 138, - height: 50, - child: WindowCaption( - backgroundColor: Colors.transparent, - brightness: fluent.FluentTheme.of(context).brightness, - ), - ), - automaticallyImplyLeading: false, + return fluent.NavigationView( + appBar: fluent.NavigationAppBar( + leading: () { + return fluent.IconButton( + icon: const Icon(fluent.FluentIcons.back, size: 12.0), + onPressed: () { + if (router.canPop()) { + context.pop(); + setState(() {}); + } + }, + ); + }(), + title: _title(), + actions: SizedBox( + width: 138, + height: 50, + child: WindowCaption( + backgroundColor: Colors.transparent, + brightness: fluent.FluentTheme.of(context).brightness, ), - paneBodyBuilder: (item, body) { - return widget.child; - }, - pane: fluent.NavigationPane( - size: const fluent.NavigationPaneSize(openMaxWidth: 200), - selected: c.selectedTab.value, - onChanged: c.changeTab, - displayMode: fluent.PaneDisplayMode.compact, - footerItems: [ - fluent.PaneItemSeparator(), - fluent.PaneItem( - icon: const Icon(fluent.FluentIcons.repo), - title: Text('common.extension-repo'.i18n), - body: const ExtensionPage(), - onTap: () { - router.go('/extension_repo'); - }, - ), - fluent.PaneItem( - icon: const Icon(fluent.FluentIcons.settings), - title: Text('common.settings'.i18n), - body: const SettingsPage(), - onTap: () { - router.go('/settings'); - }, - ), - ], - items: [ - fluent.PaneItem( - icon: const Icon(fluent.FluentIcons.home), - title: Text('common.home'.i18n), - body: const HomePage(), - onTap: () { - router.go('/'); - }, - ), - fluent.PaneItem( - icon: const Icon(fluent.FluentIcons.search), - title: Text('common.search'.i18n), - body: const SearchPage(), - onTap: () { - router.go('/search'); - }, - ), - fluent.PaneItem( - icon: const Icon(fluent.FluentIcons.add_in), - title: Text('common.extension'.i18n), - body: const ExtensionPage(), - onTap: () { - router.go('/extension'); - }, - ), - ], + ), + automaticallyImplyLeading: false, + ), + paneBodyBuilder: (item, body) { + return widget.child; + }, + pane: fluent.NavigationPane( + size: const fluent.NavigationPaneSize(openMaxWidth: 200), + selected: c.selectedTab.value, + onChanged: c.changeTab, + displayMode: fluent.PaneDisplayMode.compact, + footerItems: [ + fluent.PaneItemSeparator(), + fluent.PaneItem( + icon: const Icon(fluent.FluentIcons.repo), + title: Text('common.extension-repo'.i18n), + body: const ExtensionPage(), + onTap: () { + router.go('/extension_repo'); + }, ), - )); + fluent.PaneItem( + icon: const Icon(fluent.FluentIcons.settings), + title: Text('common.settings'.i18n), + body: const SettingsPage(), + onTap: () { + router.go('/settings'); + }, + ), + ], + items: [ + fluent.PaneItem( + icon: const Icon(fluent.FluentIcons.home), + title: Text('common.home'.i18n), + body: const HomePage(), + onTap: () { + router.go('/'); + }, + ), + fluent.PaneItem( + icon: const Icon(fluent.FluentIcons.search), + title: Text('common.search'.i18n), + body: const SearchPage(), + onTap: () { + router.go('/search'); + }, + ), + fluent.PaneItem( + icon: const Icon(fluent.FluentIcons.add_in), + title: Text('common.extension'.i18n), + body: const ExtensionPage(), + onTap: () { + router.go('/extension'); + }, + ), + ], + ), + ); } } diff --git a/lib/pages/search/controller.dart b/lib/pages/search/controller.dart index aa54c240..5f239d3e 100644 --- a/lib/pages/search/controller.dart +++ b/lib/pages/search/controller.dart @@ -24,7 +24,7 @@ class SearchPageController extends GetxController { getRuntime({ExtensionType? type}) { _randomKey = DateTime.now().millisecondsSinceEpoch.toString(); cuurentExtensionType.value = type; - final exts = ExtensionUtils.extensions.values.toList(); + final exts = ExtensionUtils.runtimes.values.toList(); if (type != null) { exts.removeWhere((element) => element.extension.type != type); } diff --git a/lib/pages/search/pages/search_extension.dart b/lib/pages/search/pages/search_extension.dart index f09e9691..9ce3afed 100644 --- a/lib/pages/search/pages/search_extension.dart +++ b/lib/pages/search/pages/search_extension.dart @@ -224,7 +224,7 @@ class _SearchExtensionPageState extends fluent.State { @override Widget build(BuildContext context) { - final runtime = ExtensionUtils.extensions[widget.package]; + final runtime = ExtensionUtils.runtimes[widget.package]; final extensionMissing = Text( FlutterI18n.translate( context, diff --git a/lib/pages/settings/view.dart b/lib/pages/settings/view.dart index 256d76ae..4408d158 100644 --- a/lib/pages/settings/view.dart +++ b/lib/pages/settings/view.dart @@ -6,7 +6,6 @@ import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:get/get.dart'; import 'package:miru_app/api/tmdb.dart'; import 'package:miru_app/pages/extension_repo/controller.dart'; -import 'package:miru_app/pages/main/controller.dart'; import 'package:miru_app/pages/settings/controller.dart'; import 'package:miru_app/widgets/settings_input_tile.dart'; import 'package:miru_app/widgets/settings_radios_tile.dart'; diff --git a/lib/pages/watch/view.dart b/lib/pages/watch/view.dart index e90f6f82..ce6e7895 100644 --- a/lib/pages/watch/view.dart +++ b/lib/pages/watch/view.dart @@ -1,13 +1,9 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; -import 'package:get/get.dart'; import 'package:miru_app/models/extension.dart'; import 'package:miru_app/pages/watch/widgets/reader/comic/comic_reader.dart'; import 'package:miru_app/pages/watch/widgets/reader/novel/novel_reader.dart'; import 'package:miru_app/pages/watch/widgets/video/video_player.dart'; import 'package:miru_app/utils/extension.dart'; -import 'package:miru_app/utils/i18n.dart'; -import 'package:miru_app/widgets/messenger.dart'; class WatchPage extends StatelessWidget { const WatchPage({ @@ -30,27 +26,7 @@ class WatchPage extends StatelessWidget { @override Widget build(BuildContext context) { - final runtime = ExtensionUtils.extensions[package]; - if (runtime == null) { - showPlatformDialog( - context: context, - title: 'common.error'.i18n, - content: Text(FlutterI18n.translate( - context, - 'common.extension-missing', - translationParams: { - 'package': package, - }, - )), - actions: [ - TextButton( - onPressed: () => Get.back(), - child: Text('common.confirm'.i18n), - ), - ], - ); - return const SizedBox.shrink(); - } + final runtime = ExtensionUtils.runtimes[package]!; switch (runtime.extension.type) { case ExtensionType.bangumi: return VideoPlayer( diff --git a/lib/utils/database.dart b/lib/utils/database.dart index 5eac5edc..7624225a 100644 --- a/lib/utils/database.dart +++ b/lib/utils/database.dart @@ -15,23 +15,23 @@ class DatabaseUtils { required String cover, required String name, }) async { - final ext = ExtensionUtils.extensions[package]; - if (ext == null) { - throw Exception('extension not found'); - } - final extension = ext.extension; return db.writeTxn(() async { if (await isFavorite( - package: extension.package, + package: package, url: url, )) { return db.favorites .filter() - .packageEqualTo(extension.package) + .packageEqualTo(package) .and() .urlEqualTo(url) .deleteAll(); } else { + final runtime = ExtensionUtils.runtimes[package]; + if (runtime == null) { + throw Exception('extension not found'); + } + final extension = runtime.extension; return db.favorites.put( Favorite() ..cover = cover diff --git a/lib/utils/extension.dart b/lib/utils/extension.dart index f5e9976f..14585d2a 100644 --- a/lib/utils/extension.dart +++ b/lib/utils/extension.dart @@ -18,7 +18,7 @@ import 'package:miru_app/widgets/messenger.dart'; import 'package:path/path.dart' as path; class ExtensionUtils { - static late Map extensions; + static late Map runtimes; static late Map extensionErrorMap; static Future get getExtensionsDir async => @@ -59,7 +59,7 @@ class ExtensionUtils { } } - extensions = exts; + runtimes = exts; extensionErrorMap = extErrorMap; // 重载扩展页面 if (Get.isRegistered()) { diff --git a/lib/widgets/extension_item_card.dart b/lib/widgets/extension_item_card.dart index 10fdaae5..e5d704b6 100644 --- a/lib/widgets/extension_item_card.dart +++ b/lib/widgets/extension_item_card.dart @@ -80,7 +80,8 @@ class _ExtensionItemCardState extends State { ), if (widget.update != null) Text( - widget.update.toString(), + widget.update!, + overflow: TextOverflow.ellipsis, style: const TextStyle( color: Colors.white, fontSize: 10,