feat: 视频操作

This commit is contained in:
guozhigq
2023-05-12 00:03:10 +08:00
parent e426236741
commit 7bcdd209ba
10 changed files with 447 additions and 52 deletions

View File

@ -1,3 +1,18 @@
import 'package:get/get.dart';
import 'package:pilipala/http/user.dart';
import 'package:pilipala/models/user/fav_folder.dart';
import 'package:pilipala/utils/storage.dart';
class FavController extends GetxController {}
class FavController extends GetxController {
Rx<FavFolderData> favFolderData = FavFolderData().obs;
Future<dynamic> queryFavFolder() async {
var res = await await UserHttp.userfavFolder(
pn: 1,
ps: 10,
mid: GStrorage.user.get(UserBoxKey.userMid),
);
favFolderData.value = res['data'];
return res;
}
}

View File

@ -1,4 +1,7 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:pilipala/common/widgets/http_error.dart';
import 'package:pilipala/pages/fav/index.dart';
class FavPage extends StatefulWidget {
const FavPage({super.key});
@ -8,12 +11,64 @@ class FavPage extends StatefulWidget {
}
class _FavPageState extends State<FavPage> {
final FavController _favController = Get.put(FavController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: false,
title: Text('我的收藏'),
title: const Text('我的收藏'),
),
body: FutureBuilder(
future: _favController.queryFavFolder(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
Map data = snapshot.data as Map;
if (data['status']) {
return Obx(
() => ListView.builder(
itemCount: _favController.favFolderData.value.list!.length,
itemBuilder: (context, index) {
return ListTile(
onTap: () => Get.toNamed(
'/favDetail',
arguments:
_favController.favFolderData.value.list![index],
parameters: {
'mediaId': _favController
.favFolderData.value.list![index].id
.toString(),
},
),
leading: const Icon(Icons.folder_special_outlined),
minLeadingWidth: 0,
title: Text(_favController
.favFolderData.value.list![index].title!),
subtitle: Text(
'${_favController.favFolderData.value.list![index].mediaCount}个内容',
style: TextStyle(
color: Theme.of(context).colorScheme.outline,
fontSize: Theme.of(context)
.textTheme
.labelSmall!
.fontSize),
),
);
},
),
);
} else {
return HttpError(
errMsg: data['msg'],
fn: () => setState(() {}),
);
}
} else {
// 骨架屏
return Text('请求中');
}
},
),
);
}

View File

@ -56,12 +56,12 @@ class MainController extends GetxController {
// 'icon': const Icon(Icons.person_outline),
// 'selectedIcon': const Icon(Icons.person),
'icon': const Icon(
CupertinoIcons.tray_full,
size: 21,
CupertinoIcons.folder,
size: 20,
),
'selectedIcon': const Icon(
CupertinoIcons.tray_full_fill,
size: 21,
CupertinoIcons.folder_fill,
size: 20,
),
'label': "媒体库",
}

View File

@ -10,12 +10,12 @@ class MediaController extends GetxController {
{
'icon': Icons.file_download_outlined,
'title': '离线缓存',
'onTap': () => Get.toNamed('/fav'),
'onTap': () {},
},
{
'icon': Icons.history,
'title': '观看记录',
'onTap': () => Get.toNamed('/fav'),
'onTap': () {},
},
{
'icon': Icons.star_border,
@ -24,8 +24,8 @@ class MediaController extends GetxController {
},
{
'icon': Icons.watch_later_outlined,
'title': '再看',
'onTap': () => Get.toNamed('/fav'),
'title': '再看',
'onTap': () => {},
},
];

View File

@ -56,8 +56,13 @@ class _MediaPageState extends State<MediaPage>
color: primary,
),
),
contentPadding:
const EdgeInsets.only(left: 15, top: 2, bottom: 2),
minLeadingWidth: 0,
title: Text(i['title']),
title: Text(
i['title'],
style: const TextStyle(fontSize: 15),
),
),
],
favFolder()
@ -105,13 +110,11 @@ class _MediaPageState extends State<MediaPage>
),
),
),
trailing: Padding(
padding: const EdgeInsets.only(right: 10),
child: Text(
'查看全部',
style: TextStyle(
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
color: Theme.of(context).colorScheme.outline),
trailing: IconButton(
onPressed: () => _mediaController.queryFavFolder(),
icon: const Icon(
Icons.refresh,
size: 20,
),
),
),

View File

@ -1,3 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:pilipala/http/user.dart';
import 'package:pilipala/http/video.dart';
@ -26,6 +28,13 @@ class VideoIntroController extends GetxController {
// up主粉丝数
Map userStat = {'follower': '-'};
// 是否点赞
RxBool hasLike = false.obs;
// 是否投币
RxBool hasCoin = false.obs;
// 是否收藏
RxBool hasFav = false.obs;
@override
void onInit() {
super.onInit();
@ -57,6 +66,13 @@ class VideoIntroController extends GetxController {
}
// 获取到粉丝数再返回
await queryUserStat();
// 获取点赞状态
queryHasLikeVideo();
// 获取投币状态
queryHasCoinVideo();
// 获取收藏状态
queryHasFavVideo();
return result;
}
@ -67,4 +83,51 @@ class VideoIntroController extends GetxController {
userStat = result['data'];
}
}
// 获取点赞状态
Future queryHasLikeVideo() async {
var result = await VideoHttp.hasLikeVideo(aid: aid);
// data num 被点赞标志 0未点赞 1已点赞
hasLike.value = result["data"] == 1 ? true : false;
}
// 获取投币状态
Future queryHasCoinVideo() async {
var result = await VideoHttp.hasCoinVideo(aid: aid);
hasCoin.value = result["data"]['multiply'] == 0 ? false : true;
}
// 获取收藏状态
Future queryHasFavVideo() async {
var result = await VideoHttp.hasFavVideo(aid: aid);
hasFav.value = result["data"]['favoured'];
}
// 一键三连
// (取消)点赞
Future actionLikeVideo() async {
var result = await VideoHttp.likeVideo(aid: aid, type: !hasLike.value);
if (result['status']) {
hasLike.value = result["data"] == 1 ? true : false;
} else {
SmartDialog.showToast(result['msg']);
}
}
// 投币
Future actionCoinVideo() async {
print('投币');
}
// (取消)收藏
Future actionFavVideo() async {
print('(取消)收藏');
// var result = await VideoHttp.favVideo(aid: aid, type: true, ids: '');
}
// 分享视频
Future actionShareVideo() async {
print('分享视频');
}
}

View File

@ -4,6 +4,8 @@ import 'package:get/get.dart';
import 'package:flutter/material.dart';
import 'package:pilipala/common/constants.dart';
import 'package:pilipala/common/widgets/http_error.dart';
import 'package:pilipala/pages/fav/index.dart';
import 'package:pilipala/pages/favDetail/index.dart';
import 'package:pilipala/pages/video/detail/widgets/expandable_section.dart';
import 'package:pilipala/common/widgets/network_img_layer.dart';
import 'package:pilipala/common/widgets/stat/danmu.dart';
@ -100,6 +102,8 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
/// 手动控制
late Animation<double>? _manualAnimation;
final FavController _favController = Get.put(FavController());
@override
void initState() {
super.initState();
@ -113,6 +117,102 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
Tween<double>(begin: 0.5, end: 1.5).animate(_manualController!);
}
showFavBottomSheet() {
Get.bottomSheet(
useRootNavigator: true,
isScrollControlled: true,
Container(
height: 450,
color: Theme.of(context).colorScheme.background,
child: Column(
children: [
AppBar(
toolbarHeight: 50,
automaticallyImplyLeading: false,
centerTitle: false,
elevation: 1,
title: Text(
'选择文件夹',
style: Theme.of(context).textTheme.titleMedium,
),
actions: [
TextButton(
onPressed: () => Get.back(),
child: const Text('完成'),
),
const SizedBox(width: 6),
],
),
Expanded(
child: Material(
child: FutureBuilder(
future: _favController.queryFavFolder(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
Map data = snapshot.data as Map;
if (data['status']) {
return Obx(
() => ListView.builder(
itemCount: _favController
.favFolderData.value.list!.length +
1,
itemBuilder: (context, index) {
if (index == 0) {
return const SizedBox(height: 15);
} else {
return ListTile(
onTap: () {},
dense: true,
leading:
const Icon(Icons.folder_special_outlined),
minLeadingWidth: 0,
title: Text(_favController.favFolderData.value
.list![index - 1].title!),
subtitle: Text(
'${_favController.favFolderData.value.list![index - 1].mediaCount}个内容',
style: TextStyle(
color: Theme.of(context)
.colorScheme
.outline,
fontSize: Theme.of(context)
.textTheme
.labelSmall!
.fontSize),
),
trailing: Transform.scale(
scale: 0.9,
child: Checkbox(
value: false,
onChanged: (bool? checkValue) {},
),
),
);
}
},
),
);
} else {
return HttpError(
errMsg: data['msg'],
fn: () => setState(() {}),
);
}
} else {
// 骨架屏
return Text('请求中');
}
},
),
),
),
],
),
),
persistent: false,
backgroundColor: Theme.of(context).bottomSheetTheme.backgroundColor,
);
}
@override
Widget build(BuildContext context) {
return SliverPadding(
@ -293,7 +393,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
),
),
const SizedBox(height: 5),
_actionGrid(context),
_actionGrid(context, widget.videoIntroController),
],
)
: const Center(child: CircularProgressIndicator()),
@ -302,7 +402,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
}
// 喜欢 投币 分享
Widget _actionGrid(BuildContext context) {
Widget _actionGrid(BuildContext context, videoIntroController) {
return LayoutBuilder(builder: (context, constraints) {
return SizedBox(
height: constraints.maxWidth / 5 * 0.8,
@ -312,39 +412,50 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
crossAxisCount: 5,
childAspectRatio: 1.25,
children: <Widget>[
ActionItem(
icon: const Icon(FontAwesomeIcons.thumbsUp),
onTap: () => {},
selectStatus: false,
loadingStatus: widget.loadingStatus,
text: !widget.loadingStatus
? widget.videoDetail!.stat!.like!.toString()
: '-'),
Obx(
() => ActionItem(
icon: const Icon(FontAwesomeIcons.thumbsUp),
selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp),
onTap: () => videoIntroController.actionLikeVideo(),
selectStatus: videoIntroController.hasLike.value,
loadingStatus: widget.loadingStatus,
text: !widget.loadingStatus
? widget.videoDetail!.stat!.like!.toString()
: '-'),
),
ActionItem(
icon: const Icon(FontAwesomeIcons.thumbsDown),
selectIcon: const Icon(FontAwesomeIcons.solidThumbsDown),
onTap: () => {},
selectStatus: false,
loadingStatus: widget.loadingStatus,
text: '不喜欢'),
ActionItem(
icon: const Icon(FontAwesomeIcons.b),
onTap: () => {},
selectStatus: false,
loadingStatus: widget.loadingStatus,
text: !widget.loadingStatus
? widget.videoDetail!.stat!.coin!.toString()
: '-'),
ActionItem(
icon: const Icon(FontAwesomeIcons.star),
onTap: () => {},
selectStatus: false,
loadingStatus: widget.loadingStatus,
text: !widget.loadingStatus
? widget.videoDetail!.stat!.favorite!.toString()
: '-'),
Obx(
() => ActionItem(
icon: const Icon(FontAwesomeIcons.b),
selectIcon: const Icon(FontAwesomeIcons.b),
onTap: () => videoIntroController.actionCoinVideo(),
selectStatus: videoIntroController.hasCoin.value,
loadingStatus: widget.loadingStatus,
text: !widget.loadingStatus
? widget.videoDetail!.stat!.coin!.toString()
: '-'),
),
Obx(
() => ActionItem(
icon: const Icon(FontAwesomeIcons.star),
selectIcon: const Icon(FontAwesomeIcons.star),
// onTap: () => videoIntroController.actionFavVideo(),
onTap: () => showFavBottomSheet(),
selectStatus: videoIntroController.hasFav.value,
loadingStatus: widget.loadingStatus,
text: !widget.loadingStatus
? widget.videoDetail!.stat!.favorite!.toString()
: '-'),
),
ActionItem(
icon: const Icon(FontAwesomeIcons.shareFromSquare),
onTap: () => {},
onTap: () => videoIntroController.actionShareVideo(),
selectStatus: false,
loadingStatus: widget.loadingStatus,
text: !widget.loadingStatus
@ -359,6 +470,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
class ActionItem extends StatelessWidget {
Icon? icon;
Icon? selectIcon;
Function? onTap;
bool? loadingStatus;
String? text;
@ -367,6 +479,7 @@ class ActionItem extends StatelessWidget {
ActionItem({
Key? key,
this.icon,
this.selectIcon,
this.onTap,
this.loadingStatus,
this.text,
@ -378,16 +491,17 @@ class ActionItem extends StatelessWidget {
return Material(
child: Ink(
child: InkWell(
onTap: () {},
onTap: () => onTap!(),
borderRadius: StyleString.mdRadius,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(icon!.icon!,
size: 21,
color: selectStatus
? Theme.of(context).primaryColor
: Theme.of(context).colorScheme.outline),
const SizedBox(height: 4),
selectStatus
? Icon(selectIcon!.icon!,
size: 21, color: Theme.of(context).primaryColor)
: Icon(icon!.icon!,
size: 21, color: Theme.of(context).colorScheme.outline),
const SizedBox(height: 4),
AnimatedOpacity(
opacity: loadingStatus! ? 0 : 1,