diff --git a/lib/common/widgets/interactiveviewer_gallery/interactiveviewer_gallery.dart b/lib/common/widgets/interactiveviewer_gallery/interactiveviewer_gallery.dart index 05a2baf7..991de633 100644 --- a/lib/common/widgets/interactiveviewer_gallery/interactiveviewer_gallery.dart +++ b/lib/common/widgets/interactiveviewer_gallery/interactiveviewer_gallery.dart @@ -127,6 +127,9 @@ class _InteractiveviewerGalleryState extends State if (Platform.isIOS || Platform.isAndroid) { StatusBarControl.setHidden(false, animation: StatusBarAnimation.FADE); } + for (int index = 0; index < widget.sources.length; index++) { + CachedNetworkImageProvider(_getActualUrl(index)).evict(); + } super.dispose(); } @@ -206,6 +209,10 @@ class _InteractiveviewerGalleryState extends State } } + String _getActualUrl(int index) => _thumbList[index] && _quality != 100 + ? '${widget.sources[index]}@${_quality}q.webp' + : widget.sources[index]; + @override Widget build(BuildContext context) { return Stack( @@ -252,7 +259,7 @@ class _InteractiveviewerGalleryState extends State index == currentIndex, _enablePageView, ) - : _itemBuilder(widget.sources, index), + : _itemBuilder(index), ); }, ), @@ -358,17 +365,15 @@ class _InteractiveviewerGalleryState extends State Share.shareXFiles([XFile(path)], subject: imgUrl); } - Widget _itemBuilder(sources, index) { + Widget _itemBuilder(index) { return Center( child: Hero( - tag: sources[index], + tag: widget.sources[index], child: CachedNetworkImage( fadeInDuration: const Duration(milliseconds: 0), fadeOutDuration: const Duration(milliseconds: 0), - imageUrl: _thumbList[index] && _quality != 100 - ? '${sources[index]}@${_quality}q.webp' - : sources[index], - fit: BoxFit.contain, + imageUrl: _getActualUrl(index), + // fit: BoxFit.contain, progressIndicatorBuilder: (context, url, progress) { return Center( child: SizedBox( @@ -377,13 +382,13 @@ class _InteractiveviewerGalleryState extends State ), ); }, - errorListener: (value) { - WidgetsBinding.instance.addPostFrameCallback((_) { - setState(() { - _thumbList[index] = false; - }); - }); - }, + // errorListener: (value) { + // WidgetsBinding.instance.addPostFrameCallback((_) { + // setState(() { + // _thumbList[index] = false; + // }); + // }); + // }, ), ), ); diff --git a/lib/common/widgets/network_img_layer.dart b/lib/common/widgets/network_img_layer.dart index 0851cb06..1fb63a8d 100644 --- a/lib/common/widgets/network_img_layer.dart +++ b/lib/common/widgets/network_img_layer.dart @@ -88,12 +88,12 @@ class NetworkImgLayer extends StatelessWidget { placeholder: (BuildContext context, String url) => placeholder(context), imageBuilder: imageBuilder, - errorListener: (value) { - thumbnail = false; - if (context.mounted) { - (context as Element).markNeedsBuild(); - } - }, + // errorListener: (value) { + // thumbnail = false; + // if (context.mounted) { + // (context as Element).markNeedsBuild(); + // } + // }, ), ), ) diff --git a/lib/pages/about/index.dart b/lib/pages/about/index.dart index 460f1a8f..f63d24cb 100644 --- a/lib/pages/about/index.dart +++ b/lib/pages/about/index.dart @@ -4,18 +4,12 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:package_info_plus/package_info_plus.dart'; -import 'package:PiliPalaX/http/index.dart'; import 'package:PiliPalaX/models/github/latest.dart'; import 'package:PiliPalaX/pages/setting/controller.dart'; import 'package:PiliPalaX/utils/storage.dart'; import 'package:PiliPalaX/utils/utils.dart'; -import 'package:url_launcher/url_launcher.dart'; import '../../utils/cache_manage.dart'; -const String _sourceCodeUrl = 'https://github.com/bggRGjQaUbCoE/PiliPalaX'; -const String _originSourceCodeUrl = 'https://github.com/guozhigq/pilipala'; -const String _upstreamUrl = 'https://github.com/orz12/PiliPalaX'; - class AboutPage extends StatefulWidget { const AboutPage({super.key}); @@ -25,6 +19,11 @@ class AboutPage extends StatefulWidget { class _AboutPageState extends State { final AboutController _aboutController = Get.put(AboutController()); + static const String _sourceCodeUrl = + 'https://github.com/bggRGjQaUbCoE/PiliPalaX'; + static const String _originSourceCodeUrl = + 'https://github.com/guozhigq/pilipala'; + static const String _upstreamUrl = 'https://github.com/orz12/PiliPalaX'; @override void initState() { @@ -115,13 +114,13 @@ class _AboutPageState extends State { color: Theme.of(context).colorScheme.outlineVariant, ), ListTile( - onTap: () => _aboutController.githubUrl(_sourceCodeUrl), + onTap: () => Utils.launchURL(_sourceCodeUrl), leading: const Icon(Icons.code), title: const Text('Source Code'), subtitle: Text(_sourceCodeUrl, style: subTitleStyle), ), ListTile( - onTap: () => _aboutController.githubUrl(_originSourceCodeUrl), + onTap: () => Utils.launchURL(_originSourceCodeUrl), leading: const Icon(Icons.code), title: const Text('Origin'), subtitle: Text( @@ -130,7 +129,7 @@ class _AboutPageState extends State { ), ), ListTile( - onTap: () => _aboutController.githubUrl(_upstreamUrl), + onTap: () => Utils.launchURL(_upstreamUrl), leading: const Icon(Icons.code), title: const Text('Upstream'), subtitle: Text( @@ -139,7 +138,23 @@ class _AboutPageState extends State { ), ), ListTile( - onTap: () => _aboutController.feedback(context), + onTap: () { + showDialog( + context: context, + builder: (context) { + return SimpleDialog( + clipBehavior: Clip.hardEdge, + title: const Text('问题反馈'), + children: [ + ListTile( + title: const Text('GitHub Issue'), + onTap: () => Utils.launchURL('$_sourceCodeUrl/issues'), + ), + ], + ); + }, + ); + }, leading: const Icon(Icons.feedback_outlined), title: const Text('问题反馈'), trailing: Icon( @@ -149,7 +164,9 @@ class _AboutPageState extends State { ), ), ListTile( - onTap: () => _aboutController.logs(), + onTap: () { + Get.toNamed('/logs'); + }, leading: const Icon(Icons.bug_report_outlined), title: const Text('错误日志'), trailing: Icon(Icons.arrow_forward, size: 16, color: outline), @@ -257,22 +274,26 @@ class _AboutPageState extends State { child: const Text('取消'), ), TextButton( - onPressed: () { + onPressed: () async { Get.back(); - GStorage.setting.clear(); - GStorage.video.clear(); + await Future.wait([ + GStorage.setting.clear(), + GStorage.video.clear(), + ]); SmartDialog.showToast('重置成功'); }, child: const Text('重置可导出的设置'), ), TextButton( - onPressed: () { + onPressed: () async { Get.back(); - GStorage.userInfo.clear(); - GStorage.setting.clear(); - GStorage.localCache.clear(); - GStorage.video.clear(); - GStorage.historyWord.clear(); + await Future.wait([ + GStorage.userInfo.clear(), + GStorage.setting.clear(), + GStorage.localCache.clear(), + GStorage.video.clear(), + GStorage.historyWord.clear(), + ]); SmartDialog.showToast('重置成功'); }, child: const Text('重置所有数据(含登录信息)'), @@ -298,7 +319,6 @@ class AboutController extends GetxController { RxBool isUpdate = true.obs; RxBool isLoading = true.obs; LatestDataModel? data; - // RxInt count = 0.obs; RxString cacheSize = ''.obs; @override @@ -330,91 +350,21 @@ class AboutController extends GetxController { currentVersion.value = "${currentInfo.version}+$buildNumber"; } - // 获取远程版本 - Future getRemoteApp() async { - var result = await Request().get(Api.latestApp, extra: {'ua': 'pc'}); - if (result.data.isEmpty) { - SmartDialog.showToast('检查更新失败,github接口未返回数据,请检查网络'); - return false; - } else if (result.data[0] == null) { - SmartDialog.showToast('检查更新失败,github接口返回如下内容:\n${result.data}'); - return false; - } - data = LatestDataModel.fromJson(result.data[0]); - remoteAppInfo = data; - remoteVersion.value = data!.tagName!; - isUpdate.value = - Utils.needUpdate(currentVersion.value, remoteVersion.value); - isLoading.value = false; - } - - // 跳转下载/本地更新 - Future onUpdate() async { - if (data != null) { - Utils.matchVersion(data); - } - } - - // 跳转github - githubUrl(String url) { - launchUrl( - Uri.parse(url), - mode: LaunchMode.externalApplication, - ); - } - - githubRelease() { - launchUrl( - Uri.parse('$_sourceCodeUrl/release'), - mode: LaunchMode.externalApplication, - ); - } - - // 问题反馈 - feedback(BuildContext context) async { - await showDialog( - context: context, - builder: (context) { - return SimpleDialog( - clipBehavior: Clip.hardEdge, - title: const Text('问题反馈'), - children: [ - ListTile( - title: const Text('GitHub Issue'), - onTap: () => launchUrl( - Uri.parse('$_sourceCodeUrl/issues'), - // 系统自带浏览器打开 - mode: LaunchMode.externalApplication, - ), - ), - // ListTile( - // title: const Text('腾讯兔小巢'), - // onTap: () => launchUrl( - // Uri.parse('https://support.qq.com/embed/phone/637735'), - // // 系统自带浏览器打开 - // mode: LaunchMode.externalApplication, - // ), - // ), - ], - ); - }, - ); - } - - // 日志 - logs() { - Get.toNamed('/logs'); - } - - // tapOnVersion() { - // if (settingController.hiddenSettingUnlocked.value) { - // SmartDialog.showToast('您已解锁开发人员选项, 无需再次操作'); - // return; - // } - // count.value++; - // if (count.value == 5) { - // setting.put(SettingBoxKey.hiddenSettingUnlocked, true); - // SmartDialog.showToast('恭喜您发现了开发人员选项!'); + // // 获取远程版本 + // Future getRemoteApp() async { + // var result = await Request().get(Api.latestApp, extra: {'ua': 'pc'}); + // if (result.data.isEmpty) { + // SmartDialog.showToast('检查更新失败,github接口未返回数据,请检查网络'); + // return false; + // } else if (result.data[0] == null) { + // SmartDialog.showToast('检查更新失败,github接口返回如下内容:\n${result.data}'); + // return false; // } + // data = LatestDataModel.fromJson(result.data[0]); + // remoteAppInfo = data; + // remoteVersion.value = data!.tagName!; + // isUpdate.value = + // Utils.needUpdate(currentVersion.value, remoteVersion.value); + // isLoading.value = false; // } } diff --git a/lib/pages/common/reply_controller.dart b/lib/pages/common/reply_controller.dart index 9882061f..8844be10 100644 --- a/lib/pages/common/reply_controller.dart +++ b/lib/pages/common/reply_controller.dart @@ -126,7 +126,6 @@ abstract class ReplyController extends CommonController { sortType = ReplySortType.time; mode = Mode.MAIN_LIST_TIME; break; - default: } sortTypeTitle.value = sortType.titles; sortTypeLabel.value = sortType.labels; diff --git a/lib/pages/dynamics/widgets/up_panel.dart b/lib/pages/dynamics/widgets/up_panel.dart index 39a728cf..528afa9b 100644 --- a/lib/pages/dynamics/widgets/up_panel.dart +++ b/lib/pages/dynamics/widgets/up_panel.dart @@ -225,28 +225,28 @@ class _UpPanelState extends State { } } -class _SliverHeaderDelegate extends SliverPersistentHeaderDelegate { - _SliverHeaderDelegate({required this.height, required this.child}); +// class _SliverHeaderDelegate extends SliverPersistentHeaderDelegate { +// _SliverHeaderDelegate({required this.height, required this.child}); - final double height; - final Widget child; +// final double height; +// final Widget child; - @override - Widget build( - BuildContext context, double shrinkOffset, bool overlapsContent) { - return child; - } +// @override +// Widget build( +// BuildContext context, double shrinkOffset, bool overlapsContent) { +// return child; +// } - @override - double get maxExtent => height; +// @override +// double get maxExtent => height; - @override - double get minExtent => height; +// @override +// double get minExtent => height; - @override - bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) => - true; -} +// @override +// bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) => +// true; +// } class UpPanelSkeleton extends StatelessWidget { const UpPanelSkeleton({super.key}); diff --git a/lib/pages/follow/view.dart b/lib/pages/follow/view.dart index 8e9779df..b992478d 100644 --- a/lib/pages/follow/view.dart +++ b/lib/pages/follow/view.dart @@ -111,21 +111,21 @@ class _FollowPageState extends State { } } -class _FakeAPI { - static const List _kOptions = [ - 'aardvark', - 'bobcat', - 'chameleon', - ]; - // Searches the options, but injects a fake "network" delay. - static Future> search(String query) async { - await Future.delayed( - const Duration(seconds: 1)); // Fake 1 second delay. - if (query == '') { - return const Iterable.empty(); - } - return _kOptions.where((String option) { - return option.contains(query.toLowerCase()); - }); - } -} +// class _FakeAPI { +// static const List _kOptions = [ +// 'aardvark', +// 'bobcat', +// 'chameleon', +// ]; +// // Searches the options, but injects a fake "network" delay. +// static Future> search(String query) async { +// await Future.delayed( +// const Duration(seconds: 1)); // Fake 1 second delay. +// if (query == '') { +// return const Iterable.empty(); +// } +// return _kOptions.where((String option) { +// return option.contains(query.toLowerCase()); +// }); +// } +// } diff --git a/lib/pages/login/view.dart b/lib/pages/login/view.dart index fbc6a174..0c82457a 100644 --- a/lib/pages/login/view.dart +++ b/lib/pages/login/view.dart @@ -120,12 +120,15 @@ class _LoginPageState extends State { child: Padding( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), - child: Text(_loginPageCtr.codeInfo.value['data']?['url'] ?? "", - style: Theme.of(context).textTheme.labelSmall!.copyWith( + child: Text( + _loginPageCtr.codeInfo.value['data']?['url'] ?? "", + style: Theme.of(context).textTheme.labelSmall!.copyWith( color: Theme.of(context) .colorScheme .onSurface - .withOpacity(0.4))), + .withOpacity(0.4), + ), + ), ), )), Padding( diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index 9408d3b6..92143292 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -1527,37 +1527,37 @@ class VideoDetailController extends GetxController }, ); - List _actionType2SegmentType(ActionType actionType) { - return switch (actionType) { - ActionType.skip => [ - SegmentType.sponsor, - SegmentType.selfpromo, - SegmentType.interaction, - SegmentType.intro, - SegmentType.outro, - SegmentType.preview, - SegmentType.filler, - ], - ActionType.mute => [ - SegmentType.sponsor, - SegmentType.selfpromo, - SegmentType.interaction, - SegmentType.intro, - SegmentType.outro, - SegmentType.preview, - SegmentType.music_offtopic, - SegmentType.filler, - ], - ActionType.full => [ - SegmentType.sponsor, - SegmentType.selfpromo, - SegmentType.exclusive_access, - ], - ActionType.poi => [ - SegmentType.poi_highlight, - ], - }; - } + // List _actionType2SegmentType(ActionType actionType) { + // return switch (actionType) { + // ActionType.skip => [ + // SegmentType.sponsor, + // SegmentType.selfpromo, + // SegmentType.interaction, + // SegmentType.intro, + // SegmentType.outro, + // SegmentType.preview, + // SegmentType.filler, + // ], + // ActionType.mute => [ + // SegmentType.sponsor, + // SegmentType.selfpromo, + // SegmentType.interaction, + // SegmentType.intro, + // SegmentType.outro, + // SegmentType.preview, + // SegmentType.music_offtopic, + // SegmentType.filler, + // ], + // ActionType.full => [ + // SegmentType.sponsor, + // SegmentType.selfpromo, + // SegmentType.exclusive_access, + // ], + // ActionType.poi => [ + // SegmentType.poi_highlight, + // ], + // }; + // } List _segmentType2ActionType(SegmentType segmentType) { return switch (segmentType) { diff --git a/lib/tcp/live.dart b/lib/tcp/live.dart index 5a347f21..721756b4 100644 --- a/lib/tcp/live.dart +++ b/lib/tcp/live.dart @@ -191,6 +191,7 @@ class LiveMessageStream { for (final server in servers) { try { return await WebSocket.connect(server); + // ignore: empty_catches } catch (e) {} } throw Exception("all servers connect failed"); diff --git a/lib/utils/app_scheme.dart b/lib/utils/app_scheme.dart index c9348562..f1e50227 100644 --- a/lib/utils/app_scheme.dart +++ b/lib/utils/app_scheme.dart @@ -301,20 +301,20 @@ class PiliScheme { // https | m.bilibili.com | /bangumi/play/ss39708 // final String scheme = value.scheme!; final String host = value.host; - final String? path = value.path; + final String path = value.path; Map query = value.queryParameters; RegExp regExp = RegExp(r'^((www\.)|(m\.))?bilibili\.com$'); if (regExp.hasMatch(host)) { debugPrint('bilibili.com'); } else if (host.contains('live')) { - int roomId = int.parse(path!.split('/').last); + int roomId = int.parse(path.split('/').last); Utils.toDupNamed( '/liveRoom?roomid=$roomId', arguments: {'liveItem': null, 'heroTag': roomId.toString()}, ); return; } else if (host.contains('space')) { - var mid = path!.split('/').last; + var mid = path.split('/').last; Utils.toDupNamed('/member?mid=$mid', arguments: {'face': ''}); return; } else if (host == 'b23.tv') { @@ -352,79 +352,77 @@ class PiliScheme { return; } - if (path != null) { - List pathPart = path.split('/'); - if (pathPart.length < 3) { + List pathPart = path.split('/'); + if (pathPart.length < 3) { + Utils.toDupNamed( + '/webviewnew', + parameters: {'url': value.toString()}, + ); + return; + } + final String area = pathPart[1] == 'mobile' ? pathPart[2] : pathPart[1]; + switch (area) { + case 'bangumi': + debugPrint('番剧'); + for (var pathSegment in pathPart) { + if (pathSegment.startsWith('ss')) { + bangumiPush(matchNum(pathSegment).first, null); + break; + } else if (pathSegment.startsWith('ep')) { + bangumiPush(null, matchNum(pathSegment).first); + break; + } + } + break; + case 'video': + debugPrint('投稿'); + final Map map = IdUtils.matchAvorBv(input: path); + if (map.containsKey('AV')) { + videoPush(map['AV']! as int, null); + } else if (map.containsKey('BV')) { + videoPush(null, map['BV'] as String); + } else { + SmartDialog.showToast('投稿匹配失败'); + } + break; + case 'read': + debugPrint('专栏'); + late String id; + if (query['id'] != null) { + id = 'cv${matchNum(query['id']!).first}'; + } else { + id = 'cv${matchNum(path).firstOrNull}'; + } + Utils.toDupNamed('/htmlRender', parameters: { + 'url': value.toString(), + 'title': '', + 'id': id, + 'dynamicType': 'read' + }); + break; + case 'space': + debugPrint('个人空间'); Utils.toDupNamed( - '/webviewnew', - parameters: {'url': value.toString()}, - ); - return; - } - final String area = pathPart[1] == 'mobile' ? pathPart[2] : pathPart[1]; - switch (area) { - case 'bangumi': - debugPrint('番剧'); - for (var pathSegment in pathPart) { - if (pathSegment.startsWith('ss')) { - bangumiPush(matchNum(pathSegment).first, null); - break; - } else if (pathSegment.startsWith('ep')) { - bangumiPush(null, matchNum(pathSegment).first); - break; - } - } - break; - case 'video': - debugPrint('投稿'); - final Map map = IdUtils.matchAvorBv(input: path); - if (map.containsKey('AV')) { - videoPush(map['AV']! as int, null); - } else if (map.containsKey('BV')) { - videoPush(null, map['BV'] as String); - } else { - SmartDialog.showToast('投稿匹配失败'); - } - break; - case 'read': - debugPrint('专栏'); - late String id; - if (query['id'] != null) { - id = 'cv${matchNum(query['id']!).first}'; - } else { - id = 'cv${matchNum(path).firstOrNull}'; - } - Utils.toDupNamed('/htmlRender', parameters: { - 'url': value.toString(), - 'title': '', - 'id': id, - 'dynamicType': 'read' - }); - break; - case 'space': - debugPrint('个人空间'); + '/member?mid=${pathPart[1] == 'mobile' ? pathPart.getOrNull(3) : pathPart.getOrNull(2)}', + arguments: {'face': ''}); + break; + default: + var res = IdUtils.matchAvorBv(input: area.split('?').first); + if (res.containsKey('AV')) { + videoPush(res['AV']! as int, null); + } else if (res.containsKey('BV')) { + videoPush(null, res['BV'] as String); + } else { + SmartDialog.showToast('未知路径或匹配错误:$value,先采用浏览器打开'); Utils.toDupNamed( - '/member?mid=${pathPart[1] == 'mobile' ? pathPart.getOrNull(3) : pathPart.getOrNull(2)}', - arguments: {'face': ''}); - break; - default: - var res = IdUtils.matchAvorBv(input: area.split('?').first); - if (res.containsKey('AV')) { - videoPush(res['AV']! as int, null); - } else if (res.containsKey('BV')) { - videoPush(null, res['BV'] as String); - } else { - SmartDialog.showToast('未知路径或匹配错误:$value,先采用浏览器打开'); - Utils.toDupNamed( - '/webviewnew', - parameters: { - 'url': value.toString(), - 'type': 'url', - 'pageTitle': '' - }, - ); - } - } + '/webviewnew', + parameters: { + 'url': value.toString(), + 'type': 'url', + 'pageTitle': '' + }, + ); + } } } diff --git a/lib/utils/event_bus.dart b/lib/utils/event_bus.dart index cd010ef9..67b6df8d 100644 --- a/lib/utils/event_bus.dart +++ b/lib/utils/event_bus.dart @@ -1,5 +1,5 @@ // 订阅者回调签名 -typedef void EventCallback(arg); +typedef EventCallback = void Function(dynamic arg); class EventBus { // 私有构造函数 diff --git a/lib/utils/extension.dart b/lib/utils/extension.dart index ae2b0592..4dea7158 100644 --- a/lib/utils/extension.dart +++ b/lib/utils/extension.dart @@ -53,7 +53,7 @@ extension StringExt on String { String get http2https => replaceFirst(RegExp("^http://"), "https://"); } -extension boolExt on bool { +extension BoolExt on bool { bool get not => !this; } diff --git a/pubspec.lock b/pubspec.lock index 1b415be4..ddbce325 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -106,18 +106,18 @@ packages: dependency: "direct main" description: name: audio_service - sha256: "9dd5ba7e77567b290c35908b1950d61485b4dfdd3a0ac398e98cfeec04651b75" + sha256: f6c8191bef6b843da34675dd0731ad11d06094c36b691ffcf3148a4feb2e585f url: "https://pub.dev" source: hosted - version: "0.18.15" + version: "0.18.16" audio_service_platform_interface: dependency: transitive description: name: audio_service_platform_interface - sha256: "8431a455dac9916cc9ee6f7da5620a666436345c906ad2ebb7fa41d18b3c1bf4" + sha256: "6283782851f6c8b501b60904a32fc7199dc631172da0629d7301e66f672ab777" url: "https://pub.dev" source: hosted - version: "0.1.1" + version: "0.1.3" audio_service_web: dependency: transitive description: @@ -914,10 +914,10 @@ packages: dependency: transitive description: name: image - sha256: "599d08e369969bdf83138f5b4e0a7e823d3f992f23b8a64dd626877c37013533" + sha256: "20842a5ad1555be624c314b0c0cc0566e8ece412f61e859a42efeb6d4101a26c" url: "https://pub.dev" source: hosted - version: "4.4.0" + version: "4.5.0" image_cropper: dependency: "direct main" description: