mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
opt: follow dialog
fix: add user tags
This commit is contained in:
@@ -390,6 +390,10 @@ class Api {
|
||||
// 0 添加至默认分组 否则使用,分割tagid
|
||||
static const String addUsers = '/x/relation/tags/addUsers';
|
||||
|
||||
static const String addSpecial = '/x/relation/tag/special/add';
|
||||
|
||||
static const String delSpecial = '/x/relation/tag/special/del';
|
||||
|
||||
// 获取指定分组下的up
|
||||
static const String followUpGroup = '/x/relation/tag';
|
||||
|
||||
|
||||
@@ -210,15 +210,44 @@ class MemberHttp {
|
||||
}
|
||||
}
|
||||
|
||||
static Future specialAction({
|
||||
int? fid,
|
||||
bool isAdd = true,
|
||||
}) async {
|
||||
var res = await Request().post(
|
||||
isAdd ? Api.addSpecial : Api.delSpecial,
|
||||
data: {
|
||||
'fid': fid,
|
||||
'csrf': await Request.getCsrf(),
|
||||
},
|
||||
options: Options(
|
||||
contentType: Headers.formUrlEncodedContentType,
|
||||
),
|
||||
);
|
||||
if (res.data['code'] == 0) {
|
||||
return {'status': true};
|
||||
} else {
|
||||
return {
|
||||
'status': false,
|
||||
'msg': res.data['message'],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 设置分组
|
||||
static Future addUsers(int? fids, String? tagids) async {
|
||||
var res = await Request().post(Api.addUsers, queryParameters: {
|
||||
var res = await Request().post(
|
||||
Api.addUsers,
|
||||
data: {
|
||||
'fids': fids,
|
||||
'tagids': tagids ?? '0',
|
||||
'csrf': await Request.getCsrf(),
|
||||
}, data: {
|
||||
'cross_domain': true
|
||||
});
|
||||
// 'cross_domain': true
|
||||
},
|
||||
options: Options(
|
||||
contentType: Headers.formUrlEncodedContentType,
|
||||
),
|
||||
);
|
||||
if (res.data['code'] == 0) {
|
||||
return {'status': true, 'data': [], 'msg': '操作成功'};
|
||||
} else {
|
||||
|
||||
@@ -36,8 +36,10 @@ class MemberController extends GetxController {
|
||||
mid = mid ?? int.parse(Get.parameters['mid']!);
|
||||
userInfo = userInfoCache.get('userInfoCache');
|
||||
ownerMid = userInfo != null ? userInfo.mid : -1;
|
||||
try {
|
||||
face.value = Get.arguments['face'] ?? '';
|
||||
heroTag = Get.arguments['heroTag'] ?? '';
|
||||
} catch (_) {}
|
||||
relationSearch();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:async';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:PiliPalaX/http/loading_state.dart';
|
||||
import 'package:PiliPalaX/http/member.dart';
|
||||
import 'package:PiliPalaX/utils/utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@@ -30,7 +31,8 @@ import '../../../../models/model_hot_video_item.dart';
|
||||
import '../related/index.dart';
|
||||
import 'widgets/group_panel.dart';
|
||||
|
||||
class VideoIntroController extends GetxController {
|
||||
class VideoIntroController extends GetxController
|
||||
with GetTickerProviderStateMixin {
|
||||
// 视频bvid
|
||||
late String bvid;
|
||||
|
||||
@@ -507,15 +509,140 @@ class VideoIntroController extends GetxController {
|
||||
SmartDialog.showToast('账号未登录');
|
||||
return;
|
||||
}
|
||||
if (videoDetail.value.owner?.mid == null) {
|
||||
return;
|
||||
}
|
||||
feedBack();
|
||||
int mid = videoDetail.value.owner!.mid!;
|
||||
MemberController _ = Get.put<MemberController>(MemberController(mid: mid),
|
||||
tag: mid.toString());
|
||||
await _.getInfo();
|
||||
if (context.mounted) await _.actionRelationMod(context);
|
||||
followStatus['attribute'] = _.attribute.value;
|
||||
if ((followStatus['attribute'] ?? 0) == 0) {
|
||||
var res = await VideoHttp.relationMod(
|
||||
mid: mid,
|
||||
act: 1,
|
||||
reSrc: 11,
|
||||
);
|
||||
SmartDialog.showToast(res['status'] ? "关注成功" : res['msg']);
|
||||
if (res['status']) {
|
||||
followStatus['attribute'] = 2;
|
||||
followStatus.refresh();
|
||||
Get.delete<MemberController>(tag: mid.toString());
|
||||
}
|
||||
} else {
|
||||
/// TODO
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (_) {
|
||||
bool isSpecialFollowed = followStatus['special'] == 1;
|
||||
String text = isSpecialFollowed ? '移除特别关注' : '加入特别关注';
|
||||
return AlertDialog(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 12),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () async {
|
||||
Get.back();
|
||||
final res = await MemberHttp.specialAction(
|
||||
fid: mid,
|
||||
isAdd: !isSpecialFollowed,
|
||||
);
|
||||
if (res['status']) {
|
||||
followStatus['special'] = isSpecialFollowed ? 0 : 1;
|
||||
List tags = followStatus['tag'] ?? [];
|
||||
if (isSpecialFollowed) {
|
||||
tags.remove(-10);
|
||||
} else {
|
||||
tags.add(-10);
|
||||
}
|
||||
followStatus['tag'] = tags;
|
||||
followStatus.refresh();
|
||||
SmartDialog.showToast('$text成功');
|
||||
} else {
|
||||
SmartDialog.showToast(res['msg']);
|
||||
}
|
||||
},
|
||||
title: Text(
|
||||
text,
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () async {
|
||||
Get.back();
|
||||
dynamic result = await showModalBottomSheet(
|
||||
context: context,
|
||||
useSafeArea: true,
|
||||
isScrollControlled: true,
|
||||
transitionAnimationController: AnimationController(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
vsync: this,
|
||||
),
|
||||
sheetAnimationStyle: AnimationStyle(curve: Curves.ease),
|
||||
builder: (BuildContext context) {
|
||||
return DraggableScrollableSheet(
|
||||
minChildSize: 0,
|
||||
maxChildSize: 1,
|
||||
initialChildSize: 0.6,
|
||||
snap: true,
|
||||
expand: false,
|
||||
snapSizes: const [0.6],
|
||||
builder: (BuildContext context,
|
||||
ScrollController scrollController) {
|
||||
return GroupPanel(
|
||||
mid: mid,
|
||||
tags: followStatus['tag'],
|
||||
scrollController: scrollController,
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
if (result == true) {
|
||||
queryFollowStatus();
|
||||
}
|
||||
},
|
||||
title: const Text(
|
||||
'设置分组',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () async {
|
||||
Get.back();
|
||||
var res = await VideoHttp.relationMod(
|
||||
mid: mid,
|
||||
act: 2,
|
||||
reSrc: 11,
|
||||
);
|
||||
SmartDialog.showToast(
|
||||
res['status'] ? "取消关注成功" : res['msg']);
|
||||
if (res['status']) {
|
||||
followStatus['attribute'] = 0;
|
||||
followStatus.refresh();
|
||||
}
|
||||
},
|
||||
title: const Text(
|
||||
'取消关注',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// MemberController _ = Get.put<MemberController>(MemberController(mid: mid),
|
||||
// tag: mid.toString());
|
||||
// await _.getInfo();
|
||||
// if (context.mounted) await _.actionRelationMod(context);
|
||||
// followStatus['attribute'] = _.attribute.value;
|
||||
// followStatus.refresh();
|
||||
// Get.delete<MemberController>(tag: mid.toString());
|
||||
}
|
||||
|
||||
// 修改分P或番剧分集
|
||||
|
||||
@@ -10,7 +10,14 @@ import '../../../../../utils/utils.dart';
|
||||
|
||||
class GroupPanel extends StatefulWidget {
|
||||
final int? mid;
|
||||
const GroupPanel({super.key, this.mid});
|
||||
final List? tags;
|
||||
final ScrollController? scrollController;
|
||||
const GroupPanel({
|
||||
super.key,
|
||||
this.mid,
|
||||
this.tags,
|
||||
this.scrollController,
|
||||
});
|
||||
|
||||
@override
|
||||
State<GroupPanel> createState() => _GroupPanelState();
|
||||
@@ -19,12 +26,25 @@ class GroupPanel extends StatefulWidget {
|
||||
class _GroupPanelState extends State<GroupPanel> {
|
||||
late Future _futureBuilderFuture;
|
||||
late List<MemberTagItemModel> tagsList;
|
||||
bool showDefault = true;
|
||||
bool showDefaultBtn = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_futureBuilderFuture = MemberHttp.followUpTags();
|
||||
() async {
|
||||
dynamic result = await _futureBuilderFuture;
|
||||
if (result['status']) {
|
||||
tagsList = result['data'];
|
||||
tagsList.removeWhere((item) => item.tagid == 0);
|
||||
tagsList = tagsList.map((item) {
|
||||
return item..checked = widget.tags?.contains(item.tagid) == true;
|
||||
}).toList();
|
||||
setState(() {
|
||||
showDefaultBtn = !tagsList.any((e) => e.checked == true);
|
||||
});
|
||||
}
|
||||
}();
|
||||
}
|
||||
|
||||
void onSave() async {
|
||||
@@ -46,26 +66,40 @@ class _GroupPanelState extends State<GroupPanel> {
|
||||
final res = await MemberHttp.addUsers(widget.mid, tagids);
|
||||
SmartDialog.showToast(res['msg']);
|
||||
if (res['status']) {
|
||||
Get.back();
|
||||
Get.back(result: true);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: Utils.getSheetHeight(context),
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
return NotificationListener<DraggableScrollableNotification>(
|
||||
onNotification: (notification) {
|
||||
if (notification.extent <= 1e-5) {
|
||||
Get.back();
|
||||
}
|
||||
return false;
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
AppBar(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(
|
||||
top: Radius.circular(18),
|
||||
),
|
||||
),
|
||||
centerTitle: false,
|
||||
elevation: 0,
|
||||
leading: IconButton(
|
||||
tooltip: '关闭',
|
||||
onPressed: () => Get.back(),
|
||||
onPressed: Get.back,
|
||||
icon: const Icon(Icons.close_outlined)),
|
||||
title:
|
||||
Text('设置关注分组', style: Theme.of(context).textTheme.titleMedium),
|
||||
title: Text('设置关注分组',
|
||||
style: Theme.of(context).textTheme.titleMedium),
|
||||
),
|
||||
Expanded(
|
||||
child: Material(
|
||||
@@ -75,33 +109,33 @@ class _GroupPanelState extends State<GroupPanel> {
|
||||
if (snapshot.connectionState == ConnectionState.done) {
|
||||
Map data = snapshot.data as Map;
|
||||
if (data['status']) {
|
||||
tagsList = data['data'];
|
||||
return ListView.builder(
|
||||
itemCount: data['data'].length,
|
||||
controller: widget.scrollController,
|
||||
itemCount: tagsList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
data['data'][index].checked =
|
||||
!data['data'][index].checked;
|
||||
showDefault =
|
||||
!data['data'].any((e) => e.checked == true);
|
||||
tagsList[index].checked =
|
||||
!tagsList[index].checked!;
|
||||
showDefaultBtn =
|
||||
!tagsList.any((e) => e.checked == true);
|
||||
setState(() {});
|
||||
},
|
||||
dense: true,
|
||||
leading: const Icon(Icons.group_outlined),
|
||||
minLeadingWidth: 0,
|
||||
title: Text(data['data'][index].name),
|
||||
subtitle: data['data'][index].tip != ''
|
||||
? Text(data['data'][index].tip)
|
||||
title: Text(tagsList[index].name ?? ''),
|
||||
subtitle: tagsList[index].tip != ''
|
||||
? Text(tagsList[index].tip ?? '')
|
||||
: null,
|
||||
trailing: Transform.scale(
|
||||
scale: 0.9,
|
||||
child: Checkbox(
|
||||
value: data['data'][index].checked,
|
||||
value: tagsList[index].checked,
|
||||
onChanged: (bool? checkValue) {
|
||||
data['data'][index].checked = checkValue;
|
||||
showDefault = !data['data']
|
||||
.any((e) => e.checked == true);
|
||||
tagsList[index].checked = checkValue;
|
||||
showDefaultBtn =
|
||||
!tagsList.any((e) => e.checked == true);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
@@ -110,14 +144,21 @@ class _GroupPanelState extends State<GroupPanel> {
|
||||
},
|
||||
);
|
||||
} else {
|
||||
return HttpError(
|
||||
return CustomScrollView(
|
||||
controller: widget.scrollController,
|
||||
slivers: [
|
||||
HttpError(
|
||||
errMsg: data['msg'],
|
||||
fn: () => setState(() {}),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// 骨架屏
|
||||
return const Text('请求中');
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
@@ -145,13 +186,14 @@ class _GroupPanelState extends State<GroupPanel> {
|
||||
backgroundColor:
|
||||
Theme.of(context).colorScheme.primary, // 设置按钮背景色
|
||||
),
|
||||
child: Text(showDefault ? '保存至默认分组' : '保存'),
|
||||
child: Text(showDefaultBtn ? '保存至默认分组' : '保存'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user