opt: follow dialog

fix: add user tags
This commit is contained in:
bggRGjQaUbCoE
2024-10-08 10:35:55 +08:00
parent 5d0e4ed441
commit e6b71d375f
5 changed files with 313 additions and 109 deletions

View File

@@ -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';

View File

@@ -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 {

View File

@@ -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();
}

View File

@@ -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或番剧分集

View File

@@ -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 ? '保存至默认分组' : '保存'),
),
],
),
),
],
),
),
);
}
}