import 'dart:async' show Timer; import 'package:PiliPlus/http/fav.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/user.dart'; import 'package:PiliPlus/http/video.dart'; import 'package:PiliPlus/models/common/video/source_type.dart'; import 'package:PiliPlus/models_new/fav/fav_folder/data.dart'; import 'package:PiliPlus/models_new/video/video_detail/data.dart'; import 'package:PiliPlus/models_new/video/video_detail/stat_detail.dart'; import 'package:PiliPlus/models_new/video/video_tag/data.dart'; import 'package:PiliPlus/services/account_service.dart'; import 'package:PiliPlus/utils/global_data.dart'; import 'package:PiliPlus/utils/id_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_key.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; abstract class CommonIntroController extends GetxController { late final String heroTag; late String bvid; // 是否点赞 final RxBool hasLike = false.obs; // 投币数量 final RxNum coinNum = RxNum(0); // 是否投币 bool get hasCoin => coinNum.value != 0; // 是否收藏 final RxBool hasFav = false.obs; // 是否稍后再看 final RxBool hasLater = false.obs; final Rx?> videoTags = Rx?>(null); Set? favIds; final Rx favFolderData = FavFolderData().obs; AccountService accountService = Get.find(); (Object, int) getFavRidType(); StatDetail? getStat(); final Rx videoDetail = VideoDetailData().obs; void queryVideoIntro(); bool prevPlay(); bool nextPlay(); void actionLikeVideo(); void actionCoinVideo(); void actionTriple(); void actionShareVideo(BuildContext context); // 同时观看 final bool isShowOnlineTotal = Pref.enableOnlineTotal; late final RxString total = '1'.obs; Timer? timer; late final RxInt cid; @override void onInit() { super.onInit(); final args = Get.arguments; heroTag = args['heroTag']; bvid = args['bvid']; cid = RxInt(args['cid']); hasLater.value = args['sourceType'] == SourceType.watchLater; queryVideoIntro(); startTimer(); } void startTimer() { if (isShowOnlineTotal) { queryOnlineTotal(); timer ??= Timer.periodic(const Duration(seconds: 10), (Timer timer) { queryOnlineTotal(); }); } } void canelTimer() { timer?.cancel(); timer = null; } // 查看同时在看人数 Future queryOnlineTotal() async { if (!isShowOnlineTotal) { return; } var result = await VideoHttp.onlineTotal( aid: IdUtils.bv2av(bvid), bvid: bvid, cid: cid.value, ); if (result['status']) { total.value = result['data']; } } @override void onClose() { canelTimer(); super.onClose(); } Future> queryVideoInFolder() async { favIds = null; final (rid, type) = getFavRidType(); final result = await FavHttp.videoInFolder( mid: accountService.mid, rid: rid, type: type, ); if (result.isSuccess) { favFolderData.value = result.data; favIds = result.data.list ?.where((item) => item.favState == 1) .map((item) => item.id) .toSet(); } return result; } Future actionFavVideo({bool isQuick = false}) async { final (rid, type) = getFavRidType(); // 收藏至默认文件夹 if (isQuick) { SmartDialog.showLoading(msg: '请求中'); queryVideoInFolder().then((res) async { if (res.isSuccess) { final hasFav = this.hasFav.value; var result = hasFav ? await FavHttp.unfavAll(rid: rid, type: type) : await FavHttp.favVideo( resources: '$rid:$type', addIds: favFolderId.toString(), ); SmartDialog.dismiss(); if (result['status']) { getStat()!.favorite += hasFav ? -1 : 1; this.hasFav.value = !hasFav; SmartDialog.showToast('✅ 快速收藏/取消收藏成功'); } else { SmartDialog.showToast(result['msg']); } } else { SmartDialog.dismiss(); } }); return; } List addMediaIdsNew = []; List delMediaIdsNew = []; try { for (var i in favFolderData.value.list!) { bool isFaved = favIds?.contains(i.id) == true; if (i.favState == 1) { if (!isFaved) { addMediaIdsNew.add(i.id); } } else { if (isFaved) { delMediaIdsNew.add(i.id); } } } } catch (e) { if (kDebugMode) debugPrint(e.toString()); } SmartDialog.showLoading(msg: '请求中'); var result = await FavHttp.favVideo( resources: '$rid:$type', addIds: addMediaIdsNew.join(','), delIds: delMediaIdsNew.join(','), ); SmartDialog.dismiss(); if (result['status']) { Get.back(); final newVal = addMediaIdsNew.isNotEmpty || favIds?.length != delMediaIdsNew.length; if (hasFav.value != newVal) { getStat()!.favorite += newVal ? 1 : -1; hasFav.value = newVal; } SmartDialog.showToast('操作成功'); } else { SmartDialog.showToast(result['msg']); } } Future coinVideo(int coin, [bool selectLike = false]) async { final stat = getStat(); if (stat == null) { return; } var res = await VideoHttp.coinVideo( bvid: bvid, multiply: coin, selectLike: selectLike ? 1 : 0, ); if (res['status']) { SmartDialog.showToast('投币成功'); coinNum.value += coin; GlobalData().afterCoin(coin); stat.coin += coin; if (selectLike && !hasLike.value) { stat.like++; hasLike.value = true; } } else { SmartDialog.showToast(res['msg']); } } late final enableQuickFav = Pref.enableQuickFav; int? quickFavId; int get favFolderId { if (this.quickFavId != null) { return this.quickFavId!; } final quickFavId = Pref.quickFavId; final list = favFolderData.value.list!; if (quickFavId != null) { final folderInfo = list.firstWhereOrNull((e) => e.id == quickFavId); if (folderInfo != null) { return this.quickFavId = quickFavId; } else { GStorage.setting.delete(SettingBoxKey.quickFavId); } } return this.quickFavId = list.first.id; } // 收藏 void showFavBottomSheet(BuildContext context, {bool isLongPress = false}) { if (!accountService.isLogin.value) { SmartDialog.showToast('账号未登录'); return; } // 快速收藏 & // 点按 收藏至默认文件夹 // 长按选择文件夹 if (enableQuickFav) { if (!isLongPress) { actionFavVideo(isQuick: true); } else { PageUtils.showFavBottomSheet(context: context, ctr: this); } } else if (!isLongPress) { PageUtils.showFavBottomSheet(context: context, ctr: this); } } Future queryVideoTags() async { var result = await UserHttp.videoTags(bvid: bvid); if (result['status']) { videoTags.value = result['data']; } else { videoTags.value = null; } } Future viewLater() async { var res = await (hasLater.value ? UserHttp.toViewDel(aids: IdUtils.bv2av(bvid).toString()) : await UserHttp.toViewLater(bvid: bvid)); if (res['status']) hasLater.value = !hasLater.value; SmartDialog.showToast(res['msg']); } }