diff --git a/lib/http/api.dart b/lib/http/api.dart index 716c7cf9..814aef15 100644 --- a/lib/http/api.dart +++ b/lib/http/api.dart @@ -49,7 +49,7 @@ class Api { /// aid num 稿件avid 必要(可选) avid与bvid任选一个 /// bvid str 稿件bvid 必要(可选) avid与bvid任选一个 // https://api.bilibili.com/x/web-interface/archive/has/like - static const String hasLikeVideo = '/x/web-interface/archive/has/like'; + // static const String hasLikeVideo = '/x/web-interface/archive/has/like'; static const String bangumiLikeCoinFav = '/pgc/season/episode/community'; @@ -79,7 +79,7 @@ class Api { /// aid num 稿件avid 必要(可选) avid与bvid任选一个 /// bvid str 稿件bvid 必要(可选) avid与bvid任选一个 /// https://api.bilibili.com/x/web-interface/archive/coins - static const String hasCoinVideo = '/x/web-interface/archive/coins'; + // static const String hasCoinVideo = '/x/web-interface/archive/coins'; /// 收藏夹 详情 /// media_id 当前收藏夹id 搜索全部时为默认收藏夹id @@ -119,7 +119,7 @@ class Api { // 判断视频是否被收藏(双端)GET /// aid // https://api.bilibili.com/x/v2/fav/video/favoured - static const String hasFavVideo = '/x/v2/fav/video/favoured'; + // static const String hasFavVideo = '/x/v2/fav/video/favoured'; // 分享视频 (Web端) POST // https://api.bilibili.com/x/web-interface/share/add @@ -281,10 +281,6 @@ class Api { // https://api.bilibili.com/x/relation/tag?mid=17340771&tagid=-10&pn=1&ps=20 static const String tagFollowings = '/x/relation/tag'; - // 关注分类 - // https://api.bilibili.com/x/relation/tags - static const String followingsClass = '/x/relation/tags'; - // 搜索follow static const followSearch = '/x/relation/followings/search'; @@ -708,6 +704,7 @@ class Api { static const String uploadImage = '/x/upload/web/image'; + // 点赞投币收藏关注 static const String videoRelation = '/x/web-interface/archive/relation'; static const String seasonFav = '/x/v3/fav/season/'; // + fav unfav diff --git a/lib/http/video.dart b/lib/http/video.dart index 176accb8..df5f4a39 100644 --- a/lib/http/video.dart +++ b/lib/http/video.dart @@ -374,26 +374,26 @@ class VideoHttp { } // 获取点赞状态 - static Future hasLikeVideo({required String bvid}) async { - var res = - await Request().get(Api.hasLikeVideo, queryParameters: {'bvid': bvid}); - if (res.data['code'] == 0) { - return {'status': true, 'data': res.data['data']}; - } else { - return {'status': false, 'data': []}; - } - } + // static Future hasLikeVideo({required String bvid}) async { + // var res = + // await Request().get(Api.hasLikeVideo, queryParameters: {'bvid': bvid}); + // if (res.data['code'] == 0) { + // return {'status': true, 'data': res.data['data']}; + // } else { + // return {'status': false, 'data': []}; + // } + // } // 获取投币状态 - static Future hasCoinVideo({required String bvid}) async { - var res = - await Request().get(Api.hasCoinVideo, queryParameters: {'bvid': bvid}); - if (res.data['code'] == 0) { - return {'status': true, 'data': res.data['data']}; - } else { - return {'status': false, 'data': []}; - } - } + // static Future hasCoinVideo({required String bvid}) async { + // var res = + // await Request().get(Api.hasCoinVideo, queryParameters: {'bvid': bvid}); + // if (res.data['code'] == 0) { + // return {'status': true, 'data': res.data['data']}; + // } else { + // return {'status': false, 'data': []}; + // } + // } // 投币 static Future coinVideo({ @@ -420,15 +420,15 @@ class VideoHttp { } // 获取收藏状态 - static Future hasFavVideo({required int aid}) async { - var res = - await Request().get(Api.hasFavVideo, queryParameters: {'aid': aid}); - if (res.data['code'] == 0) { - return {'status': true, 'data': res.data['data']}; - } else { - return {'status': false, 'data': []}; - } - } + // static Future hasFavVideo({required int aid}) async { + // var res = + // await Request().get(Api.hasFavVideo, queryParameters: {'aid': aid}); + // if (res.data['code'] == 0) { + // return {'status': true, 'data': res.data['data']}; + // } else { + // return {'status': false, 'data': []}; + // } + // } // 一键三连 bangumi static Future triple({dynamic epId, required dynamic seasonId}) async { @@ -782,16 +782,6 @@ class VideoHttp { } } - // 查询是否关注up - static Future hasFollow({required int mid}) async { - var res = await Request().get(Api.relation, queryParameters: {'fid': mid}); - if (res.data['code'] == 0) { - return {'status': true, 'data': res.data['data']}; - } else { - return {'status': false, 'data': []}; - } - } - // 操作用户关系 static Future relationMod( {required int mid, required int act, required int reSrc}) async { diff --git a/lib/pages/follow/widgets/follow_item.dart b/lib/pages/follow/widgets/follow_item.dart index defacd83..fdeba160 100644 --- a/lib/pages/follow/widgets/follow_item.dart +++ b/lib/pages/follow/widgets/follow_item.dart @@ -82,6 +82,7 @@ class FollowItem extends StatelessWidget { mid: item.mid, isFollow: item.attribute != -1, callback: callback, + followStatus: {'special': item.special, 'tag': item.tag}, ); }, style: FilledButton.styleFrom( diff --git a/lib/pages/video/detail/introduction/controller.dart b/lib/pages/video/detail/introduction/controller.dart index 6698a888..5b1b5a25 100644 --- a/lib/pages/video/detail/introduction/controller.dart +++ b/lib/pages/video/detail/introduction/controller.dart @@ -66,7 +66,7 @@ class VideoIntroController extends GetxController RxBool hasLater = false.obs; bool isLogin = false; Rx favFolderData = FavFolderData().obs; - List? favIds; + Set? favIds; // 关注状态 默认未关注 RxMap followStatus = {}.obs; @@ -139,18 +139,19 @@ class VideoIntroController extends GetxController queryVideoTags(); var result = await VideoHttp.videoIntro(bvid: bvid); if (result['status']) { - if (videoDetail.value.ugcSeason?.id == result['data']?.ugcSeason?.id) { + VideoDetailData data = result['data']; + if (videoDetail.value.ugcSeason?.id == data.ugcSeason?.id) { // keep reversed season - result['data']?.ugcSeason = videoDetail.value.ugcSeason; - result['data']?.isSeasonReversed = videoDetail.value.isSeasonReversed; + data.ugcSeason = videoDetail.value.ugcSeason; + data.isSeasonReversed = videoDetail.value.isSeasonReversed; } - if (videoDetail.value.cid == result['data']?.cid) { + if (videoDetail.value.cid == data.cid) { // keep reversed pages - result['data']?.pages = videoDetail.value.pages; - result['data']?.isPageReversed = videoDetail.value.isPageReversed; + data.pages = videoDetail.value.pages; + data.isPageReversed = videoDetail.value.isPageReversed; } - videoDetail.value = result['data']; - videoItem['staff'] = result['data'].staff; + videoDetail.value = data; + videoItem['staff'] = data.staff; try { final videoDetailController = Get.find(tag: heroTag); @@ -158,7 +159,7 @@ class VideoIntroController extends GetxController videoDetailController.videoItem['pic'] == '' || (videoDetailController.videoUrl.isNullOrEmpty && videoDetailController.isQuerying.not)) { - videoDetailController.videoItem['pic'] = result['data'].pic; + videoDetailController.videoItem['pic'] = data.pic; } } catch (_) {} if (videoDetail.value.pages != null && @@ -178,13 +179,14 @@ class VideoIntroController extends GetxController } queryVideoIntroData.value = result; if (isLogin) { - // 获取点赞状态 - queryHasLikeVideo(); - // 获取投币状态 - queryHasCoinVideo(); - // 获取收藏状态 - queryHasFavVideo(); - // + queryAllStatus(); + // // 获取点赞状态 + // queryHasLikeVideo(); + // // 获取投币状态 + // queryHasCoinVideo(); + // // 获取收藏状态 + // queryHasFavVideo(); + // // queryFollowStatus(); } } @@ -223,38 +225,49 @@ class VideoIntroController extends GetxController await MemberHttp.memberCardInfo(mid: videoDetail.value.owner!.mid!); if (result['status']) { userStat.value = result['data']; - userStat.refresh(); } } } - // 获取点赞状态 - Future queryHasLikeVideo() async { - var result = await VideoHttp.hasLikeVideo(bvid: bvid); - // data num 被点赞标志 0:未点赞 1:已点赞 2:已点踩 - hasLike.value = result["data"] == 1; - hasDislike.value = result["data"] == 2; - } - - // 获取投币状态 - Future queryHasCoinVideo() async { - var result = await VideoHttp.hasCoinVideo(bvid: bvid); + Future queryAllStatus() async { + var result = await VideoHttp.videoRelation(bvid: bvid); if (result['status']) { - hasCoin.value = result["data"]['multiply'] != 0; + var data = result['data']; + hasLike.value = data['like']; + hasDislike.value = data['dislike']; + hasCoin.value = data['coin'] != 0; + hasFav.value = data['favorite']; + // followStatus['attritube'] = data['attention'] ? 2 : 0; } } - // 获取收藏状态 - Future queryHasFavVideo() async { - /// fix 延迟查询 - await Future.delayed(const Duration(milliseconds: 200)); - var result = await VideoHttp.hasFavVideo(aid: IdUtils.bv2av(bvid)); - if (result['status']) { - hasFav.value = result["data"]['favoured']; - } else { - hasFav.value = false; - } - } + // // 获取点赞状态 + // Future queryHasLikeVideo() async { + // var result = await VideoHttp.hasLikeVideo(bvid: bvid); + // // data num 被点赞标志 0:未点赞 1:已点赞 2:已点踩 + // hasLike.value = result["data"] == 1; + // hasDislike.value = result["data"] == 2; + // } + + // // 获取投币状态 + // Future queryHasCoinVideo() async { + // var result = await VideoHttp.hasCoinVideo(bvid: bvid); + // if (result['status']) { + // hasCoin.value = result["data"]['multiply'] != 0; + // } + // } + + // // 获取收藏状态 + // Future queryHasFavVideo() async { + // /// fix 延迟查询 + // await Future.delayed(const Duration(milliseconds: 200)); + // var result = await VideoHttp.hasFavVideo(aid: IdUtils.bv2av(bvid)); + // if (result['status']) { + // hasFav.value = result["data"]['favoured']; + // } else { + // hasFav.value = false; + // } + // } // 一键三连 Future actionOneThree() async { @@ -302,7 +315,6 @@ class VideoIntroController extends GetxController hasLike.value = false; videoDetail.value.stat!.like = videoDetail.value.stat!.like! - 1; } - hasLike.refresh(); } else { SmartDialog.showToast(result['msg']); } @@ -433,16 +445,17 @@ class VideoIntroController extends GetxController queryVideoInFolder().then((res) async { if (res['status']) { int defaultFolderId = favFolderData.value.list!.first.id!; - int favStatus = favFolderData.value.list!.first.favState!; + bool notInDefFolder = favFolderData.value.list!.first.favState! == 0; var result = await VideoHttp.favVideo( aid: IdUtils.bv2av(bvid), - addIds: favStatus == 0 ? '$defaultFolderId' : '', - delIds: favStatus == 1 ? '$defaultFolderId' : '', + addIds: notInDefFolder ? '$defaultFolderId' : '', + delIds: !notInDefFolder ? '$defaultFolderId' : '', ); SmartDialog.dismiss(); if (result['status']) { + hasFav.value = !hasFav.value || (hasFav.value && notInDefFolder); // 重新获取收藏状态 - await queryHasFavVideo(); + // await queryHasFavVideo(); SmartDialog.showToast('✅ 快速收藏/取消收藏成功'); } else { SmartDialog.showToast(result['msg']); @@ -481,8 +494,10 @@ class VideoIntroController extends GetxController SmartDialog.dismiss(); if (result['status']) { Get.back(); + hasFav.value = + addMediaIdsNew.isNotEmpty || favIds?.length != delMediaIdsNew.length; // 重新获取收藏状态 - await queryHasFavVideo(); + // await queryHasFavVideo(); SmartDialog.showToast('操作成功'); } else { SmartDialog.showToast(result['msg']); @@ -569,7 +584,7 @@ class VideoIntroController extends GetxController favIds = favFolderData.value.list ?.where((item) => item.favState == 1) .map((item) => item.id) - .toList(); + .toSet(); } return result; } @@ -591,11 +606,10 @@ class VideoIntroController extends GetxController if (videoDetail.value.owner == null) { return; } - var result = await VideoHttp.hasFollow(mid: videoDetail.value.owner!.mid!); + var result = await UserHttp.hasFollow(videoDetail.value.owner!.mid!); if (result['status']) { followStatus.value = result['data']; } - return result; } // 关注/取关up @@ -608,23 +622,21 @@ class VideoIntroController extends GetxController if (attr == 128) { dynamic res = await VideoHttp.relationMod( mid: videoDetail.value.owner?.mid ?? -1, - act: attr != 128 ? 5 : 6, + act: 6, reSrc: 11, ); if (res['status']) { followStatus['attribute'] = 0; - followStatus.refresh(); } return; - } - if (context.mounted) { + } else { Utils.actionRelationMod( context: context, mid: videoDetail.value.owner?.mid, - isFollow: (followStatus['attribute'] ?? 0) != 0, + isFollow: attr != 0, + followStatus: followStatus, callback: (attribute) { followStatus['attribute'] = attribute; - followStatus.refresh(); }, ); } diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index 6ee70199..a97cbbce 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -888,11 +888,13 @@ class _VideoInfoState extends State with TickerProviderStateMixin { : t.colorScheme.secondaryContainer, ), child: Text( - attr == 128 - ? '已拉黑' - : attr != 0 - ? '已关注' - : '关注', + switch (attr) { + 1 => '悄悄关注', + 2 => '已关注', + 6 => '已互关', + 128 => '已拉黑', + _ => '关注' + }, style: TextStyle(fontSize: t.textTheme.labelMedium!.fontSize), ), ); diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 1422b9e5..9b83dc69 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -14,6 +14,7 @@ import 'package:PiliPlus/http/init.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/member.dart'; import 'package:PiliPlus/http/search.dart'; +import 'package:PiliPlus/http/user.dart'; import 'package:PiliPlus/http/video.dart'; import 'package:PiliPlus/main.dart'; import 'package:PiliPlus/models/bangumi/info.dart'; @@ -887,6 +888,7 @@ class Utils { required dynamic mid, required bool isFollow, required ValueChanged? callback, + Map? followStatus, }) async { if (mid == null) { return; @@ -900,16 +902,23 @@ class Utils { ); SmartDialog.showToast(res['status'] ? "关注成功" : res['msg']); if (res['status']) { - callback?.call(1); + callback?.call(2); } } else { - dynamic result = await VideoHttp.hasFollow(mid: mid); - if (result['status'] && context.mounted) { - Map followStatus = result['data']; + if (followStatus == null) { + Map result = await UserHttp.hasFollow(mid); + if (result['status']) { + followStatus = result['data']; + } else { + SmartDialog.showToast(result['msg']); + return; + } + } + if (context.mounted) { showDialog( context: context, builder: (context) { - bool isSpecialFollowed = followStatus['special'] == 1; + bool isSpecialFollowed = followStatus!['special'] == 1; String text = isSpecialFollowed ? '移除特别关注' : '加入特别关注'; return AlertDialog( clipBehavior: Clip.hardEdge, @@ -927,25 +936,21 @@ class Utils { ); if (res['status']) { SmartDialog.showToast('$text成功'); - if (isSpecialFollowed) { - callback?.call(1); - } else { - callback?.call(2); - } + callback?.call(2); } else { SmartDialog.showToast(res['msg']); } }, title: Text( text, - style: TextStyle(fontSize: 14), + style: const TextStyle(fontSize: 14), ), ), ListTile( dense: true, onTap: () async { Get.back(); - dynamic result = await showModalBottomSheet( + var result = await showModalBottomSheet( context: context, useSafeArea: true, isScrollControlled: true, @@ -963,17 +968,15 @@ class Utils { ScrollController scrollController) { return GroupPanel( mid: mid, - tags: followStatus['tag'], + tags: followStatus!['tag'], scrollController: scrollController, ); }, ); }, ); - if (result == true) { + if (result != null) { callback?.call(2); - } else if (result == false) { - callback?.call(1); } }, title: const Text(