diff --git a/lib/common/widgets/video_popup_menu.dart b/lib/common/widgets/video_popup_menu.dart index 775485c57..69253dc24 100644 --- a/lib/common/widgets/video_popup_menu.dart +++ b/lib/common/widgets/video_popup_menu.dart @@ -5,6 +5,7 @@ import 'package:get/get.dart'; import '../../http/user.dart'; import '../../http/video.dart'; +import '../../models/home/rcmd/result.dart'; import '../../pages/mine/controller.dart'; import '../../utils/storage.dart'; @@ -73,9 +74,157 @@ class VideoPopupMenu extends StatelessWidget { // 不感兴趣 PopupMenuItem( onTap: () async { - // var res = await VideoHttp.dislike(bvid: videoItem.bvid as String); - // SmartDialog.showToast(res['msg']); - SmartDialog.showToast("暂未实现"); + String? accessKey = GStrorage.localCache + .get(LocalCacheKey.accessKey, defaultValue: {})['value']; + if (accessKey == null || accessKey == "") { + SmartDialog.showToast("本操作使用app端接口,请前往【隐私设置】刷新access_key"); + return; + } + if (videoItem is RecVideoItemAppModel) { + RecVideoItemAppModel v = videoItem as RecVideoItemAppModel; + ThreePoint? tp = v.threePoint; + if (tp == null) { + SmartDialog.showToast("未能获取threePoint"); + return; + } + if (tp.dislikeReasons == null && tp.feedbacks == null) { + SmartDialog.showToast("未能获取dislikeReasons或feedbacks"); + return; + } + Widget actionButton(DislikeReason? r, FeedbackReason? f) { + return ElevatedButton( + style: ElevatedButton.styleFrom( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, vertical: 0.0), + ), + onPressed: () async { + SmartDialog.showLoading(msg: '正在提交'); + var res = await VideoHttp.feedDislike( + reasonId: r?.id, + feedbackId: f?.id, + id: v.param!, + goto: v.goto!, + ); + SmartDialog.dismiss(); + SmartDialog.showToast( + res['status'] ? (r?.toast ?? f?.toast) : res['msg']); + Get.back(); + }, + child: Text(r?.name ?? f?.name ?? '未知'), + ); + } + + await showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: const Text('请选择'), + content: SingleChildScrollView( + child: Column( + children: [ + if (tp.dislikeReasons != null) + const Padding( + padding: EdgeInsets.symmetric(vertical: 8.0), + child: Text('我不想看'), + ), + if (tp.dislikeReasons != null) + Wrap( + spacing: 5.0, + runSpacing: 2.0, + children: tp.dislikeReasons!.map((item) { + return actionButton(item, null); + }).toList(), + ), + if (tp.feedbacks != null) + const Padding( + padding: EdgeInsets.symmetric(vertical: 8.0), + child: Text('反馈'), + ), + if (tp.feedbacks != null) + Wrap( + spacing: 5.0, + runSpacing: 2.0, + children: tp.feedbacks!.map((item) { + return actionButton(null, item); + }).toList(), + ), + //分割线 + const Divider(), + ElevatedButton( + onPressed: () async { + SmartDialog.showLoading(msg: '正在提交'); + var res = await VideoHttp.feedDislikeCancel( + // reasonId: r?.id, + // feedbackId: f?.id, + id: v.param!, + goto: v.goto!, + ); + SmartDialog.dismiss(); + SmartDialog.showToast( + res['status'] ? "成功" : res['msg']); + Get.back(); + }, + child: const Text("撤销"), + ), + ], + ), + ), + ); + }, + ); + } else { + await showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: const Text('点踩该视频?'), + content: SingleChildScrollView( + child: Column( + children: [ + const SizedBox(height: 5), + const Text("web端暂不支持精细选择"), + const SizedBox(height: 5), + Wrap( + spacing: 5.0, + runSpacing: 2.0, + children: [ + ElevatedButton( + onPressed: () async { + SmartDialog.showLoading(msg: '正在提交'); + var res = await VideoHttp.dislikeVideo( + bvid: videoItem.bvid as String, + type: true); + SmartDialog.dismiss(); + SmartDialog.showToast(res['status'] + ? "点踩成功" + : res['msg']); + Get.back(); + }, + child: const Text("点踩"), + ), + ElevatedButton( + onPressed: () async { + SmartDialog.showLoading(msg: '正在提交'); + var res = await VideoHttp.dislikeVideo( + bvid: videoItem.bvid as String, + type: false); + SmartDialog.dismiss(); + SmartDialog.showToast(res['status'] + ? "取消踩" + : res['msg']); + Get.back(); + }, + child: const Text("撤销"), + ), + ], + ) + ], + ), + ), + ); + }, + ); + } }, value: 'dislike', height: menuItemHeight, diff --git a/lib/http/api.dart b/lib/http/api.dart index 8cfeb4d62..4fede3aa0 100644 --- a/lib/http/api.dart +++ b/lib/http/api.dart @@ -6,6 +6,10 @@ class Api { '${HttpString.appBaseUrl}/x/v2/feed/index'; static const String recommendListWeb = '/x/web-interface/index/top/feed/rcmd'; + // APP端不感兴趣、取消不感兴趣 + static const String feedDislike = '${HttpString.appBaseUrl}/x/feed/dislike'; + static const String feedDislikeCancel = '${HttpString.appBaseUrl}/x/feed/dislike/cancel'; + // 热门视频 static const String hotList = '/x/web-interface/popular'; diff --git a/lib/http/member.dart b/lib/http/member.dart index fe896e2e9..9de714315 100644 --- a/lib/http/member.dart +++ b/lib/http/member.dart @@ -416,7 +416,8 @@ class MemberHttp { var authCodeRes = await getTVCode(); if (authCodeRes['status']) { SmartDialog.showLoading(msg: "正在确认登录..."); - var confirmRes = await Request().post(Api.qrcodeConfirm, queryParameters: { + var confirmRes = + await Request().post(Api.qrcodeConfirm, queryParameters: { 'auth_code': authCodeRes['data'], 'local_id': '0', 'build': 1442100, @@ -427,6 +428,14 @@ class MemberHttp { print(confirmRes); SmartDialog.dismiss(); if (confirmRes.data['code'] != 0) { + if (confirmRes.data['code'] == -101 || + confirmRes.data['message'] == "账号未登录") { + return { + 'status': false, + 'data': [], + 'msg': "请在设置中退出账号并重新登录再试", + }; + } return { 'status': false, 'data': [], @@ -478,7 +487,11 @@ class MemberHttp { var userInfo = userInfoCache.get('userInfoCache'); localCache.put( LocalCacheKey.accessKey, {'mid': userInfo.mid, 'value': accessKey}); - return {'status': true, 'data': [], 'message': '操作成功,当前获取的access_key为:$accessKey'}; + return { + 'status': true, + 'data': [], + 'message': '操作成功,当前获取的access_key为:$accessKey' + }; } else { return { 'status': false, diff --git a/lib/http/video.dart b/lib/http/video.dart index 2914ab18b..d0a7a509b 100644 --- a/lib/http/video.dart +++ b/lib/http/video.dart @@ -325,7 +325,7 @@ class VideoHttp { String? accessKey = GStrorage.localCache .get(LocalCacheKey.accessKey, defaultValue: {})['value']; if (accessKey == null || accessKey == "") { - return {'status': false, 'data': [], 'msg': "本操作使用app端接口,请前往【隐私设置】刷新access_key"}; + return {'status': false, 'msg': "本操作使用app端接口,请前往【隐私设置】刷新access_key"}; } var res = await Request().post( Api.dislikeVideo, @@ -337,9 +337,74 @@ class VideoHttp { ); print(res); if (res.data is! String && res.data['code'] == 0) { - return {'status': true, 'data': res.data['data']}; + return {'status': true}; } else { - return {'status': false, 'data': [], 'msg': res.data['message']}; + return { + 'status': false, + 'msg': res.data is String ? res.data : res.data['message'] + }; + } + } + + // 推送不感兴趣反馈 + static Future feedDislike( + {required String goto, + required int id, + int? reasonId, + int? feedbackId}) async { + String? accessKey = GStrorage.localCache + .get(LocalCacheKey.accessKey, defaultValue: {})['value']; + if (accessKey == null || accessKey == "") { + return {'status': false, 'msg': "本操作使用app端接口,请前往【隐私设置】刷新access_key"}; + } + assert((reasonId != null) ^ (feedbackId != null)); + var res = await Request().get(Api.feedDislike, data: { + 'goto': goto, + 'id': id, + // 'mid': mid, + if (reasonId != null) 'reason_id': reasonId, + if (feedbackId != null) 'feedback_id': feedbackId, + 'build': 1, + 'mobi_app': 'android', + 'access_key': accessKey, + 'appkey': Constants.appKey, + }); + print(res); + if (res.data['code'] == 0) { + return {'status': true}; + } else { + return {'status': false, 'msg': res.data['message']}; + } + } + + // 推送不感兴趣取消 + static Future feedDislikeCancel( + {required String goto, + required int id, + int? reasonId, + int? feedbackId}) async { + String? accessKey = GStrorage.localCache + .get(LocalCacheKey.accessKey, defaultValue: {})['value']; + if (accessKey == null || accessKey == "") { + return {'status': false, 'msg': "本操作使用app端接口,请前往【隐私设置】刷新access_key"}; + } + // assert ((reasonId != null) ^ (feedbackId != null)); + var res = await Request().get(Api.feedDislikeCancel, data: { + 'goto': goto, + 'id': id, + // 'mid': mid, + if (reasonId != null) 'reason_id': reasonId, + if (feedbackId != null) 'feedback_id': feedbackId, + 'build': 1, + 'mobi_app': 'android', + 'access_key': accessKey, + 'appkey': Constants.appKey, + }); + print(res); + if (res.data['code'] == 0) { + return {'status': true}; + } else { + return {'status': false, 'msg': res.data['message']}; } } diff --git a/lib/models/home/rcmd/result.dart b/lib/models/home/rcmd/result.dart index 9c4d21867..79a1f7d73 100644 --- a/lib/models/home/rcmd/result.dart +++ b/lib/models/home/rcmd/result.dart @@ -22,6 +22,7 @@ class RecVideoItemAppModel { this.bangumiBadge, this.cardType, this.adInfo, + this.threePoint, }); int? id; @@ -46,6 +47,7 @@ class RecVideoItemAppModel { String? cardType; Map? adInfo; + ThreePoint? threePoint; RecVideoItemAppModel.fromJson(Map json) { id = json['player_args'] != null @@ -89,6 +91,9 @@ class RecVideoItemAppModel { cardType = json['card_type']; adInfo = json['ad_info']; + threePoint = json['three_point'] != null + ? ThreePoint.fromJson(json['three_point']) + : null; } } @@ -135,3 +140,67 @@ class RcmdReason { content = json["text"] ?? ''; } } + +class ThreePoint { + ThreePoint({ + this.dislikeReasons, + this.feedbacks, + this.watchLater, + }); + + List? dislikeReasons; + List? feedbacks; + int? watchLater; + + ThreePoint.fromJson(Map json) { + if (json['dislike_reasons'] != null) { + dislikeReasons = []; + json['dislike_reasons'].forEach((v) { + dislikeReasons!.add(DislikeReason.fromJson(v)); + }); + } + if (json['feedbacks'] != null) { + feedbacks = []; + json['feedbacks'].forEach((v) { + feedbacks!.add(FeedbackReason.fromJson(v)); + }); + } + watchLater = json['watch_later']; + } +} + +class DislikeReason { + DislikeReason({ + this.id, + this.name, + this.toast, + }); + + int? id; + String? name; + String? toast; + + DislikeReason.fromJson(Map json) { + id = json['id']; + name = json['name']; + toast = json['toast']; + } +} + +class FeedbackReason { + FeedbackReason({ + this.id, + this.name, + this.toast, + }); + + int? id; + String? name; + String? toast; + + FeedbackReason.fromJson(Map json) { + id = json['id']; + name = json['name']; + toast = json['toast']; + } +} diff --git a/lib/pages/setting/privacy_setting.dart b/lib/pages/setting/privacy_setting.dart index 41ef1c1ba..6d47a0b7a 100644 --- a/lib/pages/setting/privacy_setting.dart +++ b/lib/pages/setting/privacy_setting.dart @@ -78,7 +78,7 @@ class _PrivacySettingState extends State { if (res['status']) { SmartDialog.showToast(res['msg']); } else { - SmartDialog.showToast('刷新失败:${res['msg']}'); + SmartDialog.showToast("刷新失败:${res['msg']}"); } }, dense: false,