Merge branch 'feature-updateVideoDetailStructure'
This commit is contained in:
BIN
assets/images/coin.png
Normal file
BIN
assets/images/coin.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.0 KiB |
@ -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
|
||||
|
||||
93
lib/models/common/action_type.dart
Normal file
93
lib/models/common/action_type.dart
Normal file
@ -0,0 +1,93 @@
|
||||
// 操作类型的枚举值:点赞 不喜欢 收藏 投币 稍后再看 下载封面 后台播放 听视频 分享 下载视频
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
enum ActionType {
|
||||
like,
|
||||
coin,
|
||||
collect,
|
||||
watchLater,
|
||||
share,
|
||||
dislike,
|
||||
downloadCover,
|
||||
copyLink,
|
||||
// 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<Map> 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,
|
||||
},
|
||||
];
|
||||
102
lib/pages/setting/pages/action_menu_set.dart
Normal file
102
lib/pages/setting/pages/action_menu_set.dart
Normal file
@ -0,0 +1,102 @@
|
||||
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 {
|
||||
const ActionMenuSetPage({super.key});
|
||||
|
||||
@override
|
||||
State<ActionMenuSetPage> createState() => _ActionMenuSetPageState();
|
||||
}
|
||||
|
||||
class _ActionMenuSetPageState extends State<ActionMenuSetPage> {
|
||||
Box setting = GStrorage.setting;
|
||||
late List<String> actionTypeSort;
|
||||
late List<Map> allLabels;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
actionTypeSort = setting.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<String> sortedTabbar = allLabels
|
||||
.where((i) => actionTypeSort.contains((i['value'] as ActionType).value))
|
||||
.map<String>((i) => (i['value'] as ActionType).value)
|
||||
.toList();
|
||||
setting.put(SettingBoxKey.actionTypeSort, sortedTabbar);
|
||||
GlobalData().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,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -289,6 +289,11 @@ class _StyleSettingState extends State<StyleSetting> {
|
||||
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,
|
||||
|
||||
@ -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 = 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);
|
||||
print('🤣🦴:${result["data"]}');
|
||||
if (result['status']) {
|
||||
hasLike.value = result["data"]["like"];
|
||||
hasCoin.value = result["data"]["coin"];
|
||||
hasFav.value = result["data"]["fav"];
|
||||
SmartDialog.showToast('三连成功 🎉');
|
||||
SmartDialog.showToast('三连成功');
|
||||
} else {
|
||||
SmartDialog.showToast(result['msg']);
|
||||
}
|
||||
SmartDialog.dismiss();
|
||||
},
|
||||
child: const Text('确认'),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// (取消)点赞
|
||||
@ -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']);
|
||||
}
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
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';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
@ -16,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';
|
||||
@ -147,13 +150,18 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
RxBool isExpand = false.obs;
|
||||
late ExpandableController _expandableCtr;
|
||||
|
||||
void Function()? handleState(Future Function() action) {
|
||||
// 一键三连动画
|
||||
late AnimationController _controller;
|
||||
late Animation<double> _scaleTransition;
|
||||
final RxDouble _progress = 0.0.obs;
|
||||
|
||||
void Function()? handleState(Future<dynamic> Function() action) {
|
||||
return isProcessing
|
||||
? null
|
||||
: () async {
|
||||
setState(() => isProcessing = true);
|
||||
await action();
|
||||
setState(() => isProcessing = false);
|
||||
isProcessing = true;
|
||||
await action.call();
|
||||
isProcessing = false;
|
||||
};
|
||||
}
|
||||
|
||||
@ -170,6 +178,25 @@ class _VideoInfoState extends State<VideoInfo> 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<double>(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();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 收藏
|
||||
@ -250,6 +277,8 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
@override
|
||||
void dispose() {
|
||||
_expandableCtr.dispose();
|
||||
_controller.dispose();
|
||||
_scaleTransition.removeListener(() {});
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@ -539,47 +568,116 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
}
|
||||
|
||||
Widget actionGrid(BuildContext context, videoIntroController) {
|
||||
return LayoutBuilder(
|
||||
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: <Widget>[
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.thumbsUp),
|
||||
selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp),
|
||||
onTap: handleState(videoIntroController.actionLikeVideo),
|
||||
selectStatus: videoIntroController.hasLike.value,
|
||||
text: widget.videoDetail!.stat!.like!.toString()),
|
||||
final actionTypeSort = GlobalData().actionTypeSort;
|
||||
|
||||
Widget progressWidget(progress) {
|
||||
return SizedBox(
|
||||
width: 68,
|
||||
height: 68,
|
||||
child: CircularProgressIndicator(
|
||||
value: progress.value,
|
||||
strokeWidth: 4,
|
||||
),
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.b),
|
||||
selectIcon: const Icon(FontAwesomeIcons.b),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, Widget> 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<double> animation) {
|
||||
return ScaleTransition(
|
||||
scale: animation, child: child);
|
||||
},
|
||||
child: Icon(
|
||||
key: ValueKey<bool>(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(),
|
||||
),
|
||||
],
|
||||
),
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.star),
|
||||
selectIcon: const Icon(FontAwesomeIcons.solidStar),
|
||||
),
|
||||
'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(),
|
||||
),
|
||||
],
|
||||
),
|
||||
ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.clock),
|
||||
),
|
||||
'watchLater': ActionItem(
|
||||
icon: const Icon(Icons.watch_later_outlined),
|
||||
onTap: () async {
|
||||
final res =
|
||||
await UserHttp.toViewLater(bvid: widget.videoDetail!.bvid);
|
||||
@ -588,13 +686,47 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
selectStatus: false,
|
||||
text: '稍后看',
|
||||
),
|
||||
ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.shareFromSquare),
|
||||
'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<Widget> list = [];
|
||||
for (var i = 0; i < actionTypeSort.length; i++) {
|
||||
list.add(menuListWidgets[actionTypeSort[i]]!);
|
||||
}
|
||||
|
||||
return LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(top: 6, bottom: 4),
|
||||
height: constraints.maxWidth / 5,
|
||||
child: ListView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
children: list,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
@ -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,27 +32,47 @@ class ActionItem extends StatelessWidget {
|
||||
if (onLongPress != null) {onLongPress!()}
|
||||
},
|
||||
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<double> animation) {
|
||||
return ScaleTransition(scale: animation, child: child);
|
||||
},
|
||||
child: icon is Icon
|
||||
? Icon(
|
||||
selectStatus
|
||||
? Icon(selectIcon!.icon!,
|
||||
size: 18, color: Theme.of(context).colorScheme.primary)
|
||||
: Icon(icon!.icon!,
|
||||
size: 18, color: Theme.of(context).colorScheme.outline),
|
||||
? selectIcon!.icon ?? icon!.icon
|
||||
: icon!.icon,
|
||||
color: selectStatus
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.outline,
|
||||
)
|
||||
: Image.asset(
|
||||
key: ValueKey<bool>(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 ?? '',
|
||||
style: TextStyle(
|
||||
color: selectStatus
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.outline,
|
||||
color:
|
||||
selectStatus ? Theme.of(context).colorScheme.primary : null,
|
||||
fontSize: Theme.of(context).textTheme.labelSmall!.fontSize,
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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()),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@ -11,7 +11,8 @@ class GlobalData {
|
||||
bool enablePlayerControlAnimation = true;
|
||||
final bool enableMYBar =
|
||||
setting.get(SettingBoxKey.enableMYBar, defaultValue: true);
|
||||
|
||||
List<String> actionTypeSort = setting.get(SettingBoxKey.actionTypeSort,
|
||||
defaultValue: ['like', 'coin', 'collect', 'watchLater', 'share']);
|
||||
// 私有构造函数
|
||||
GlobalData._();
|
||||
|
||||
|
||||
@ -149,7 +149,8 @@ class SettingBoxKey {
|
||||
tabbarSort = 'tabbarSort', // 首页tabbar
|
||||
dynamicBadgeMode = 'dynamicBadgeMode',
|
||||
enableGradientBg = 'enableGradientBg',
|
||||
navBarSort = 'navBarSort';
|
||||
navBarSort = 'navBarSort',
|
||||
actionTypeSort = 'actionTypeSort';
|
||||
}
|
||||
|
||||
class LocalCacheKey {
|
||||
|
||||
Reference in New Issue
Block a user