305 lines
13 KiB
Dart
305 lines
13 KiB
Dart
/// 关注列表
|
||
library;
|
||
|
||
import 'package:easy_refresh/easy_refresh.dart';
|
||
import 'package:flutter/material.dart';
|
||
import 'package:get/get.dart';
|
||
import 'package:loopin/IM/controller/chat_controller.dart';
|
||
import 'package:loopin/IM/im_service.dart';
|
||
import 'package:loopin/behavior/custom_scroll_behavior.dart';
|
||
import 'package:loopin/components/network_or_asset_image.dart';
|
||
import 'package:loopin/styles/index.dart';
|
||
import 'package:loopin/utils/index.dart';
|
||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
|
||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_follow_type_check_result.dart';
|
||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_full_info.dart';
|
||
|
||
class UserWithFollow {
|
||
final V2TimUserFullInfo userInfo;
|
||
int followType;
|
||
|
||
UserWithFollow({
|
||
required this.userInfo,
|
||
this.followType = 0,
|
||
});
|
||
}
|
||
|
||
class Newfoucs extends StatefulWidget {
|
||
const Newfoucs({super.key});
|
||
|
||
@override
|
||
State<Newfoucs> createState() => NewfoucsState();
|
||
}
|
||
|
||
class NewfoucsState extends State<Newfoucs> with SingleTickerProviderStateMixin {
|
||
bool isLoading = false; // 是否在加载中
|
||
bool hasMore = true; // 是否还有更多数据
|
||
String page = '';
|
||
List<UserWithFollow> dataList = <UserWithFollow>[];
|
||
|
||
///-------------------
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
getData();
|
||
}
|
||
|
||
// 分页获取陌关注列表数据
|
||
Future<void> getData() async {
|
||
/// 0:不是好友也没有关注
|
||
/// 1:你关注了对方(单向)
|
||
/// 2:对方关注了你(单向)
|
||
/// 3:互相关注(双向好友)
|
||
final res = await ImService.instance.getMyFollowingList(
|
||
nextCursor: page,
|
||
);
|
||
if (res.success && res.data != null) {
|
||
logger.i('获取成功:${res.data!.nextCursor}');
|
||
final userInfoList = res.data!.userFullInfoList ?? [];
|
||
// 构建数据
|
||
List<UserWithFollow> wrappedList = userInfoList.map((u) {
|
||
return UserWithFollow(userInfo: u);
|
||
}).toList();
|
||
// 获取id
|
||
final userIDList = userInfoList.map((item) => item.userID).whereType<String>().toList();
|
||
if (userIDList.isNotEmpty) {
|
||
final shiRes = await ImService.instance.checkFollowType(userIDList: userIDList);
|
||
if (shiRes.success && shiRes.data != null) {
|
||
final shipResData = shiRes.data!;
|
||
for (final uwf in wrappedList) {
|
||
final userID = uwf.userInfo.userID;
|
||
if (userID != null) {
|
||
// 查找对应关系
|
||
final match = shipResData.firstWhere(
|
||
(e) => e.userID == userID,
|
||
orElse: () => V2TimFollowTypeCheckResult(userID: ''),
|
||
);
|
||
if (match.userID?.isNotEmpty ?? false) {
|
||
uwf.followType = match.followType ?? 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
final isFinished = res.data!.nextCursor == null || res.data!.nextCursor!.isEmpty;
|
||
if (isFinished) {
|
||
setState(() {
|
||
hasMore = false;
|
||
});
|
||
// 加载没数据了
|
||
page = '';
|
||
} else {
|
||
page = res.data!.nextCursor ?? '';
|
||
}
|
||
logger.i('获取数据成功:$userInfoList');
|
||
setState(() {
|
||
dataList.addAll(wrappedList);
|
||
});
|
||
} else {
|
||
logger.e('获取数据失败:${res.desc}');
|
||
}
|
||
}
|
||
|
||
// 下拉刷新
|
||
Future<void> handleRefresh() async {
|
||
dataList.clear();
|
||
page = '';
|
||
getData();
|
||
setState(() {});
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Scaffold(
|
||
backgroundColor: Colors.grey[50],
|
||
appBar: AppBar(
|
||
centerTitle: true,
|
||
forceMaterialTransparency: true,
|
||
bottom: PreferredSize(
|
||
preferredSize: const Size.fromHeight(1.0),
|
||
child: Container(
|
||
color: Colors.grey[300],
|
||
height: 1.0,
|
||
),
|
||
),
|
||
title: const Text(
|
||
'关注',
|
||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||
),
|
||
actions: [],
|
||
),
|
||
body: ScrollConfiguration(
|
||
behavior: CustomScrollBehavior().copyWith(scrollbars: false),
|
||
child: Column(
|
||
children: [
|
||
Expanded(
|
||
child: EasyRefresh.builder(
|
||
callLoadOverOffset: 20, //触底距离
|
||
callRefreshOverOffset: 20, // 下拉距离
|
||
header: ClassicHeader(
|
||
dragText: '下拉刷新',
|
||
armedText: '释放刷新',
|
||
readyText: '加载中...',
|
||
processingText: '加载中...',
|
||
processedText: '加载完成',
|
||
failedText: '加载失败,请重试',
|
||
messageText: '最后更新于 %T',
|
||
),
|
||
footer: ClassicFooter(
|
||
dragText: '加载更多',
|
||
armedText: '释放加载',
|
||
readyText: '加载中...',
|
||
processingText: '加载中...',
|
||
processedText: hasMore ? '加载完成' : '没有更多了~',
|
||
failedText: '加载失败,请重试',
|
||
messageText: '最后更新于 %T',
|
||
),
|
||
onRefresh: () async {
|
||
await handleRefresh();
|
||
},
|
||
onLoad: () async {
|
||
if (hasMore) {
|
||
await getData();
|
||
}
|
||
},
|
||
childBuilder: (context, physics) {
|
||
return ListView.builder(
|
||
physics: physics,
|
||
itemCount: dataList.length,
|
||
itemBuilder: (context, index) {
|
||
final item = dataList[index];
|
||
return Ink(
|
||
key: ValueKey(item.userInfo.userID),
|
||
child: Container(
|
||
padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10.0),
|
||
child: Row(
|
||
crossAxisAlignment: CrossAxisAlignment.center,
|
||
children: <Widget>[
|
||
// 左侧部分(头像 + 昵称 + 描述)
|
||
Expanded(
|
||
child: InkWell(
|
||
onTap: () {
|
||
Get.toNamed(
|
||
'/vloger',
|
||
arguments: item.userInfo.userID,
|
||
);
|
||
},
|
||
child: Row(
|
||
children: [
|
||
ClipOval(
|
||
child: NetworkOrAssetImage(
|
||
imageUrl: item.userInfo.faceUrl,
|
||
width: 50,
|
||
height: 50,
|
||
),
|
||
),
|
||
const SizedBox(width: 10),
|
||
Expanded(
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: <Widget>[
|
||
Text(
|
||
item.userInfo.nickName?.isNotEmpty == true ? item.userInfo.nickName! : '未知昵称',
|
||
style: const TextStyle(
|
||
fontSize: 16,
|
||
fontWeight: FontWeight.normal,
|
||
),
|
||
),
|
||
if (item.userInfo.selfSignature?.isNotEmpty ?? false) ...[
|
||
const SizedBox(height: 2.0),
|
||
Text(
|
||
item.userInfo.selfSignature!,
|
||
style: const TextStyle(
|
||
color: Colors.grey,
|
||
fontSize: 13.0,
|
||
),
|
||
maxLines: 2,
|
||
overflow: TextOverflow.ellipsis,
|
||
),
|
||
],
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
|
||
SizedBox(width: 10),
|
||
|
||
// 右侧按钮
|
||
TextButton(
|
||
style: TextButton.styleFrom(
|
||
backgroundColor: item.followType == 3 ? Colors.grey : FStyle.primaryColor,
|
||
minimumSize: const Size(70, 32),
|
||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||
shape: RoundedRectangleBorder(
|
||
borderRadius: BorderRadius.circular(4),
|
||
),
|
||
),
|
||
onPressed: () async {
|
||
final ctl = Get.find<ChatController>();
|
||
final checkRes = await ImService.instance.checkFollowType(userIDList: [item.userInfo.userID!]);
|
||
int realFollowType = 0;
|
||
if (checkRes.success && checkRes.data != null) {
|
||
realFollowType = checkRes.data!.first.followType ?? 0;
|
||
if ([1, 3].contains(realFollowType)) {
|
||
// 取关
|
||
final unRes = await ImService.instance.unfollowUser(userIDList: [item.userInfo.userID!]);
|
||
if (unRes.success) {
|
||
setState(() {
|
||
item.followType = 2;
|
||
});
|
||
ctl.mergeNoFriend(conversationID: 'c2c_${item.userInfo.userID!}');
|
||
}
|
||
} else {
|
||
// 关注
|
||
final res = await ImService.instance.followUser(userIDList: [item.userInfo.userID!]);
|
||
if (res.success) {
|
||
setState(() {
|
||
item.followType = realFollowType == 0
|
||
? 1
|
||
: realFollowType == 2
|
||
? 3
|
||
: 0;
|
||
});
|
||
final chatRes = await ImService.instance.followUser(userIDList: [item.userInfo.userID!]);
|
||
if (chatRes.success) {
|
||
final res = await ImService.instance.getConversation(conversationID: 'c2c_${item.userInfo.userID}');
|
||
if (res.success) {
|
||
V2TimConversation conversation = res.data;
|
||
if (conversation.conversationGroupList?.isNotEmpty ?? false) {
|
||
await ImService.instance.deleteConversationsFromGroup(
|
||
groupName: conversation.conversationGroupList!.first!,
|
||
conversationIDList: [conversation.conversationID],
|
||
);
|
||
ctl.updateNoFriendMenu();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
child: Text(
|
||
Utils.getTipText(item.followType),
|
||
style: const TextStyle(color: Colors.white, fontSize: 14),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
},
|
||
);
|
||
},
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|