From 68d35a7ed8830c4b352389dd59c4aa60d335ac34 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 13 May 2024 23:37:22 +0800 Subject: [PATCH 1/8] =?UTF-8?q?feat:=20=E6=90=9C=E7=B4=A2=E5=88=86?= =?UTF-8?q?=E5=8C=BAUI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/api.dart | 2 +- lib/http/search.dart | 2 + lib/pages/search/widgets/search_text.dart | 7 +- lib/pages/search_panel/controller.dart | 14 +- .../search_panel/widgets/video_panel.dart | 125 +++++++++++++++++- 5 files changed, 142 insertions(+), 8 deletions(-) diff --git a/lib/http/api.dart b/lib/http/api.dart index 42fc03b8..77c168d0 100644 --- a/lib/http/api.dart +++ b/lib/http/api.dart @@ -189,7 +189,7 @@ class Api { 'https://s.search.bilibili.com/main/suggest'; // 分类搜索 - static const String searchByType = '/x/web-interface/search/type'; + static const String searchByType = '/x/web-interface/wbi/search/type'; // 记录视频播放进度 // https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/video/report.md diff --git a/lib/http/search.dart b/lib/http/search.dart index 9b493a84..70980547 100644 --- a/lib/http/search.dart +++ b/lib/http/search.dart @@ -75,6 +75,7 @@ class SearchHttp { required page, String? order, int? duration, + int? tid, }) async { var reqData = { 'search_type': searchType.type, @@ -84,6 +85,7 @@ class SearchHttp { 'page': page, if (order != null) 'order': order, if (duration != null) 'duration': duration, + if (tid != null) 'tid': tid, }; var res = await Request().get(Api.searchByType, data: reqData); if (res.data['code'] == 0 && res.data['data']['numPages'] > 0) { diff --git a/lib/pages/search/widgets/search_text.dart b/lib/pages/search/widgets/search_text.dart index 039a851b..5e91a4cd 100644 --- a/lib/pages/search/widgets/search_text.dart +++ b/lib/pages/search/widgets/search_text.dart @@ -5,12 +5,14 @@ class SearchText extends StatelessWidget { final Function? onSelect; final int? searchTextIdx; final Function? onLongSelect; + final bool isSelect; const SearchText({ super.key, this.searchText, this.onSelect, this.searchTextIdx, this.onLongSelect, + this.isSelect = false, }); @override @@ -34,7 +36,10 @@ class SearchText extends StatelessWidget { child: Text( searchText!, style: TextStyle( - color: Theme.of(context).colorScheme.onSurfaceVariant), + color: isSelect + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.onSurfaceVariant, + ), ), ), ), diff --git a/lib/pages/search_panel/controller.dart b/lib/pages/search_panel/controller.dart index 85952e90..56d83601 100644 --- a/lib/pages/search_panel/controller.dart +++ b/lib/pages/search_panel/controller.dart @@ -16,14 +16,18 @@ class SearchPanelController extends GetxController { RxString order = ''.obs; // 视频时长筛选 仅用于搜索视频 RxInt duration = 0.obs; + // 视频分区筛选 仅用于搜索视频 + RxInt tid = (-1).obs; Future onSearch({type = 'init'}) async { var result = await SearchHttp.searchByType( - searchType: searchType!, - keyword: keyword!, - page: page.value, - order: searchType!.type != 'video' ? null : order.value, - duration: searchType!.type != 'video' ? null : duration.value); + searchType: searchType!, + keyword: keyword!, + page: page.value, + order: searchType!.type != 'video' ? null : order.value, + duration: searchType!.type != 'video' ? null : duration.value, + tid: searchType!.type != 'video' ? null : tid.value, + ); if (result['status']) { if (type == 'onRefresh') { resultList.value = result['data'].list; diff --git a/lib/pages/search_panel/widgets/video_panel.dart b/lib/pages/search_panel/widgets/video_panel.dart index c24a007c..06ee5d4b 100644 --- a/lib/pages/search_panel/widgets/video_panel.dart +++ b/lib/pages/search_panel/widgets/video_panel.dart @@ -3,6 +3,7 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/widgets/video_card_h.dart'; import 'package:pilipala/models/common/search_type.dart'; +import 'package:pilipala/pages/search/widgets/search_text.dart'; import 'package:pilipala/pages/search_panel/index.dart'; class SearchVideoPanel extends StatelessWidget { @@ -94,7 +95,7 @@ class SearchVideoPanel extends StatelessWidget { style: ButtonStyle( padding: MaterialStateProperty.all(EdgeInsets.zero), ), - onPressed: () => controller.onShowFilterDialog(ctr), + onPressed: () => controller.onShowFilterSheet(ctr), icon: Icon( Icons.filter_list_outlined, size: 18, @@ -165,7 +166,33 @@ class VideoPanelController extends GetxController { {'label': '30-60分钟', 'value': 3}, {'label': '60分钟+', 'value': 4}, ]; + List> partFiltersList = [ + {'label': '全部', 'value': -1}, + {'label': '动画', 'value': 1}, + {'label': '番剧', 'value': 13}, + {'label': '国创', 'value': 167}, + {'label': '音乐', 'value': 3}, + {'label': '舞蹈', 'value': 129}, + {'label': '游戏', 'value': 4}, + {'label': '知识', 'value': 36}, + {'label': '科技', 'value': 188}, + {'label': '运动', 'value': 234}, + {'label': '汽车', 'value': 223}, + {'label': '生活', 'value': 160}, + {'label': '美食', 'value': 211}, + {'label': '动物', 'value': 217}, + {'label': '鬼畜', 'value': 119}, + {'label': '时尚', 'value': 155}, + {'label': '资讯', 'value': 202}, + {'label': '娱乐', 'value': 5}, + {'label': '影视', 'value': 181}, + {'label': '记录', 'value': 177}, + {'label': '电影', 'value': 23}, + {'label': '电视', 'value': 11}, + ]; + RxInt currentTimeFilterval = 0.obs; + RxInt currentPartFilterval = (-1).obs; @override void onInit() { @@ -219,4 +246,100 @@ class VideoPanelController extends GetxController { }, ); } + + onShowFilterSheet(searchPanelCtr) { + showModalBottomSheet( + context: Get.context!, + builder: (context) { + return StatefulBuilder( + builder: (context, StateSetter setState) { + return Container( + color: Theme.of(Get.context!).colorScheme.surface, + padding: const EdgeInsets.only(top: 12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ListTile( + title: Text('内容时长'), + ), + Padding( + padding: const EdgeInsets.only( + left: 14, + right: 14, + bottom: 14, + ), + child: Wrap( + spacing: 10, + runSpacing: 10, + direction: Axis.horizontal, + textDirection: TextDirection.ltr, + children: [ + for (var i in timeFiltersList) + Obx( + () => SearchText( + searchText: i['label'], + searchTextIdx: i['value'], + isSelect: + currentTimeFilterval.value == i['value'], + onSelect: (value) async { + currentTimeFilterval.value = i['value']; + setState(() {}); + SmartDialog.showToast("「${i['label']}」的筛选结果"); + SearchPanelController ctr = + Get.find( + tag: 'video${searchPanelCtr.keyword!}'); + ctr.duration.value = i['value']; + Get.back(); + SmartDialog.showLoading(msg: '获取中'); + await ctr.onRefresh(); + SmartDialog.dismiss(); + }, + onLongSelect: (value) => {}, + ), + ) + ], + ), + ), + const ListTile( + title: Text('内容分区'), + ), + Padding( + padding: const EdgeInsets.only(left: 14, right: 14), + child: Wrap( + spacing: 10, + runSpacing: 10, + direction: Axis.horizontal, + textDirection: TextDirection.ltr, + children: [ + for (var i in partFiltersList) + SearchText( + searchText: i['label'], + searchTextIdx: i['value'], + isSelect: currentPartFilterval.value == i['value'], + onSelect: (value) async { + currentPartFilterval.value = i['value']; + setState(() {}); + SmartDialog.showToast("「${i['label']}」的筛选结果"); + SearchPanelController ctr = + Get.find( + tag: 'video${searchPanelCtr.keyword!}'); + ctr.tid.value = i['value']; + Get.back(); + SmartDialog.showLoading(msg: '获取中'); + await ctr.onRefresh(); + SmartDialog.dismiss(); + }, + onLongSelect: (value) => {}, + ) + ], + ), + ) + ], + ), + ); + }, + ); + }, + ); + } } From cb7cd0a2f0658ca84d48b213760aee80decff555 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 19 May 2024 19:57:13 +0800 Subject: [PATCH 2/8] feat: videoDetail menu edit --- assets/images/coin.png | Bin 0 -> 7159 bytes lib/models/common/action_type.dart | 94 ++++++++++++++++ lib/pages/setting/pages/action_menu_set.dart | 100 ++++++++++++++++++ lib/pages/setting/style_setting.dart | 5 + lib/pages/video/detail/introduction/view.dart | 28 ++--- .../introduction/widgets/action_item.dart | 54 ++++++---- lib/router/app_pages.dart | 4 + lib/utils/storage.dart | 3 +- 8 files changed, 249 insertions(+), 39 deletions(-) create mode 100644 assets/images/coin.png create mode 100644 lib/models/common/action_type.dart create mode 100644 lib/pages/setting/pages/action_menu_set.dart diff --git a/assets/images/coin.png b/assets/images/coin.png new file mode 100644 index 0000000000000000000000000000000000000000..bc2952a7a5cf519a331b83c0f268eef88769d471 GIT binary patch literal 7159 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 literal 0 HcmV?d00001 diff --git a/lib/models/common/action_type.dart b/lib/models/common/action_type.dart new file mode 100644 index 00000000..2284df6c --- /dev/null +++ b/lib/models/common/action_type.dart @@ -0,0 +1,94 @@ +// 操作类型的枚举值:点赞 不喜欢 收藏 投币 稍后再看 下载封面 后台播放 听视频 分享 下载视频 +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +enum ActionType { + like, + coin, + collect, + watchLater, + share, + dislike, + downloadCover, + copyLink, + threeAction, + // backgroundPlay, + // listenVideo, + // downloadVideo, +} + +extension ActionTypeExtension on ActionType { + String get value => [ + 'like', + 'coin', + 'collect', + 'watchLater', + 'share', + 'dislike', + 'downloadCover', + 'copyLink', + // 'backgroundPlay', + // 'listenVideo', + // 'downloadVideo', + ][index]; + String get label => [ + '点赞视频', + '投币', + '收藏视频', + '稍后再看', + '视频分享', + '不喜欢', + '下载封面', + '复制链接', + // '后台播放', + // '听视频', + // '下载视频', + ][index]; +} + +List actionMenuConfig = [ + { + 'icon': const Icon(Icons.thumb_up_alt_outlined), + 'label': '点赞视频', + 'value': ActionType.like, + }, + { + 'icon': Image.asset( + 'assets/images/coin.png', + width: 26, + color: IconTheme.of(Get.context!).color!.withOpacity(0.65), + ), + 'label': '投币', + 'value': ActionType.coin, + }, + { + 'icon': const Icon(Icons.star_border), + 'label': '收藏视频', + 'value': ActionType.collect, + }, + { + 'icon': const Icon(Icons.watch_later_outlined), + 'label': '稍后再看', + 'value': ActionType.watchLater, + }, + { + 'icon': const Icon(Icons.share), + 'label': '视频分享', + 'value': ActionType.share, + }, + { + 'icon': const Icon(Icons.thumb_down_alt_outlined), + 'label': '不喜欢', + 'value': ActionType.dislike, + }, + { + 'icon': const Icon(Icons.image_outlined), + 'label': '下载封面', + 'value': ActionType.downloadCover, + }, + { + 'icon': const Icon(Icons.link_outlined), + 'label': '复制链接', + 'value': ActionType.copyLink, + }, +]; diff --git a/lib/pages/setting/pages/action_menu_set.dart b/lib/pages/setting/pages/action_menu_set.dart new file mode 100644 index 00000000..f7d92e17 --- /dev/null +++ b/lib/pages/setting/pages/action_menu_set.dart @@ -0,0 +1,100 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; +import 'package:hive/hive.dart'; +import 'package:pilipala/models/common/action_type.dart'; +import '../../../utils/storage.dart'; + +class ActionMenuSetPage extends StatefulWidget { + const ActionMenuSetPage({super.key}); + + @override + State createState() => _ActionMenuSetPageState(); +} + +class _ActionMenuSetPageState extends State { + Box settingStorage = GStrorage.setting; + late List actionTypeSort; + late List allLabels; + + @override + void initState() { + super.initState(); + actionTypeSort = settingStorage.get(SettingBoxKey.actionTypeSort, + defaultValue: ['like', 'coin', 'collect', 'watchLater', 'share']); + allLabels = actionMenuConfig; + allLabels.sort((a, b) { + int indexA = actionTypeSort.indexOf((a['value'] as ActionType).value); + int indexB = actionTypeSort.indexOf((b['value'] as ActionType).value); + if (indexA == -1) indexA = actionTypeSort.length; + if (indexB == -1) indexB = actionTypeSort.length; + return indexA.compareTo(indexB); + }); + } + + void saveEdit() { + List sortedTabbar = allLabels + .where((i) => actionTypeSort.contains((i['value'] as ActionType).value)) + .map((i) => (i['value'] as ActionType).value) + .toList(); + settingStorage.put(SettingBoxKey.actionTypeSort, sortedTabbar); + SmartDialog.showToast('保存成功,下次启动时生效'); + } + + void onReorder(int oldIndex, int newIndex) { + setState(() { + if (newIndex > oldIndex) { + newIndex -= 1; + } + final tabsItem = allLabels.removeAt(oldIndex); + allLabels.insert(newIndex, tabsItem); + }); + } + + @override + Widget build(BuildContext context) { + final listTiles = [ + for (int i = 0; i < allLabels.length; i++) ...[ + CheckboxListTile( + key: Key((allLabels[i]['value'] as ActionType).value), + value: actionTypeSort + .contains((allLabels[i]['value'] as ActionType).value), + onChanged: (bool? newValue) { + String actionTypeId = (allLabels[i]['value'] as ActionType).value; + if (!newValue!) { + actionTypeSort.remove(actionTypeId); + } else { + actionTypeSort.add(actionTypeId); + } + setState(() {}); + }, + title: Row( + children: [ + allLabels[i]['icon'], + const SizedBox(width: 8), + Text(allLabels[i]['label']), + ], + ), + secondary: const Icon(Icons.drag_indicator_rounded), + ) + ] + ]; + + return Scaffold( + appBar: AppBar( + title: const Text('视频操作菜单'), + actions: [ + TextButton(onPressed: () => saveEdit(), child: const Text('保存')), + const SizedBox(width: 12) + ], + ), + body: ReorderableListView( + onReorder: onReorder, + physics: const NeverScrollableScrollPhysics(), + footer: SizedBox( + height: MediaQuery.of(context).padding.bottom + 30, + ), + children: listTiles, + ), + ); + } +} diff --git a/lib/pages/setting/style_setting.dart b/lib/pages/setting/style_setting.dart index 364eabf0..20fdada0 100644 --- a/lib/pages/setting/style_setting.dart +++ b/lib/pages/setting/style_setting.dart @@ -289,6 +289,11 @@ class _StyleSettingState extends State { onTap: () => Get.toNamed('/navbarSetting'), title: Text('底部导航栏设置', style: titleStyle), ), + ListTile( + dense: false, + onTap: () => Get.toNamed('/actionMenuSet'), + title: Text('操作菜单设置', style: titleStyle), + ), if (Platform.isAndroid) ListTile( dense: false, diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index 9103c130..dab81f18 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -1,7 +1,6 @@ import 'package:expandable/expandable.dart'; import 'package:flutter/services.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:get/get.dart'; import 'package:flutter/material.dart'; import 'package:hive/hive.dart'; @@ -539,26 +538,21 @@ class _VideoInfoState extends State with TickerProviderStateMixin { builder: (BuildContext context, BoxConstraints constraints) { return Container( margin: const EdgeInsets.only(top: 6, bottom: 4), - height: constraints.maxWidth / 5 * 0.8, - child: GridView.count( - physics: const NeverScrollableScrollPhysics(), - primary: false, - padding: EdgeInsets.zero, - crossAxisCount: 5, - childAspectRatio: 1.25, - children: [ + height: constraints.maxWidth / 5, + child: ListView( + scrollDirection: Axis.horizontal, + children: [ Obx( () => ActionItem( - icon: const Icon(FontAwesomeIcons.thumbsUp), - selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp), + icon: const Icon(Icons.thumb_up_alt_outlined), + selectIcon: const Icon(Icons.thumb_up), onTap: handleState(videoIntroController.actionLikeVideo), selectStatus: videoIntroController.hasLike.value, text: widget.videoDetail!.stat!.like!.toString()), ), Obx( () => ActionItem( - icon: const Icon(FontAwesomeIcons.b), - selectIcon: const Icon(FontAwesomeIcons.b), + icon: Image.asset('assets/images/coin.png', width: 30), onTap: handleState(videoIntroController.actionCoinVideo), selectStatus: videoIntroController.hasCoin.value, text: widget.videoDetail!.stat!.coin!.toString(), @@ -566,8 +560,8 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ), Obx( () => ActionItem( - icon: const Icon(FontAwesomeIcons.star), - selectIcon: const Icon(FontAwesomeIcons.solidStar), + icon: const Icon(Icons.star_border), + selectIcon: const Icon(Icons.star), onTap: () => showFavBottomSheet(), onLongPress: () => showFavBottomSheet(type: 'longPress'), selectStatus: videoIntroController.hasFav.value, @@ -575,7 +569,7 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ), ), ActionItem( - icon: const Icon(FontAwesomeIcons.clock), + icon: const Icon(Icons.watch_later_outlined), onTap: () async { final res = await UserHttp.toViewLater(bvid: widget.videoDetail!.bvid); @@ -585,7 +579,7 @@ class _VideoInfoState extends State with TickerProviderStateMixin { text: '稍后看', ), ActionItem( - icon: const Icon(FontAwesomeIcons.shareFromSquare), + icon: const Icon(Icons.share), onTap: () => videoIntroController.actionShareVideo(), selectStatus: false, text: '分享', diff --git a/lib/pages/video/detail/introduction/widgets/action_item.dart b/lib/pages/video/detail/introduction/widgets/action_item.dart index 022d9223..2a89afe7 100644 --- a/lib/pages/video/detail/introduction/widgets/action_item.dart +++ b/lib/pages/video/detail/introduction/widgets/action_item.dart @@ -1,9 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import 'package:pilipala/common/constants.dart'; import 'package:pilipala/utils/feed_back.dart'; class ActionItem extends StatelessWidget { - final Icon? icon; + final dynamic icon; final Icon? selectIcon; final Function? onTap; final Function? onLongPress; @@ -31,26 +32,37 @@ class ActionItem extends StatelessWidget { if (onLongPress != null) {onLongPress!()} }, borderRadius: StyleString.mdRadius, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const SizedBox(height: 4), - selectStatus - ? Icon(selectIcon!.icon!, - size: 18, color: Theme.of(context).colorScheme.primary) - : Icon(icon!.icon!, - size: 18, color: Theme.of(context).colorScheme.outline), - const SizedBox(height: 6), - Text( - text ?? '', - style: TextStyle( - color: selectStatus - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.outline, - fontSize: Theme.of(context).textTheme.labelSmall!.fontSize, - ), - ) - ], + child: SizedBox( + width: (Get.size.width - 24) / 5, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 4), + icon is Icon + ? Icon( + selectStatus ? selectIcon!.icon ?? icon!.icon : icon!.icon, + color: selectStatus + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.outline, + ) + : Image.asset( + 'assets/images/coin.png', + width: 25, + color: selectStatus + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.outline, + ), + const SizedBox(height: 6), + Text( + text ?? '', + style: TextStyle( + color: + selectStatus ? Theme.of(context).colorScheme.primary : null, + fontSize: Theme.of(context).textTheme.labelSmall!.fontSize, + ), + ) + ], + ), ), ); } diff --git a/lib/router/app_pages.dart b/lib/router/app_pages.dart index 7fda1bd8..2ca333f8 100644 --- a/lib/router/app_pages.dart +++ b/lib/router/app_pages.dart @@ -35,6 +35,7 @@ import '../pages/search/index.dart'; import '../pages/search_result/index.dart'; import '../pages/setting/extra_setting.dart'; import '../pages/setting/index.dart'; +import '../pages/setting/pages/action_menu_set.dart'; import '../pages/setting/pages/color_select.dart'; import '../pages/setting/pages/display_mode.dart'; import '../pages/setting/pages/font_size_select.dart'; @@ -174,6 +175,9 @@ class Routes { // navigation bar CustomGetPage( name: '/navbarSetting', page: () => const NavigationBarSetPage()), + // 操作菜单 + CustomGetPage( + name: '/actionMenuSet', page: () => const ActionMenuSetPage()), ]; } diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index 29cf1846..4a163446 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -149,7 +149,8 @@ class SettingBoxKey { tabbarSort = 'tabbarSort', // 首页tabbar dynamicBadgeMode = 'dynamicBadgeMode', enableGradientBg = 'enableGradientBg', - navBarSort = 'navBarSort'; + navBarSort = 'navBarSort', + actionTypeSort = 'actionTypeSort'; } class LocalCacheKey { From 897551bf237c65ec364507aa1c3d1cff865c6851 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 8 Jun 2024 15:35:45 +0800 Subject: [PATCH 3/8] =?UTF-8?q?fix:=20=E7=A7=81=E4=BF=A1=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../whisper_detail/widget/chat_item.dart | 203 +++++++++--------- 1 file changed, 101 insertions(+), 102 deletions(-) diff --git a/lib/pages/whisper_detail/widget/chat_item.dart b/lib/pages/whisper_detail/widget/chat_item.dart index ad11e4c3..0d37e8b3 100644 --- a/lib/pages/whisper_detail/widget/chat_item.dart +++ b/lib/pages/whisper_detail/widget/chat_item.dart @@ -259,115 +259,114 @@ class ChatItem extends StatelessWidget { ); case MsgType.auto_reply_push: return Container( - constraints: const BoxConstraints( - maxWidth: 300.0, // 设置最大宽度为200.0 + constraints: const BoxConstraints( + maxWidth: 300.0, // 设置最大宽度为200.0 + ), + decoration: BoxDecoration( + color: Theme.of(context) + .colorScheme + .secondaryContainer + .withOpacity(0.4), + borderRadius: const BorderRadius.all( + Radius.circular(16), ), - decoration: BoxDecoration( - color: Theme.of(context) - .colorScheme - .secondaryContainer - .withOpacity(0.4), - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(16), - topRight: Radius.circular(16), - bottomLeft: Radius.circular(6), - bottomRight: Radius.circular(16), - ), - ), - margin: const EdgeInsets.all(12), - padding: const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - content['main_title'], - style: TextStyle( - letterSpacing: 0.6, - height: 1.5, - color: textColor(context), - fontWeight: FontWeight.bold, - ), + ), + margin: const EdgeInsets.all(12), + padding: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + content['main_title'], + style: TextStyle( + letterSpacing: 0.6, + height: 1.5, + color: textColor(context), + fontWeight: FontWeight.bold, ), - for (var i in content['sub_cards']) ...[ - const SizedBox(height: 6), - GestureDetector( - onTap: () async { - RegExp bvRegex = RegExp(r'BV[0-9A-Za-z]{10}', - caseSensitive: false); - Iterable matches = - bvRegex.allMatches(i['jump_url']); - if (matches.isNotEmpty) { - Match match = matches.first; - String bvid = match.group(0)!; - try { - SmartDialog.showLoading(); - final int cid = await SearchHttp.ab2c(bvid: bvid); - final String heroTag = Utils.makeHeroTag(bvid); - SmartDialog.dismiss().then( - (e) => Get.toNamed( - '/video?bvid=$bvid&cid=$cid', - arguments: { - 'pic': i['cover_url'], - 'heroTag': heroTag, - }), - ); - } catch (err) { - SmartDialog.dismiss(); - SmartDialog.showToast(err.toString()); - } - } else { - SmartDialog.showToast('未匹配到 BV 号'); - Get.toNamed('/webview', - arguments: {'url': i['jump_url']}); - } - }, - child: Row( + ), + for (var i in content['sub_cards']) ...[ + const SizedBox(height: 6), + GestureDetector( + onTap: () async { + RegExp bvRegex = + RegExp(r'BV[0-9A-Za-z]{10}', caseSensitive: false); + Iterable matches = + bvRegex.allMatches(i['jump_url']); + if (matches.isNotEmpty) { + Match match = matches.first; + String bvid = match.group(0)!; + try { + SmartDialog.showLoading(); + final int cid = await SearchHttp.ab2c(bvid: bvid); + final String heroTag = Utils.makeHeroTag(bvid); + SmartDialog.dismiss().then( + (e) => Get.toNamed( + '/video?bvid=$bvid&cid=$cid', + arguments: { + 'pic': i['cover_url'], + 'heroTag': heroTag, + }), + ); + } catch (err) { + SmartDialog.dismiss(); + SmartDialog.showToast(err.toString()); + } + } else { + SmartDialog.showToast('未匹配到 BV 号'); + Get.toNamed('/webview', + arguments: {'url': i['jump_url']}); + } + }, + child: Row( + children: [ + NetworkImgLayer( + width: 130, + height: 130 * 9 / 16, + src: i['cover_url'], + ), + const SizedBox(width: 6), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - NetworkImgLayer( - width: 130, - height: 130 * 9 / 16, - src: i['cover_url'], + Text( + i['field1'], + maxLines: 2, + style: TextStyle( + letterSpacing: 0.6, + height: 1.5, + color: textColor(context), + fontWeight: FontWeight.bold, + ), + ), + Text( + i['field2'], + style: TextStyle( + letterSpacing: 0.6, + height: 1.5, + color: textColor(context).withOpacity(0.6), + fontSize: 12, + ), + ), + Text( + i['field3'], + style: TextStyle( + letterSpacing: 0.6, + height: 1.5, + color: textColor(context).withOpacity(0.6), + fontSize: 12, + ), ), - const SizedBox(width: 6), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - i['field1'], - maxLines: 2, - style: TextStyle( - letterSpacing: 0.6, - height: 1.5, - color: textColor(context), - fontWeight: FontWeight.bold, - ), - ), - Text( - i['field2'], - style: TextStyle( - letterSpacing: 0.6, - height: 1.5, - color: textColor(context).withOpacity(0.6), - fontSize: 12, - ), - ), - Text( - Utils.timeFormat(int.parse(i['field3'])), - style: TextStyle( - letterSpacing: 0.6, - height: 1.5, - color: textColor(context).withOpacity(0.6), - fontSize: 12, - ), - ), - ], - )), ], )), - ], + ], + ), + ), ], - )); + ], + ), + ); default: return Text( content != null && content != '' From a03d159a86b338c6ca6e7cc145cb83b86e603870 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 8 Jun 2024 17:36:55 +0800 Subject: [PATCH 4/8] =?UTF-8?q?mod:=20=E5=86=85=E5=AE=B9=E5=88=86=E5=8C=BA?= =?UTF-8?q?=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/search.dart | 4 ++-- lib/pages/search/widgets/search_text.dart | 10 ++++++---- lib/pages/search_panel/controller.dart | 6 +++--- lib/pages/search_panel/widgets/video_panel.dart | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/http/search.dart b/lib/http/search.dart index 70980547..075defc7 100644 --- a/lib/http/search.dart +++ b/lib/http/search.dart @@ -75,7 +75,7 @@ class SearchHttp { required page, String? order, int? duration, - int? tid, + int? tids, }) async { var reqData = { 'search_type': searchType.type, @@ -85,7 +85,7 @@ class SearchHttp { 'page': page, if (order != null) 'order': order, if (duration != null) 'duration': duration, - if (tid != null) 'tid': tid, + if (tids != null && tids != -1) 'tids': tids, }; var res = await Request().get(Api.searchByType, data: reqData); if (res.data['code'] == 0 && res.data['data']['numPages'] > 0) { diff --git a/lib/pages/search/widgets/search_text.dart b/lib/pages/search/widgets/search_text.dart index fbd1cfc6..d3ffafea 100644 --- a/lib/pages/search/widgets/search_text.dart +++ b/lib/pages/search/widgets/search_text.dart @@ -18,10 +18,12 @@ class SearchText extends StatelessWidget { @override Widget build(BuildContext context) { return Material( - color: Theme.of(context) - .colorScheme - .surfaceContainerHighest - .withOpacity(0.5), + color: isSelect + ? Theme.of(context).colorScheme.primaryContainer + : Theme.of(context) + .colorScheme + .surfaceContainerHighest + .withOpacity(0.5), borderRadius: BorderRadius.circular(6), child: Padding( padding: EdgeInsets.zero, diff --git a/lib/pages/search_panel/controller.dart b/lib/pages/search_panel/controller.dart index 56d83601..35113198 100644 --- a/lib/pages/search_panel/controller.dart +++ b/lib/pages/search_panel/controller.dart @@ -16,8 +16,8 @@ class SearchPanelController extends GetxController { RxString order = ''.obs; // 视频时长筛选 仅用于搜索视频 RxInt duration = 0.obs; - // 视频分区筛选 仅用于搜索视频 - RxInt tid = (-1).obs; + // 视频分区筛选 仅用于搜索视频 -1时不传 + RxInt tids = (-1).obs; Future onSearch({type = 'init'}) async { var result = await SearchHttp.searchByType( @@ -26,7 +26,7 @@ class SearchPanelController extends GetxController { page: page.value, order: searchType!.type != 'video' ? null : order.value, duration: searchType!.type != 'video' ? null : duration.value, - tid: searchType!.type != 'video' ? null : tid.value, + tids: searchType!.type != 'video' ? null : tids.value, ); if (result['status']) { if (type == 'onRefresh') { diff --git a/lib/pages/search_panel/widgets/video_panel.dart b/lib/pages/search_panel/widgets/video_panel.dart index 06ee5d4b..15745bde 100644 --- a/lib/pages/search_panel/widgets/video_panel.dart +++ b/lib/pages/search_panel/widgets/video_panel.dart @@ -323,7 +323,7 @@ class VideoPanelController extends GetxController { SearchPanelController ctr = Get.find( tag: 'video${searchPanelCtr.keyword!}'); - ctr.tid.value = i['value']; + ctr.tids.value = i['value']; Get.back(); SmartDialog.showLoading(msg: '获取中'); await ctr.onRefresh(); From 006ba8bc59f1898f77d7c95c4a8013a861455514 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 9 Jun 2024 14:51:59 +0800 Subject: [PATCH 5/8] =?UTF-8?q?feat:=20=E4=B8=80=E9=94=AE=E4=B8=89?= =?UTF-8?q?=E8=BF=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/Podfile.lock | 6 +- lib/models/common/action_type.dart | 1 - lib/pages/setting/pages/action_menu_set.dart | 10 +- lib/pages/setting/style_setting.dart | 10 +- .../video/detail/introduction/controller.dart | 55 ++-- lib/pages/video/detail/introduction/view.dart | 234 ++++++++++++++---- .../introduction/widgets/action_item.dart | 39 +-- lib/utils/global_data.dart | 3 +- 8 files changed, 246 insertions(+), 112 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 04fe6670..a400600f 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -23,7 +23,7 @@ PODS: - FMDB (2.7.5): - FMDB/standard (= 2.7.5) - FMDB/standard (2.7.5) - - gt3_flutter_plugin (0.0.8): + - gt3_flutter_plugin (0.0.9): - Flutter - GT3Captcha-iOS - GT3Captcha-iOS (0.15.8.3) @@ -171,13 +171,13 @@ SPEC CHECKSUMS: flutter_volume_controller: e4d5832f08008180f76e30faf671ffd5a425e529 fluttertoast: 31b00dabfa7fb7bacd9e7dbee580d7a2ff4bf265 FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a - gt3_flutter_plugin: bfa1f26e9a09dc00401514be5ed437f964cabf23 + gt3_flutter_plugin: 5bd2c08d3c19cbb6ee3b08f4358439e54c8ab2ee GT3Captcha-iOS: 5e3b1077834d8a9d6f4d64a447a30af3e14affe6 media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1 media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 - path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 + path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 saver_gallery: 2b4e584106fde2407ab51560f3851564963e6b78 screen_brightness_ios: 715ca807df953bf676d339f11464e438143ee625 diff --git a/lib/models/common/action_type.dart b/lib/models/common/action_type.dart index 2284df6c..b888be17 100644 --- a/lib/models/common/action_type.dart +++ b/lib/models/common/action_type.dart @@ -11,7 +11,6 @@ enum ActionType { dislike, downloadCover, copyLink, - threeAction, // backgroundPlay, // listenVideo, // downloadVideo, diff --git a/lib/pages/setting/pages/action_menu_set.dart b/lib/pages/setting/pages/action_menu_set.dart index f7d92e17..7a4fd9ba 100644 --- a/lib/pages/setting/pages/action_menu_set.dart +++ b/lib/pages/setting/pages/action_menu_set.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/models/common/action_type.dart'; +import 'package:pilipala/utils/global_data.dart'; import '../../../utils/storage.dart'; class ActionMenuSetPage extends StatefulWidget { @@ -12,14 +13,14 @@ class ActionMenuSetPage extends StatefulWidget { } class _ActionMenuSetPageState extends State { - Box settingStorage = GStrorage.setting; + Box setting = GStrorage.setting; late List actionTypeSort; late List allLabels; @override void initState() { super.initState(); - actionTypeSort = settingStorage.get(SettingBoxKey.actionTypeSort, + actionTypeSort = setting.get(SettingBoxKey.actionTypeSort, defaultValue: ['like', 'coin', 'collect', 'watchLater', 'share']); allLabels = actionMenuConfig; allLabels.sort((a, b) { @@ -36,8 +37,9 @@ class _ActionMenuSetPageState extends State { .where((i) => actionTypeSort.contains((i['value'] as ActionType).value)) .map((i) => (i['value'] as ActionType).value) .toList(); - settingStorage.put(SettingBoxKey.actionTypeSort, sortedTabbar); - SmartDialog.showToast('保存成功,下次启动时生效'); + setting.put(SettingBoxKey.actionTypeSort, sortedTabbar); + GlobalData().actionTypeSort = sortedTabbar; + SmartDialog.showToast('操作成功'); } void onReorder(int oldIndex, int newIndex) { diff --git a/lib/pages/setting/style_setting.dart b/lib/pages/setting/style_setting.dart index 20fdada0..5fca0c86 100644 --- a/lib/pages/setting/style_setting.dart +++ b/lib/pages/setting/style_setting.dart @@ -289,11 +289,11 @@ class _StyleSettingState extends State { onTap: () => Get.toNamed('/navbarSetting'), title: Text('底部导航栏设置', style: titleStyle), ), - ListTile( - dense: false, - onTap: () => Get.toNamed('/actionMenuSet'), - title: Text('操作菜单设置', style: titleStyle), - ), + // ListTile( + // dense: false, + // onTap: () => Get.toNamed('/actionMenuSet'), + // title: Text('操作菜单设置', style: titleStyle), + // ), if (Platform.isAndroid) ListTile( dense: false, diff --git a/lib/pages/video/detail/introduction/controller.dart b/lib/pages/video/detail/introduction/controller.dart index 9ed04870..9c542f21 100644 --- a/lib/pages/video/detail/introduction/controller.dart +++ b/lib/pages/video/detail/introduction/controller.dart @@ -38,6 +38,8 @@ class VideoIntroController extends GetxController { RxBool hasCoin = false.obs; // 是否收藏 RxBool hasFav = false.obs; + // 是否不喜欢 + RxBool hasDisLike = false.obs; Box userInfoCache = GStrorage.userInfo; bool userLogin = false; Rx favFolderData = FavFolderData().obs; @@ -153,36 +155,16 @@ class VideoIntroController extends GetxController { SmartDialog.showToast('🙏 UP已经收到了~'); return false; } - SmartDialog.show( - useSystem: true, - animationType: SmartAnimationType.centerFade_otherSlide, - builder: (BuildContext context) { - return AlertDialog( - title: const Text('提示'), - content: const Text('一键三连 给UP送温暖'), - actions: [ - TextButton( - onPressed: () => SmartDialog.dismiss(), - child: const Text('点错了')), - TextButton( - onPressed: () async { - var result = await VideoHttp.oneThree(bvid: bvid); - if (result['status']) { - hasLike.value = result["data"]["like"]; - hasCoin.value = result["data"]["coin"]; - hasFav.value = result["data"]["fav"]; - SmartDialog.showToast('三连成功 🎉'); - } else { - SmartDialog.showToast(result['msg']); - } - SmartDialog.dismiss(); - }, - child: const Text('确认'), - ) - ], - ); - }, - ); + var result = await VideoHttp.oneThree(bvid: bvid); + print('🤣🦴:${result["data"]}'); + if (result['status']) { + hasLike.value = result["data"]["like"]; + hasCoin.value = result["data"]["coin"]; + hasFav.value = result["data"]["fav"]; + SmartDialog.showToast('三连成功'); + } else { + SmartDialog.showToast(result['msg']); + } } // (取消)点赞 @@ -193,9 +175,8 @@ class VideoIntroController extends GetxController { } var result = await VideoHttp.likeVideo(bvid: bvid, type: !hasLike.value); if (result['status']) { - // hasLike.value = result["data"] == 1 ? true : false; if (!hasLike.value) { - SmartDialog.showToast('点赞成功 👍'); + SmartDialog.showToast('点赞成功'); hasLike.value = true; videoDetail.value.stat!.like = videoDetail.value.stat!.like! + 1; } else if (hasLike.value) { @@ -215,6 +196,10 @@ class VideoIntroController extends GetxController { SmartDialog.showToast('账号未登录'); return; } + if (hasCoin.value) { + SmartDialog.showToast('已投过币了'); + return; + } showDialog( context: Get.context!, builder: (context) { @@ -236,7 +221,7 @@ class VideoIntroController extends GetxController { var res = await VideoHttp.coinVideo( bvid: bvid, multiply: _tempThemeValue); if (res['status']) { - SmartDialog.showToast('投币成功 👏'); + SmartDialog.showToast('投币成功'); hasCoin.value = true; videoDetail.value.stat!.coin = videoDetail.value.stat!.coin! + _tempThemeValue; @@ -269,7 +254,7 @@ class VideoIntroController extends GetxController { if (result['status']) { // 重新获取收藏状态 await queryHasFavVideo(); - SmartDialog.showToast('✅ 操作成功'); + SmartDialog.showToast('操作成功'); } else { SmartDialog.showToast(result['msg']); } @@ -299,7 +284,7 @@ class VideoIntroController extends GetxController { Get.back(); // 重新获取收藏状态 await queryHasFavVideo(); - SmartDialog.showToast('✅ 操作成功'); + SmartDialog.showToast('操作成功'); } else { SmartDialog.showToast(result['msg']); } diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index ceec8fa4..91287c59 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -1,3 +1,6 @@ +import 'dart:ffi'; + +import 'package:easy_debounce/easy_throttle.dart'; import 'package:expandable/expandable.dart'; import 'package:flutter/services.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -15,6 +18,7 @@ import 'package:pilipala/models/video_detail_res.dart'; import 'package:pilipala/pages/video/detail/introduction/controller.dart'; import 'package:pilipala/pages/video/detail/widgets/ai_detail.dart'; import 'package:pilipala/utils/feed_back.dart'; +import 'package:pilipala/utils/global_data.dart'; import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/utils.dart'; import '../../../../http/user.dart'; @@ -146,13 +150,18 @@ class _VideoInfoState extends State with TickerProviderStateMixin { RxBool isExpand = false.obs; late ExpandableController _expandableCtr; - void Function()? handleState(Future Function() action) { + // 一键三连动画 + late AnimationController _controller; + late Animation _scaleTransition; + final RxDouble _progress = 0.0.obs; + + void Function()? handleState(Future Function() action) { return isProcessing ? null : () async { - setState(() => isProcessing = true); - await action(); - setState(() => isProcessing = false); + isProcessing = true; + await action.call(); + isProcessing = false; }; } @@ -169,6 +178,25 @@ class _VideoInfoState extends State with TickerProviderStateMixin { follower = Utils.numFormat(videoIntroController.userStat['follower']); enableAi = setting.get(SettingBoxKey.enableAi, defaultValue: true); _expandableCtr = ExpandableController(initialExpanded: false); + + /// 一键三连动画 + _controller = AnimationController( + duration: const Duration(milliseconds: 1500), + reverseDuration: const Duration(milliseconds: 300), + vsync: this, + ); + _scaleTransition = Tween(begin: 0.5, end: 1.5).animate(_controller) + ..addListener(() async { + _progress.value = _scaleTransition.value - 0.5; + if (_progress.value == 1) { + if (_controller.status == AnimationStatus.completed) { + await videoIntroController.actionOneThree(); + } + _progress.value = 0; + _scaleTransition.removeListener(() {}); + _controller.stop(); + } + }); } // 收藏 @@ -249,6 +277,8 @@ class _VideoInfoState extends State with TickerProviderStateMixin { @override void dispose() { _expandableCtr.dispose(); + _controller.dispose(); + _scaleTransition.removeListener(() {}); super.dispose(); } @@ -538,6 +568,157 @@ class _VideoInfoState extends State with TickerProviderStateMixin { } Widget actionGrid(BuildContext context, videoIntroController) { + final actionTypeSort = GlobalData().actionTypeSort; + + Widget progressWidget(progress) { + return SizedBox( + width: 68, + height: 68, + child: CircularProgressIndicator( + value: progress.value, + strokeWidth: 4, + ), + ); + } + + Map menuListWidgets = { + 'like': Obx( + () { + bool likeStatus = videoIntroController.hasLike.value; + ColorScheme colorScheme = Theme.of(context).colorScheme; + return Stack( + alignment: Alignment.center, + children: [ + progressWidget(_progress), + InkWell( + onTapDown: (details) { + feedBack(); + _controller.forward(); + }, + onTapUp: (TapUpDetails details) { + if (_progress.value == 0) { + feedBack(); + EasyThrottle.throttle( + 'my-throttler', const Duration(milliseconds: 200), () { + videoIntroController.actionLikeVideo(); + }); + } + _controller.reverse(); + }, + borderRadius: StyleString.mdRadius, + child: SizedBox( + width: (Get.size.width - 24) / 5, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 4), + AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + transitionBuilder: + (Widget child, Animation animation) { + return ScaleTransition( + scale: animation, child: child); + }, + child: Icon( + key: ValueKey(likeStatus), + likeStatus + ? Icons.thumb_up + : Icons.thumb_up_alt_outlined, + color: likeStatus + ? colorScheme.primary + : colorScheme.outline, + ), + ), + const SizedBox(height: 6), + Text( + widget.videoDetail!.stat!.like!.toString(), + style: TextStyle( + color: likeStatus ? colorScheme.primary : null, + fontSize: + Theme.of(context).textTheme.labelSmall!.fontSize, + ), + ) + ], + ), + ), + ), + ], + ); + }, + ), + 'coin': Obx( + () => Stack( + alignment: Alignment.center, + children: [ + progressWidget(_progress), + ActionItem( + icon: Image.asset('assets/images/coin.png', width: 30), + onTap: handleState(videoIntroController.actionCoinVideo), + selectStatus: videoIntroController.hasCoin.value, + text: widget.videoDetail!.stat!.coin!.toString(), + ), + ], + ), + ), + 'collect': Obx( + () => Stack( + alignment: Alignment.center, + children: [ + progressWidget(_progress), + ActionItem( + icon: const Icon(Icons.star_border), + selectIcon: const Icon(Icons.star), + onTap: () => showFavBottomSheet(), + onLongPress: () => showFavBottomSheet(type: 'longPress'), + selectStatus: videoIntroController.hasFav.value, + text: widget.videoDetail!.stat!.favorite!.toString(), + ), + ], + ), + ), + 'watchLater': ActionItem( + icon: const Icon(Icons.watch_later_outlined), + onTap: () async { + final res = + await UserHttp.toViewLater(bvid: widget.videoDetail!.bvid); + SmartDialog.showToast(res['msg']); + }, + selectStatus: false, + text: '稍后看', + ), + 'share': ActionItem( + icon: const Icon(Icons.share), + onTap: () => videoIntroController.actionShareVideo(), + selectStatus: false, + text: '分享', + ), + 'dislike': Obx( + () => ActionItem( + icon: const Icon(Icons.thumb_down_alt_outlined), + selectIcon: const Icon(Icons.thumb_down), + onTap: () {}, + selectStatus: videoIntroController.hasDisLike.value, + text: '不喜欢', + ), + ), + 'downloadCover': ActionItem( + icon: const Icon(Icons.image_outlined), + onTap: () {}, + selectStatus: false, + text: '下载封面', + ), + 'copyLink': ActionItem( + icon: const Icon(Icons.link_outlined), + onTap: () {}, + selectStatus: false, + text: '复制链接', + ), + }; + final List list = []; + for (var i = 0; i < actionTypeSort.length; i++) { + list.add(menuListWidgets[actionTypeSort[i]]!); + } + return LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { return Container( @@ -545,50 +726,7 @@ class _VideoInfoState extends State with TickerProviderStateMixin { height: constraints.maxWidth / 5, child: ListView( scrollDirection: Axis.horizontal, - children: [ - Obx( - () => ActionItem( - icon: const Icon(Icons.thumb_up_alt_outlined), - selectIcon: const Icon(Icons.thumb_up), - onTap: handleState(videoIntroController.actionLikeVideo), - selectStatus: videoIntroController.hasLike.value, - text: widget.videoDetail!.stat!.like!.toString()), - ), - Obx( - () => ActionItem( - icon: Image.asset('assets/images/coin.png', width: 30), - onTap: handleState(videoIntroController.actionCoinVideo), - selectStatus: videoIntroController.hasCoin.value, - text: widget.videoDetail!.stat!.coin!.toString(), - ), - ), - Obx( - () => ActionItem( - icon: const Icon(Icons.star_border), - selectIcon: const Icon(Icons.star), - onTap: () => showFavBottomSheet(), - onLongPress: () => showFavBottomSheet(type: 'longPress'), - selectStatus: videoIntroController.hasFav.value, - text: widget.videoDetail!.stat!.favorite!.toString(), - ), - ), - ActionItem( - icon: const Icon(Icons.watch_later_outlined), - onTap: () async { - final res = - await UserHttp.toViewLater(bvid: widget.videoDetail!.bvid); - SmartDialog.showToast(res['msg']); - }, - selectStatus: false, - text: '稍后看', - ), - ActionItem( - icon: const Icon(Icons.share), - onTap: () => videoIntroController.actionShareVideo(), - selectStatus: false, - text: '分享', - ), - ], + children: list, ), ); }); diff --git a/lib/pages/video/detail/introduction/widgets/action_item.dart b/lib/pages/video/detail/introduction/widgets/action_item.dart index 2a89afe7..af409dfc 100644 --- a/lib/pages/video/detail/introduction/widgets/action_item.dart +++ b/lib/pages/video/detail/introduction/widgets/action_item.dart @@ -38,20 +38,29 @@ class ActionItem extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ const SizedBox(height: 4), - icon is Icon - ? Icon( - selectStatus ? selectIcon!.icon ?? icon!.icon : icon!.icon, - color: selectStatus - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.outline, - ) - : Image.asset( - 'assets/images/coin.png', - width: 25, - color: selectStatus - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.outline, - ), + AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + transitionBuilder: (Widget child, Animation animation) { + return ScaleTransition(scale: animation, child: child); + }, + child: icon is Icon + ? Icon( + selectStatus + ? selectIcon!.icon ?? icon!.icon + : icon!.icon, + color: selectStatus + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.outline, + ) + : Image.asset( + key: ValueKey(selectStatus), + 'assets/images/coin.png', + width: 25, + color: selectStatus + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.outline, + ), + ), const SizedBox(height: 6), Text( text ?? '', @@ -60,7 +69,7 @@ class ActionItem extends StatelessWidget { selectStatus ? Theme.of(context).colorScheme.primary : null, fontSize: Theme.of(context).textTheme.labelSmall!.fontSize, ), - ) + ), ], ), ), diff --git a/lib/utils/global_data.dart b/lib/utils/global_data.dart index 29791210..97bff5a5 100644 --- a/lib/utils/global_data.dart +++ b/lib/utils/global_data.dart @@ -11,7 +11,8 @@ class GlobalData { bool enablePlayerControlAnimation = true; final bool enableMYBar = setting.get(SettingBoxKey.enableMYBar, defaultValue: true); - + List actionTypeSort = setting.get(SettingBoxKey.actionTypeSort, + defaultValue: ['like', 'coin', 'collect', 'watchLater', 'share']); // 私有构造函数 GlobalData._(); From d94ddca9056f1f00f8b2a7412a3cdcf86e07edfa Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 10 Jun 2024 00:58:04 +0800 Subject: [PATCH 6/8] =?UTF-8?q?opt:=20=E4=B8=89=E8=BF=9E=E8=BF=9B=E5=BA=A6?= =?UTF-8?q?=E6=9D=A1=E6=A0=B7=E5=BC=8F&=E7=99=BB=E5=BD=95=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/introduction/view.dart | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index 91287c59..22f2dfe2 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -1,5 +1,3 @@ -import 'dart:ffi'; - import 'package:easy_debounce/easy_throttle.dart'; import 'package:expandable/expandable.dart'; import 'package:flutter/services.dart'; @@ -576,7 +574,7 @@ class _VideoInfoState extends State with TickerProviderStateMixin { height: 68, child: CircularProgressIndicator( value: progress.value, - strokeWidth: 4, + strokeWidth: 2, ), ); } @@ -593,6 +591,10 @@ class _VideoInfoState extends State with TickerProviderStateMixin { InkWell( onTapDown: (details) { feedBack(); + if (videoIntroController.userInfo == null) { + SmartDialog.showToast('账号未登录'); + return; + } _controller.forward(); }, onTapUp: (TapUpDetails details) { From 61c29d30829a59d189225abfc1eae830fc0d1ff4 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 10 Jun 2024 01:09:28 +0800 Subject: [PATCH 7/8] =?UTF-8?q?fix:=20=E8=B7=B3=E8=BD=AC=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/login/controller.dart | 6 +++--- lib/pages/login/view.dart | 30 +++++++++++++----------------- lib/pages/mine/controller.dart | 3 +-- 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/lib/pages/login/controller.dart b/lib/pages/login/controller.dart index b5ddba16..fbb06e2f 100644 --- a/lib/pages/login/controller.dart +++ b/lib/pages/login/controller.dart @@ -31,7 +31,7 @@ class LoginPageController extends GetxController { // 倒计时60s RxInt seconds = 60.obs; - late Timer timer; + Timer? timer; RxBool smsCodeSendStatus = false.obs; // 默认密码登录 @@ -43,7 +43,7 @@ class LoginPageController extends GetxController { late int webSmsCode; RxInt validSeconds = 180.obs; - late Timer validTimer; + Timer? validTimer; late String qrcodeKey; // 监听pageView切换 @@ -329,7 +329,7 @@ class LoginPageController extends GetxController { var res = await LoginHttp.queryWebQrcodeStatus(qrcodeKey); if (res['status']) { await LoginUtils.confirmLogin('', null); - validTimer.cancel(); + validTimer?.cancel(); Get.back(); } } diff --git a/lib/pages/login/view.dart b/lib/pages/login/view.dart index cd91ea26..85a8adf0 100644 --- a/lib/pages/login/view.dart +++ b/lib/pages/login/view.dart @@ -15,8 +15,10 @@ class _LoginPageState extends State { final LoginPageController _loginPageCtr = Get.put(LoginPageController()); @override - void initState() { - super.initState(); + void dispose() { + _loginPageCtr.validTimer?.cancel(); + _loginPageCtr.timer?.cancel(); + super.dispose(); } @override @@ -51,7 +53,7 @@ class _LoginPageState extends State { }, ); }, - icon: const Icon(Icons.language), + icon: const Icon(Icons.language, size: 20), ), IconButton( tooltip: '二维码登录', @@ -90,7 +92,7 @@ class _LoginPageState extends State { Map data = snapshot.data as Map; return QrImageView( data: data['data']['url'], - backgroundColor: Colors.transparent, + backgroundColor: Colors.white, ); } else { return const Center( @@ -131,9 +133,11 @@ class _LoginPageState extends State { ); }); }, - ); + ).then((value) { + _loginPageCtr.validTimer!.cancel(); + }); }, - icon: const Icon(Icons.qr_code), + icon: const Icon(Icons.qr_code, size: 20), ), const SizedBox(width: 22), ], @@ -164,17 +168,9 @@ class _LoginPageState extends State { fontSize: 34, fontWeight: FontWeight.w500), ), - Row( - children: [ - Text( - '请使用您的 BiliBili 账号登录。', - style: Theme.of(context).textTheme.titleSmall!, - ), - GestureDetector( - onTap: () {}, - child: const Icon(Icons.info_outline, size: 16), - ) - ], + Text( + '请使用您的 BiliBili 账号登录。', + style: Theme.of(context).textTheme.titleSmall!, ), Container( margin: const EdgeInsets.only(top: 38, bottom: 15), diff --git a/lib/pages/mine/controller.dart b/lib/pages/mine/controller.dart index 153a7162..75c50d82 100644 --- a/lib/pages/mine/controller.dart +++ b/lib/pages/mine/controller.dart @@ -33,8 +33,7 @@ class MineController extends GetxController { onLogin() async { if (!userLogin.value) { - // RoutePush.loginPush(); - Get.toNamed('/loginPage'); + Get.toNamed('/loginPage', preventDuplicates: false); } else { int mid = userInfo.value.mid!; String face = userInfo.value.face!; From 51be62cd26f06364d9a8ef923ed13b874ce6c88d Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 10 Jun 2024 12:50:15 +0800 Subject: [PATCH 8/8] =?UTF-8?q?opt:=20=E4=B8=80=E9=94=AE=E4=B8=89=E8=BF=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/introduction/view.dart | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index 22f2dfe2..3b89d1de 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -185,7 +185,8 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ); _scaleTransition = Tween(begin: 0.5, end: 1.5).animate(_controller) ..addListener(() async { - _progress.value = _scaleTransition.value - 0.5; + _progress.value = + double.parse((_scaleTransition.value - 0.5).toStringAsFixed(3)); if (_progress.value == 1) { if (_controller.status == AnimationStatus.completed) { await videoIntroController.actionOneThree(); @@ -570,8 +571,8 @@ class _VideoInfoState extends State with TickerProviderStateMixin { Widget progressWidget(progress) { return SizedBox( - width: 68, - height: 68, + width: 33, + height: 33, child: CircularProgressIndicator( value: progress.value, strokeWidth: 2, @@ -585,16 +586,15 @@ class _VideoInfoState extends State with TickerProviderStateMixin { bool likeStatus = videoIntroController.hasLike.value; ColorScheme colorScheme = Theme.of(context).colorScheme; return Stack( - alignment: Alignment.center, children: [ - progressWidget(_progress), + Positioned(child: progressWidget(_progress), top: 15, left: 24), InkWell( onTapDown: (details) { feedBack(); - if (videoIntroController.userInfo == null) { - SmartDialog.showToast('账号未登录'); - return; - } + // if (videoIntroController.userInfo == null) { + // SmartDialog.showToast('账号未登录'); + // return; + // } _controller.forward(); }, onTapUp: (TapUpDetails details) { @@ -650,9 +650,8 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ), 'coin': Obx( () => Stack( - alignment: Alignment.center, children: [ - progressWidget(_progress), + Positioned(child: progressWidget(_progress), top: 15, left: 24), ActionItem( icon: Image.asset('assets/images/coin.png', width: 30), onTap: handleState(videoIntroController.actionCoinVideo), @@ -664,9 +663,8 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ), 'collect': Obx( () => Stack( - alignment: Alignment.center, children: [ - progressWidget(_progress), + Positioned(child: progressWidget(_progress), top: 15, left: 24), ActionItem( icon: const Icon(Icons.star_border), selectIcon: const Icon(Icons.star),