4.1.1
This commit is contained in:
parent
57fb6f7de9
commit
9bb7aea8ab
1
assets/images/svg/more.svg
Normal file
1
assets/images/svg/more.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1759238468389" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5738" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M256 512m-74.666667 0a74.666667 74.666667 0 1 0 149.333334 0 74.666667 74.666667 0 1 0-149.333334 0Z" fill="#111111" p-id="5739"></path><path d="M512 512m-74.666667 0a74.666667 74.666667 0 1 0 149.333334 0 74.666667 74.666667 0 1 0-149.333334 0Z" fill="#111111" p-id="5740"></path><path d="M768 512m-74.666667 0a74.666667 74.666667 0 1 0 149.333334 0 74.666667 74.666667 0 1 0-149.333334 0Z" fill="#111111" p-id="5741"></path></svg>
|
||||
|
After Width: | Height: | Size: 765 B |
@ -72,6 +72,13 @@
|
||||
<string>App需要访问您的相册用于选择图片或视频</string>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>CFBundleLocalizations</key>
|
||||
<array>
|
||||
<string>en</string>
|
||||
<string>zh-Hans</string>
|
||||
</array>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<false/>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>remote-notification</string>
|
||||
|
||||
@ -47,6 +47,11 @@ class IMMessage {
|
||||
title: myInfo.nickname.value,
|
||||
desc: parseMessageSummary(msg),
|
||||
ext: jsonEncode({"userID": myInfo.userID.value, "title": myInfo.nickname.value}),
|
||||
//ios ios>18必须声明
|
||||
iOSPushType: 0, //0=普通消息 1=语音/视频
|
||||
iOSSound: 'default', // kIOSOfflinePushDefaultSound
|
||||
ignoreIOSBadge: false, // 是否忽略角标
|
||||
iOSInterruptionLevel: 'active', // 普通通知 active // time-sensitive
|
||||
);
|
||||
sendRes = await TencentImSDKPlugin.v2TIMManager.getMessageManager().sendMessage(
|
||||
message: msg,
|
||||
@ -75,7 +80,12 @@ class IMMessage {
|
||||
OfflinePushInfo offlinePushInfo = OfflinePushInfo(
|
||||
title: groupName,
|
||||
desc: parseMessageSummary(msg),
|
||||
ext: jsonEncode({"groupID": groupID, "title": groupName ?? ''}),
|
||||
ext: jsonEncode({"groupID": groupID, "title": groupName ?? '群聊'}),
|
||||
//ios ios>18必须声明
|
||||
iOSPushType: 0, //0=普通消息 1=语音/视频
|
||||
iOSSound: 'default', // kIOSOfflinePushDefaultSound
|
||||
ignoreIOSBadge: false, // 是否忽略角标
|
||||
iOSInterruptionLevel: 'active', // 普通通知
|
||||
);
|
||||
sendRes = await TencentImSDKPlugin.v2TIMManager.getMessageManager().sendMessage(
|
||||
message: msg,
|
||||
|
||||
@ -124,6 +124,15 @@ class ImService {
|
||||
);
|
||||
} else {
|
||||
logger.i("IM 登录失败:${result.code} - ${result.desc}");
|
||||
if (result.code == 70013) {
|
||||
Get.snackbar(
|
||||
'登录失败',
|
||||
'请求的 Identifier 与生成 UserSig 的 Identifier 不匹配',
|
||||
backgroundColor: Colors.red.withAlpha(230),
|
||||
colorText: Colors.white,
|
||||
icon: const Icon(Icons.error_outline, color: Colors.white),
|
||||
);
|
||||
} else {
|
||||
Get.snackbar(
|
||||
'登录失败',
|
||||
'${result.code} - ${result.desc}',
|
||||
@ -132,6 +141,7 @@ class ImService {
|
||||
icon: const Icon(Icons.error_outline, color: Colors.white),
|
||||
);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -136,12 +136,14 @@ class PushService {
|
||||
// "userID": "123456",
|
||||
// "groupID": "654321",
|
||||
// });
|
||||
final isGroup = groupID != null && groupID.isNotEmpty;
|
||||
|
||||
final data = jsonDecode(ext);
|
||||
logger.i(data);
|
||||
String extGroupID = data['groupID'] ?? '';
|
||||
final isGroup = extGroupID.isNotEmpty;
|
||||
|
||||
// final type = data['type'];
|
||||
final router = conversationTypeFromString(userID); //这里就是解析用于发送消息的管理员的userID
|
||||
|
||||
final router = conversationTypeFromString(data['userID']); //这里就是解析用于发送消息的管理员的userID
|
||||
logger.w(router);
|
||||
if (router == null) {
|
||||
// 聊天
|
||||
|
||||
@ -50,7 +50,8 @@ class _ImageViewerState extends State<ImageViewer> {
|
||||
Widget build(BuildContext context) {
|
||||
var imgCount = widget.images?.length;
|
||||
|
||||
return Scaffold(
|
||||
return SafeArea(
|
||||
child: Scaffold(
|
||||
body: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
@ -113,6 +114,7 @@ class _ImageViewerState extends State<ImageViewer> {
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -502,6 +502,7 @@ class _ChatState extends State<Chat> with SingleTickerProviderStateMixin {
|
||||
child: NetworkOrAssetImage(
|
||||
imageUrl: item.videoElem?.snapshotUrl ?? '',
|
||||
width: 120,
|
||||
placeholderAsset: 'assets/images/bk.jpg',
|
||||
),
|
||||
),
|
||||
const Align(
|
||||
@ -701,6 +702,7 @@ class _ChatState extends State<Chat> with SingleTickerProviderStateMixin {
|
||||
NetworkOrAssetImage(
|
||||
imageUrl: url,
|
||||
width: 160.0,
|
||||
placeholderAsset: 'assets/images/bk.jpg',
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
|
||||
@ -1606,10 +1608,10 @@ class _ChatState extends State<Chat> with SingleTickerProviderStateMixin {
|
||||
if (file != null) {
|
||||
var fileSizeInBytes = await file.length();
|
||||
var sizeInMB = fileSizeInBytes / (1024 * 1024);
|
||||
if (sizeInMB > 28) {
|
||||
MyDialog.toast('图片大小不能超过28MB', icon: const Icon(Icons.check_circle), style: ToastStyle(backgroundColor: Colors.red.withAlpha(200)));
|
||||
if (sizeInMB > 100) {
|
||||
MyDialog.toast('文件大小不能超过100MB', icon: const Icon(Icons.check_circle), style: ToastStyle(backgroundColor: Colors.red.withAlpha(200)));
|
||||
} else {
|
||||
print("图片合法,大小:$sizeInMB MB");
|
||||
print("视频合法,大小:$sizeInMB MB");
|
||||
// 执行发送逻辑
|
||||
var snapshot = await generateVideoThumbnail(file.path);
|
||||
String? mimeType = await asset.mimeTypeAsync;
|
||||
@ -1875,7 +1877,7 @@ class _ChatState extends State<Chat> with SingleTickerProviderStateMixin {
|
||||
title: Obx(() {
|
||||
return Text(
|
||||
// '${arguments['title']}',
|
||||
'${arguments.value.showName}',
|
||||
arguments.value.showName ?? '神秘人',
|
||||
style: const TextStyle(fontSize: 18.0, fontFamily: 'Arial'),
|
||||
);
|
||||
}),
|
||||
|
||||
@ -383,6 +383,7 @@ class _ChatGroupState extends State<ChatGroup> with SingleTickerProviderStateMix
|
||||
borderRadius: BorderRadius.circular(10.0),
|
||||
child: NetworkOrAssetImage(
|
||||
imageUrl: item.videoElem?.snapshotUrl ?? '',
|
||||
placeholderAsset: 'assets/images/bk.jpg',
|
||||
width: 120,
|
||||
),
|
||||
),
|
||||
@ -541,6 +542,7 @@ class _ChatGroupState extends State<ChatGroup> with SingleTickerProviderStateMix
|
||||
children: [
|
||||
NetworkOrAssetImage(
|
||||
imageUrl: url,
|
||||
placeholderAsset: 'assets/images/bk.jpg',
|
||||
width: 160.0,
|
||||
),
|
||||
Container(
|
||||
@ -1568,7 +1570,7 @@ class _ChatGroupState extends State<ChatGroup> with SingleTickerProviderStateMix
|
||||
obj['ids'] = ids.join(',');
|
||||
data.customElem!.data = jsonEncode(obj);
|
||||
// 修改消息体
|
||||
ImService.instance.modifyMessage(message: data);
|
||||
await ImService.instance.modifyMessage(message: data);
|
||||
// 模拟开红包逻辑,1 秒后停止动画
|
||||
Future.delayed(Duration(seconds: 1), () {
|
||||
animController.stop();
|
||||
@ -1585,7 +1587,7 @@ class _ChatGroupState extends State<ChatGroup> with SingleTickerProviderStateMix
|
||||
obj['totalCount'] = 0;
|
||||
obj['open'] = true; //总开关标记为true
|
||||
data.customElem!.data = jsonEncode(obj);
|
||||
ImService.instance.modifyMessage(message: data);
|
||||
await ImService.instance.modifyMessage(message: data);
|
||||
|
||||
Future.delayed(Duration(seconds: 1), () {
|
||||
animController.stop();
|
||||
@ -1748,7 +1750,7 @@ class _ChatGroupState extends State<ChatGroup> with SingleTickerProviderStateMix
|
||||
),
|
||||
titleSpacing: 1.0,
|
||||
title: Text(
|
||||
'${arguments.showName}',
|
||||
arguments.showName ?? '群聊',
|
||||
style: const TextStyle(fontSize: 18.0, fontFamily: 'Arial'),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
|
||||
@ -441,6 +441,7 @@ class _ChatNoFriendState extends State<ChatNoFriend> with SingleTickerProviderSt
|
||||
child: NetworkOrAssetImage(
|
||||
imageUrl: item.videoElem?.snapshotUrl ?? '',
|
||||
width: 120,
|
||||
placeholderAsset: 'assets/images/bk.jpg',
|
||||
),
|
||||
),
|
||||
const Align(
|
||||
@ -605,6 +606,7 @@ class _ChatNoFriendState extends State<ChatNoFriend> with SingleTickerProviderSt
|
||||
children: [
|
||||
NetworkOrAssetImage(
|
||||
imageUrl: url,
|
||||
placeholderAsset: 'assets/images/bk.jpg',
|
||||
width: 160.0,
|
||||
),
|
||||
Container(
|
||||
@ -1515,7 +1517,7 @@ class _ChatNoFriendState extends State<ChatNoFriend> with SingleTickerProviderSt
|
||||
title: Obx(() {
|
||||
return Text(
|
||||
// '${arguments['title']}',
|
||||
'${arguments.value.showName}',
|
||||
arguments.value.showName ?? '陌生人',
|
||||
style: const TextStyle(fontSize: 18.0, fontFamily: 'Arial'),
|
||||
);
|
||||
}),
|
||||
|
||||
@ -103,6 +103,7 @@ class ChatPageState extends State<ChatPage> {
|
||||
final controller = Get.find<ImUserInfoController>();
|
||||
final role = controller.role.value;
|
||||
final isSeller = Utils.hasRole(role, 2);
|
||||
// writeOffCodeId
|
||||
if (isSeller) {
|
||||
// 带着核销码,跳转到商家的商品详情页面,引导商家去手动点击核销按钮
|
||||
Get.toNamed('/sellerOrder/detail', arguments: {'writeOffCodeId': value});
|
||||
@ -638,6 +639,8 @@ class ChatPageState extends State<ChatPage> {
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
// logger.e(chatList[index].isCustomAdmin);
|
||||
|
||||
if (conversationTypeFromString(chatList[index].isCustomAdmin) != null) {
|
||||
// 跳转对应的通知消息页 notify下的内容
|
||||
logger.e(chatList[index].isCustomAdmin);
|
||||
|
||||
@ -7,13 +7,11 @@ import 'package:easy_refresh/easy_refresh.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:loopin/IM/im_service.dart';
|
||||
import 'package:loopin/api/video_api.dart';
|
||||
import 'package:loopin/behavior/custom_scroll_behavior.dart';
|
||||
import 'package:loopin/components/empty_tip.dart';
|
||||
import 'package:loopin/components/network_or_asset_image.dart';
|
||||
import 'package:loopin/models/conversation_type.dart';
|
||||
import 'package:loopin/models/notify_message.type.dart';
|
||||
import 'package:loopin/service/http.dart';
|
||||
import 'package:loopin/styles/index.dart';
|
||||
import 'package:loopin/utils/index.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
|
||||
@ -93,7 +91,7 @@ class InteractionState extends State<Interaction> with SingleTickerProviderState
|
||||
Future<void> getMsgData() async {
|
||||
// 获取最旧一条消息作为游标
|
||||
V2TimMessage? lastRealMsg;
|
||||
lastRealMsg = msgList.last;
|
||||
lastRealMsg = msgList.isEmpty ? null : msgList.last;
|
||||
final res = await ImService.instance.getHistoryMessageList(
|
||||
userID: ConversationType.interaction.name, // userID为固定的interaction
|
||||
lastMsg: lastRealMsg,
|
||||
@ -118,13 +116,34 @@ class InteractionState extends State<Interaction> with SingleTickerProviderState
|
||||
// 获取不同的消息分类数据
|
||||
void _filterMessages(String filterType) async {
|
||||
logger.e(filterType);
|
||||
if (filterType == 'all') {
|
||||
getMsgData();
|
||||
return;
|
||||
}
|
||||
// 非全部
|
||||
String keyword;
|
||||
// interactionComment, //互动->评论
|
||||
// interactionAt, //互动->视频评论中的@
|
||||
// interactionLike, //互动->点赞
|
||||
// interactionReply, //互动->评论回复
|
||||
if (filterType == 'interactionComment') {
|
||||
keyword = '评论';
|
||||
} else if (filterType == 'interactionLike') {
|
||||
keyword = '点赞';
|
||||
} else if (filterType == 'interactionReply') {
|
||||
keyword = '回复';
|
||||
} else {
|
||||
keyword = '视频'; //这个兜底
|
||||
}
|
||||
final res = await ImService.instance.searchLocalMessages(
|
||||
page: page,
|
||||
conversationID: 'c2c_${ConversationType.interaction.name}',
|
||||
keywordList: ['action', filterType],
|
||||
keywordList: [keyword],
|
||||
// keywordList: ['action', filterType], //interactionLike
|
||||
);
|
||||
logger.e(res.data!.toLogString());
|
||||
logger.e(res.data!.toJson());
|
||||
if (res.success && res.data != null) {
|
||||
msgList.clear();
|
||||
final resultList = res.data?.messageSearchResultItems ?? [];
|
||||
if (resultList.isNotEmpty) {
|
||||
for (var item in resultList) {
|
||||
@ -132,6 +151,7 @@ class InteractionState extends State<Interaction> with SingleTickerProviderState
|
||||
msgList.addAll(item.messageList ?? []);
|
||||
}
|
||||
} else {
|
||||
msgList.clear();
|
||||
logger.e('数据为空${res.desc}');
|
||||
}
|
||||
}
|
||||
@ -244,15 +264,15 @@ class InteractionState extends State<Interaction> with SingleTickerProviderState
|
||||
child: EasyRefresh.builder(
|
||||
callLoadOverOffset: 20, //触底距离
|
||||
callRefreshOverOffset: 20, // 下拉距离
|
||||
header: ClassicHeader(
|
||||
dragText: '下拉刷新',
|
||||
armedText: '释放刷新',
|
||||
readyText: '加载中...',
|
||||
processingText: '加载中...',
|
||||
processedText: '加载完成',
|
||||
failedText: '加载失败,请重试',
|
||||
messageText: '最后更新于 %T',
|
||||
),
|
||||
// header: ClassicHeader(
|
||||
// dragText: '下拉刷新',
|
||||
// armedText: '释放刷新',
|
||||
// readyText: '加载中...',
|
||||
// processingText: '加载中...',
|
||||
// processedText: '加载完成',
|
||||
// failedText: '加载失败,请重试',
|
||||
// messageText: '最后更新于 %T',
|
||||
// ),
|
||||
footer: ClassicFooter(
|
||||
dragText: '加载更多',
|
||||
armedText: '释放加载',
|
||||
@ -263,11 +283,11 @@ class InteractionState extends State<Interaction> with SingleTickerProviderState
|
||||
failedText: '加载失败,请重试',
|
||||
messageText: '最后更新于 %T',
|
||||
),
|
||||
onRefresh: () async {
|
||||
await handleRefresh();
|
||||
},
|
||||
// onRefresh: () async {
|
||||
// await handleRefresh();
|
||||
// },
|
||||
onLoad: () async {
|
||||
if (hasMore.value) {
|
||||
if (selectedMessageType.value != 'all' && hasMore.value) {
|
||||
await getMsgData();
|
||||
return hasMore.value ? IndicatorResult.success : IndicatorResult.noMore;
|
||||
}
|
||||
@ -297,6 +317,8 @@ class InteractionState extends State<Interaction> with SingleTickerProviderState
|
||||
final desc = msgList[index].customElem!.desc!;
|
||||
final jsonData = msgList[index].customElem!.data ?? '{"faceUrl":"","nickName":"data为null","userID":"213213"}';
|
||||
final item = jsonDecode(jsonData); // 数据
|
||||
logger.e(item);
|
||||
|
||||
// ----测试数据
|
||||
// final jsonData = '{"faceUrl":"","nickName":"测试昵称","userID":"213213"}';
|
||||
// final item = jsonDecode(jsonData); // 数据
|
||||
@ -310,15 +332,14 @@ class InteractionState extends State<Interaction> with SingleTickerProviderState
|
||||
spacing: 10.0,
|
||||
children: <Widget>[
|
||||
// 头像
|
||||
InkWell(
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
// 点击头像转到对方主页
|
||||
// 先获取视频详情
|
||||
// 如果cloudCustomData是interactionComment,interactionAt,interactionReply,传参时带上评论id,这三个是评论相关的
|
||||
//
|
||||
final res = await Http.get('${VideoApi.detail}/${item['vlogID']}');
|
||||
// 此人存在才做跳转
|
||||
Get.toNamed('/vloger', arguments: res['data']);
|
||||
// final res = await Http.get('${VideoApi.detail}/${item['vlogID']}');
|
||||
Get.toNamed('/vloger', arguments: {'memberId': item['userID']});
|
||||
},
|
||||
child: ClipOval(
|
||||
child: NetworkOrAssetImage(
|
||||
@ -331,15 +352,13 @@ class InteractionState extends State<Interaction> with SingleTickerProviderState
|
||||
|
||||
// 消息
|
||||
Expanded(
|
||||
child: InkWell(
|
||||
child: GestureDetector(
|
||||
onTap: () async {
|
||||
// 点击头像转到对方主页
|
||||
// 先获取视频详情
|
||||
// 如果cloudCustomData是interactionComment,interactionAt,interactionReply,传参时带上评论id,
|
||||
//
|
||||
final res = await Http.get('${VideoApi.detail}/${item['vlogID']}');
|
||||
Get.toNamed('/vloger', arguments: res['data']);
|
||||
// Get.toNamed('/vloger');
|
||||
logger.e(item);
|
||||
Get.toNamed('/videoDetail', arguments: {'videoId': item['vlogID']});
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@ -373,7 +392,11 @@ class InteractionState extends State<Interaction> with SingleTickerProviderState
|
||||
),
|
||||
|
||||
// 右侧
|
||||
Row(
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Get.toNamed('/videoDetail', arguments: {'videoId': item['vlogID']});
|
||||
},
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Visibility(
|
||||
@ -394,6 +417,7 @@ class InteractionState extends State<Interaction> with SingleTickerProviderState
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@ -7,13 +7,10 @@ import 'package:easy_refresh/easy_refresh.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:loopin/IM/im_service.dart';
|
||||
import 'package:loopin/api/video_api.dart';
|
||||
import 'package:loopin/behavior/custom_scroll_behavior.dart';
|
||||
import 'package:loopin/components/empty_tip.dart';
|
||||
import 'package:loopin/components/my_toast.dart';
|
||||
import 'package:loopin/components/network_or_asset_image.dart';
|
||||
import 'package:loopin/models/conversation_type.dart';
|
||||
import 'package:loopin/service/http.dart';
|
||||
import 'package:loopin/styles/index.dart';
|
||||
import 'package:loopin/utils/index.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
|
||||
@ -187,6 +184,7 @@ class NewfoucsState extends State<Newfoucs> with SingleTickerProviderStateMixin
|
||||
jsonData = (jsonData == null || jsonData.isEmpty) ? '{"faceUrl":"","nickName":"data为空","userID":"213213"}' : jsonData;
|
||||
|
||||
final item = jsonDecode(jsonData);
|
||||
logger.e(item);
|
||||
|
||||
logger.w(element.toJson());
|
||||
|
||||
@ -210,13 +208,7 @@ class NewfoucsState extends State<Newfoucs> with SingleTickerProviderStateMixin
|
||||
// 先获取视频详情
|
||||
// 如果cloudCustomData是interactionComment,interactionAt,interactionReply,传参时带上评论id,
|
||||
//
|
||||
final res = await Http.get('${VideoApi.detail}/${item['vlogID']}');
|
||||
if (res['data'] == null) {
|
||||
MyToast().tip(title: '视频数据不存在', position: 'top');
|
||||
} else {
|
||||
// 这里跟视频首页一样,跳转博主主页时传视频详情数据
|
||||
Get.toNamed('/vloger', arguments: res['data']);
|
||||
}
|
||||
Get.toNamed('/vloger', arguments: {'memberId': item['userID']});
|
||||
},
|
||||
child: ClipOval(
|
||||
child: NetworkOrAssetImage(
|
||||
@ -232,8 +224,8 @@ class NewfoucsState extends State<Newfoucs> with SingleTickerProviderStateMixin
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
// 点击头像转到对方主页,先获取视频详情
|
||||
final res = await Http.get('${VideoApi.detail}/${item['vlogID']}');
|
||||
Get.toNamed('/vloger', arguments: res['data']);
|
||||
Get.toNamed('/vloger', arguments: {'memberId': item['userID']});
|
||||
|
||||
// Get.toNamed('/vloger');
|
||||
},
|
||||
child: Column(
|
||||
|
||||
@ -190,7 +190,8 @@ class _GoodsState extends State<Goods> {
|
||||
|
||||
void handlCoverClick(V2TimConversation conv) async {
|
||||
// 发送自定义消息 商品信息
|
||||
final userId = conv.userID;
|
||||
final isGroup = conv.groupID != null && (conv.groupID ?? '').isNotEmpty;
|
||||
final id = isGroup ? conv.groupID : conv.userID;
|
||||
//price,title,url,sell
|
||||
logger.w(shopObj['name']);
|
||||
final makeJson = jsonEncode({
|
||||
@ -205,7 +206,12 @@ class _GoodsState extends State<Goods> {
|
||||
data: makeJson,
|
||||
);
|
||||
if (res.success) {
|
||||
final sendRes = await IMMessage().sendMessage(msg: res.data!.messageInfo!, toUserID: userId, cloudCustomData: SummaryType.shareTuangou);
|
||||
final sendRes = await IMMessage().sendMessage(
|
||||
msg: res.data!.messageInfo!,
|
||||
groupID: isGroup ? id : null,
|
||||
toUserID: isGroup ? null : id,
|
||||
cloudCustomData: SummaryType.shareTuangou,
|
||||
);
|
||||
if (sendRes.success) {
|
||||
MyToast().tip(
|
||||
title: '分享成功',
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import 'package:easy_refresh/easy_refresh.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:loopin/IM/im_service.dart';
|
||||
import 'package:loopin/components/network_or_asset_image.dart';
|
||||
import 'package:loopin/styles/index.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_full_info.dart';
|
||||
@ -184,6 +185,7 @@ class _MemberActionSheetState extends State<InviteActionSheet> {
|
||||
final showName = uname.isEmpty ? nickname : uname;
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
FocusScope.of(context).unfocus();
|
||||
setState(() {
|
||||
if (_selectedIDs.contains(id)) {
|
||||
_selectedIDs.remove(id);
|
||||
@ -196,12 +198,15 @@ class _MemberActionSheetState extends State<InviteActionSheet> {
|
||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
// 左侧圆形头像
|
||||
CircleAvatar(
|
||||
radius: 20,
|
||||
backgroundImage: m.faceUrl != null ? NetworkImage(m.faceUrl!) : null,
|
||||
child: m.faceUrl == null ? const Icon(Icons.person) : null,
|
||||
// 头像
|
||||
ClipOval(
|
||||
child: NetworkOrAssetImage(
|
||||
imageUrl: m.faceUrl ?? '',
|
||||
width: 40.0,
|
||||
height: 40.0,
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(width: 12),
|
||||
|
||||
// 用户名
|
||||
|
||||
@ -2,6 +2,7 @@ import 'package:easy_refresh/easy_refresh.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:loopin/IM/im_service.dart';
|
||||
import 'package:loopin/components/network_or_asset_image.dart';
|
||||
import 'package:loopin/pages/groupChat/controller/group_detail_controller.dart';
|
||||
import 'package:loopin/styles/index.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/enum/group_member_filter_enum.dart';
|
||||
@ -50,6 +51,7 @@ class _MemberActionSheetState extends State<MemberActionSheet> {
|
||||
final self = Get.find<GroupDetailController>().selfInfo.value!;
|
||||
members.insert(0, self);
|
||||
}
|
||||
|
||||
getMemberData();
|
||||
}
|
||||
|
||||
@ -59,7 +61,7 @@ class _MemberActionSheetState extends State<MemberActionSheet> {
|
||||
loading = true;
|
||||
final res = await ImService.instance.getGroupMemberList(
|
||||
groupID: widget.groupID,
|
||||
filter: GroupMemberFilterTypeEnum.V2TIM_GROUP_MEMBER_FILTER_COMMON,
|
||||
filter: GroupMemberFilterTypeEnum.V2TIM_GROUP_MEMBER_FILTER_ALL,
|
||||
nextSeq: nextSeq,
|
||||
count: 100,
|
||||
);
|
||||
@ -67,8 +69,13 @@ class _MemberActionSheetState extends State<MemberActionSheet> {
|
||||
logger.e(res.data!.nextSeq);
|
||||
nextSeq = res.data!.nextSeq ?? '0';
|
||||
final mem = res.data!.memberInfoList ?? [];
|
||||
setState(() {
|
||||
//去重自己
|
||||
if (widget.showSelf) {
|
||||
members.addAll(mem);
|
||||
members = {for (var m in members) m.userID: m}.values.toList();
|
||||
}
|
||||
|
||||
setState(() {
|
||||
hasMore = res.data!.nextSeq == '0' ? false : true;
|
||||
loading = false;
|
||||
});
|
||||
@ -131,7 +138,7 @@ class _MemberActionSheetState extends State<MemberActionSheet> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List filteredMembers;
|
||||
List<V2TimGroupMemberFullInfo> filteredMembers;
|
||||
if (_query.isEmpty) {
|
||||
filteredMembers = members;
|
||||
} else {
|
||||
@ -223,23 +230,36 @@ class _MemberActionSheetState extends State<MemberActionSheet> {
|
||||
final showName = uname.isEmpty ? nickname : uname;
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
FocusScope.of(context).unfocus();
|
||||
setState(() {
|
||||
if (widget.showSelf) {
|
||||
// 显示自己=查看群成员,这里后面加查看群成员资料,先跳去博主的主页吧
|
||||
final selfInfo = Get.find<GroupDetailController>().selfInfo.value ?? V2TimGroupMemberFullInfo(userID: '');
|
||||
final currentUserID = selfInfo.userID;
|
||||
if (m.userID != currentUserID) {
|
||||
Get.toNamed('/vloger', arguments: {'memberId': m.userID});
|
||||
}
|
||||
} else {
|
||||
// false=移除群成员
|
||||
if (_selectedIDs.contains(id)) {
|
||||
_selectedIDs.remove(id);
|
||||
} else {
|
||||
_selectedIDs.add(id);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
// 左侧圆形头像
|
||||
CircleAvatar(
|
||||
radius: 20,
|
||||
backgroundImage: m.faceUrl != null ? NetworkImage(m.faceUrl!) : null,
|
||||
child: m.faceUrl == null ? const Icon(Icons.person) : null,
|
||||
// 头像
|
||||
ClipOval(
|
||||
child: NetworkOrAssetImage(
|
||||
imageUrl: m.faceUrl ?? '',
|
||||
width: 40.0,
|
||||
height: 40.0,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
|
||||
|
||||
@ -166,16 +166,34 @@ class GroupdetailState extends State<Groupdetail> {
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
Utils.handleText(controller.info.value?.groupName, '', "未命名群聊"),
|
||||
// '很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长',
|
||||
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
if (controller.isOwner.value)
|
||||
Icon(
|
||||
Icons.edit,
|
||||
size: 14,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// 群简介
|
||||
subtitle: Obx(
|
||||
subtitle: Padding(
|
||||
padding: const EdgeInsets.only(top: 6.0),
|
||||
child: Obx(
|
||||
() => GestureDetector(
|
||||
onTap: () {
|
||||
// 去setinfo页
|
||||
@ -200,17 +218,64 @@ class GroupdetailState extends State<Groupdetail> {
|
||||
},
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// 普通成员点击,查看完成的描述内容
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
|
||||
),
|
||||
isScrollControlled: true, // 超出可滚动
|
||||
builder: (ctx) => SafeArea(
|
||||
child: Container(
|
||||
width: double.infinity, // 👈 占满宽度
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min, // 根据内容自适应高度
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text(
|
||||
"群简介",
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
Utils.handleText(controller.info.value?.introduction, '', "暂无群介绍"),
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Row(mainAxisSize: MainAxisSize.max, children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
Utils.handleText(controller.info.value?.introduction, '', "暂无群介绍"),
|
||||
// '非常长的内容非常长的内容非常长的内容非常长的内容非常长的内容非常长的内容',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(color: Colors.grey),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
trailing: const Icon(Icons.chevron_right),
|
||||
if (controller.isOwner.value)
|
||||
Icon(
|
||||
Icons.edit,
|
||||
size: 14,
|
||||
)
|
||||
]),
|
||||
),
|
||||
),
|
||||
),
|
||||
// trailing: const Icon(Icons.chevron_right),
|
||||
),
|
||||
const Divider(height: 1),
|
||||
|
||||
@ -252,19 +317,12 @@ class GroupdetailState extends State<Groupdetail> {
|
||||
);
|
||||
},
|
||||
),
|
||||
// 群成员头像区域
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||
child: Wrap(
|
||||
spacing: 16,
|
||||
runSpacing: 12,
|
||||
children: [
|
||||
Obx(
|
||||
() {
|
||||
return Wrap(
|
||||
spacing: 16,
|
||||
runSpacing: 12,
|
||||
children: controller.memberList.take(8).map((m) {
|
||||
// 点击成员头像
|
||||
child: Obx(() {
|
||||
// 成员头像
|
||||
final memberWidgets = controller.memberList.take(8).map((m) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
final currentUserID = controller.selfInfo.value?.userID ?? '';
|
||||
@ -288,25 +346,22 @@ class GroupdetailState extends State<Groupdetail> {
|
||||
child: Text(
|
||||
m.nickName ?? '未知昵称',
|
||||
maxLines: 1,
|
||||
softWrap: false,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: false,
|
||||
style: const TextStyle(fontSize: 12),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
},
|
||||
),
|
||||
// 邀请 +
|
||||
GestureDetector(
|
||||
}).toList();
|
||||
|
||||
// 邀请按钮
|
||||
final inviteWidget = GestureDetector(
|
||||
onTap: () {
|
||||
//检测群人数上限,
|
||||
logger.w('当前人数${controller.info.value?.memberCount ?? 0}---上限人数${controller.info.value?.memberMaxCount ?? 0}');
|
||||
if ((controller.info.value?.memberCount ?? 0) < (controller.info.value?.memberMaxCount ?? 0)) {
|
||||
// 群人数未达到上限,可以继续加人
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
barrierColor: Colors.white,
|
||||
@ -331,19 +386,17 @@ class GroupdetailState extends State<Groupdetail> {
|
||||
}
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
CircleAvatar(
|
||||
radius: 25,
|
||||
child: const Icon(Icons.add),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
const Text("邀请", style: TextStyle(fontSize: 12)),
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: const [
|
||||
CircleAvatar(radius: 25, child: Icon(Icons.add)),
|
||||
SizedBox(height: 4),
|
||||
Text("邀请", style: TextStyle(fontSize: 12)),
|
||||
],
|
||||
),
|
||||
),
|
||||
// 移除 -
|
||||
Obx(
|
||||
() => controller.isOwner.value
|
||||
);
|
||||
|
||||
// 移除按钮(只有群主显示)
|
||||
final removeWidget = controller.isOwner.value
|
||||
? GestureDetector(
|
||||
onTap: () {
|
||||
showModalBottomSheet(
|
||||
@ -367,20 +420,32 @@ class GroupdetailState extends State<Groupdetail> {
|
||||
);
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
const CircleAvatar(
|
||||
radius: 25,
|
||||
child: Icon(Icons.remove),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
const Text("移除", style: TextStyle(fontSize: 12)),
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: const [
|
||||
CircleAvatar(radius: 25, child: Icon(Icons.remove)),
|
||||
SizedBox(height: 4),
|
||||
Text("移除", style: TextStyle(fontSize: 12)),
|
||||
],
|
||||
),
|
||||
)
|
||||
: SizedBox.shrink(),
|
||||
)
|
||||
],
|
||||
),
|
||||
: const SizedBox.shrink();
|
||||
|
||||
final allWidgets = <Widget>[
|
||||
...memberWidgets,
|
||||
inviteWidget,
|
||||
];
|
||||
if (controller.isOwner.value) allWidgets.add(removeWidget);
|
||||
|
||||
return GridView.count(
|
||||
shrinkWrap: true, // 适应内容高度
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
crossAxisCount: 4, // 每行显示 4 个
|
||||
mainAxisSpacing: 0, // 行间距
|
||||
crossAxisSpacing: 16, // 列间距
|
||||
childAspectRatio: 1, // 调整宽高比
|
||||
children: allWidgets,
|
||||
);
|
||||
}),
|
||||
),
|
||||
const Divider(height: 1),
|
||||
|
||||
|
||||
@ -167,6 +167,7 @@ class _IndexPageState extends State<IndexPage> with TickerProviderStateMixin {
|
||||
|
||||
/// 切换数据
|
||||
Future<void> changeData(int index) async {
|
||||
dataList.clear();
|
||||
if (isLoading.value) return;
|
||||
isLoading.value = true;
|
||||
final res = await Http.post(ShopApi.shopList, data: {
|
||||
@ -178,12 +179,12 @@ class _IndexPageState extends State<IndexPage> with TickerProviderStateMixin {
|
||||
final data = res['data']['records'];
|
||||
final total = res['data']['total'];
|
||||
logger.w(res);
|
||||
dataList.value = data;
|
||||
if (dataList.length >= total) {
|
||||
hasMore.value = false;
|
||||
isLoading.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// logger.w(res);
|
||||
dataList.value = data;
|
||||
page += 1;
|
||||
isLoading.value = false;
|
||||
isInitLoading.value = false;
|
||||
@ -202,13 +203,14 @@ class _IndexPageState extends State<IndexPage> with TickerProviderStateMixin {
|
||||
final data = res['data']['records'];
|
||||
final total = res['data']['total'];
|
||||
logger.w(res);
|
||||
dataList.addAll(data);
|
||||
if (dataList.length >= total) {
|
||||
hasMore.value = false;
|
||||
isLoading.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// logger.w(res);
|
||||
dataList.addAll(data);
|
||||
page += 1;
|
||||
logger.e(page);
|
||||
isLoading.value = false;
|
||||
isInitLoading.value = false;
|
||||
}
|
||||
@ -528,16 +530,16 @@ class _IndexPageState extends State<IndexPage> with TickerProviderStateMixin {
|
||||
SliverToBoxAdapter(
|
||||
child: Obx(
|
||||
() {
|
||||
if (isInitLoading.value) {
|
||||
return Column(
|
||||
children: [
|
||||
RefreshProgressIndicator(
|
||||
backgroundColor: Colors.white,
|
||||
color: Color(0xFFFF5000),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
// if (isInitLoading.value) {
|
||||
// return Column(
|
||||
// children: [
|
||||
// RefreshProgressIndicator(
|
||||
// backgroundColor: Colors.white,
|
||||
// color: Color(0xFFFF5000),
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// }
|
||||
if (dataList.isEmpty) {
|
||||
return EmptyTip();
|
||||
}
|
||||
|
||||
@ -291,7 +291,6 @@ class _UserInfoState extends State<UserInfo> {
|
||||
} else {
|
||||
print("图片合法,大小:$sizeInMB MB");
|
||||
//走upload(file)上传图片拿到url地址
|
||||
|
||||
final croppedFile = await ImageCropper().cropImage(
|
||||
sourcePath: file.path,
|
||||
maxWidth: 1024,
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get_rx/src/rx_typedefs/rx_typedefs.dart';
|
||||
import 'package:loopin/IM/controller/chat_controller.dart';
|
||||
@ -271,6 +272,17 @@ class MyPageState extends State<Vloger> with SingleTickerProviderStateMixin {
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildIcon(String assetPath, VoidCallback onTap) {
|
||||
return InkWell(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 5.0, vertical: 5.0),
|
||||
decoration: BoxDecoration(color: Colors.black.withAlpha((0.3 * 255).round()), borderRadius: BorderRadius.circular(20.0)),
|
||||
child: SvgPicture.asset(assetPath, height: 20.0, width: 20.0, colorFilter: const ColorFilter.mode(Colors.white70, BlendMode.srcIn)),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PopScope(
|
||||
@ -297,12 +309,7 @@ class MyPageState extends State<Vloger> with SingleTickerProviderStateMixin {
|
||||
pinned: true,
|
||||
stretch: true,
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(
|
||||
Icons.more_horiz,
|
||||
color: Colors.black,
|
||||
),
|
||||
onPressed: () async {
|
||||
_buildIcon('assets/images/svg/more.svg', () async {
|
||||
final paddingTop = MediaQuery.of(Get.context!).padding.top;
|
||||
|
||||
final selected = await showMenu(
|
||||
@ -364,8 +371,8 @@ class MyPageState extends State<Vloger> with SingleTickerProviderStateMixin {
|
||||
// break;
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
}),
|
||||
const SizedBox(width: 10.0),
|
||||
],
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
|
||||
@ -84,6 +84,9 @@ class _SellerOrderDetailState extends State<SellerOrderDetail> with SingleTicker
|
||||
logger.e('code=$code');
|
||||
final res = await Http.get('${ShopApi.getWriteOffDetail}?code=$code');
|
||||
logger.w('订单详情-------------->${res['data']}');
|
||||
if (res == null) {
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
orderGoodsInfo = res['data'];
|
||||
_isLoading = false;
|
||||
@ -428,7 +431,9 @@ class _SellerOrderDetailState extends State<SellerOrderDetail> with SingleTicker
|
||||
body: _isLoading
|
||||
? Center(child: CircularProgressIndicator())
|
||||
: orderGoodsInfo == null
|
||||
? emptyTip()
|
||||
? Center(
|
||||
child: emptyTip(),
|
||||
)
|
||||
: ScrollConfiguration(
|
||||
behavior: CustomScrollBehavior().copyWith(scrollbars: false),
|
||||
child: ListView(
|
||||
@ -494,7 +499,8 @@ class _SellerOrderDetailState extends State<SellerOrderDetail> with SingleTicker
|
||||
Row(
|
||||
children: [
|
||||
Spacer(),
|
||||
orderGoodsInfo['items'][0]['status'] == 1
|
||||
// orderGoodsInfo['items'][0]['status'] == 1
|
||||
orderGoodsInfo['verificationCodeStatus'] == 1
|
||||
? Text(
|
||||
'已核销',
|
||||
style: TextStyle(
|
||||
@ -557,7 +563,7 @@ class _SellerOrderDetailState extends State<SellerOrderDetail> with SingleTicker
|
||||
SizedBox(height: 10),
|
||||
Column(
|
||||
children: [
|
||||
_buildOrderInfoRow('订单号', orderGoodsInfo?['orderId']?.toString() ?? ''),
|
||||
_buildOrderInfoRow('订单号', orderGoodsInfo?['orderSn']?.toString() ?? ''),
|
||||
_buildOrderInfoRow('下单时间', orderGoodsInfo?['createTime']?.toString() ?? ''),
|
||||
_buildOrderInfoRow('购买数量', _calculateTotalQuantity().toString()),
|
||||
_orderId.isNotEmpty
|
||||
@ -607,6 +613,7 @@ class _SellerOrderDetailState extends State<SellerOrderDetail> with SingleTicker
|
||||
}
|
||||
|
||||
Widget _buildOrderInfoRow(String label, String value) {
|
||||
// logger.e(orderGoodsInfo);
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 6.0),
|
||||
child: Row(
|
||||
|
||||
@ -90,6 +90,7 @@ class _UploadVideoPageState extends State<UploadVideoPage> {
|
||||
if (file != null) {
|
||||
final fileSizeInBytes = await file.length();
|
||||
final sizeInMB = fileSizeInBytes / (1024 * 1024);
|
||||
// 时间长度
|
||||
if (sizeInMB > 200) {
|
||||
MyDialog.toast('文件大小不能超过200MB', icon: const Icon(Icons.check_circle), style: ToastStyle(backgroundColor: Colors.red.withAlpha(200)));
|
||||
} else {
|
||||
|
||||
@ -683,7 +683,7 @@ class _VideoDetailPageState extends State<VideoDetailPage> {
|
||||
),
|
||||
child: ClipOval(
|
||||
child: NetworkOrAssetImage(
|
||||
imageUrl: videoData['vlogerFace'] ?? videoData['commentUserFace'],
|
||||
imageUrl: videoData['vlogerFace'] ?? videoData['avatar'],
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -808,7 +808,7 @@ class _VideoDetailPageState extends State<VideoDetailPage> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'@${videoData['vlogerNickname'] ?? videoData['commentUserNickname'] ?? '未知用户'}',
|
||||
'@${videoData['nickname'] ?? '未知用户'}',
|
||||
style: const TextStyle(color: Colors.white, fontSize: 16.0),
|
||||
),
|
||||
LayoutBuilder(
|
||||
@ -1179,8 +1179,8 @@ class _CommentBottomSheetState extends State<CommentBottomSheet> {
|
||||
|
||||
final comment = commentList[index];
|
||||
final hasReplies = comment['childCount'] > 0;
|
||||
final isExpanded = expandedReplies[comment['id']] == true;
|
||||
final replies = replyData[comment['id']] ?? [];
|
||||
final isExpanded = expandedReplies[comment['commentId']] == true;
|
||||
final replies = replyData[comment['commentId']] ?? [];
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
@ -1211,7 +1211,7 @@ class _CommentBottomSheetState extends State<CommentBottomSheet> {
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
replyingCommentId = comment['id'];
|
||||
replyingCommentId = comment['commentId'];
|
||||
replyingCommentUser = comment['commentUserNickname'] ?? '未知用户';
|
||||
});
|
||||
},
|
||||
@ -1239,10 +1239,10 @@ class _CommentBottomSheetState extends State<CommentBottomSheet> {
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
expandedReplies[comment['id']] = !isExpanded;
|
||||
if (expandedReplies[comment['id']] == true &&
|
||||
(replyData[comment['id']] == null || replyData[comment['id']]!.isEmpty)) {
|
||||
fetchReplies(comment['id'], false);
|
||||
expandedReplies[comment['commentId']] = !isExpanded;
|
||||
if (expandedReplies[comment['commentId']] == true &&
|
||||
(replyData[comment['commentId']] == null || replyData[comment['commentId']]!.isEmpty)) {
|
||||
fetchReplies(comment['commentId'], false);
|
||||
}
|
||||
});
|
||||
},
|
||||
@ -1303,7 +1303,7 @@ class _CommentBottomSheetState extends State<CommentBottomSheet> {
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
replyingCommentId = comment['id'];
|
||||
replyingCommentId = comment['commentId'];
|
||||
replyingCommentUser = reply['commentUserNickname'] ?? '未知用户';
|
||||
});
|
||||
},
|
||||
@ -1337,8 +1337,8 @@ class _CommentBottomSheetState extends State<CommentBottomSheet> {
|
||||
if (replies.length < comment['childCount'])
|
||||
Center(
|
||||
child: TextButton(
|
||||
onPressed: () => fetchReplies(comment['id'], true),
|
||||
child: isLoadingReplies[comment['id']] == true ? CircularProgressIndicator() : Text('加载更多回复'),
|
||||
onPressed: () => fetchReplies(comment['commentId'], true),
|
||||
child: isLoadingReplies[comment['commentId']] == true ? CircularProgressIndicator() : Text('加载更多回复'),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@ -295,8 +295,8 @@ class _CommentBottomSheetState extends State<CommentBottomSheet> {
|
||||
|
||||
final comment = commentList[index];
|
||||
final hasReplies = comment['childCount'] > 0;
|
||||
final isExpanded = expandedReplies[comment['id']] == true;
|
||||
final replies = replyData[comment['id']] ?? [];
|
||||
final isExpanded = expandedReplies[comment['commentId']] == true;
|
||||
final replies = replyData[comment['commentId']] ?? [];
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
@ -327,7 +327,7 @@ class _CommentBottomSheetState extends State<CommentBottomSheet> {
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
replyingCommentId = comment['id'];
|
||||
replyingCommentId = comment['commentId'];
|
||||
replyingCommentUser = comment['commentUserNickname'] ?? '未知用户';
|
||||
});
|
||||
},
|
||||
@ -355,10 +355,10 @@ class _CommentBottomSheetState extends State<CommentBottomSheet> {
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
expandedReplies[comment['id']] = !isExpanded;
|
||||
if (expandedReplies[comment['id']] == true &&
|
||||
(replyData[comment['id']] == null || replyData[comment['id']]!.isEmpty)) {
|
||||
fetchReplies(comment['id'], false);
|
||||
expandedReplies[comment['commentId']] = !isExpanded;
|
||||
if (expandedReplies[comment['commentId']] == true &&
|
||||
(replyData[comment['commentId']] == null || replyData[comment['commentId']]!.isEmpty)) {
|
||||
fetchReplies(comment['commentId'], false);
|
||||
}
|
||||
});
|
||||
},
|
||||
@ -419,7 +419,7 @@ class _CommentBottomSheetState extends State<CommentBottomSheet> {
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
replyingCommentId = comment['id'];
|
||||
replyingCommentId = comment['commentId'];
|
||||
replyingCommentUser = reply['commentUserNickname'] ?? '未知用户';
|
||||
});
|
||||
},
|
||||
@ -453,8 +453,8 @@ class _CommentBottomSheetState extends State<CommentBottomSheet> {
|
||||
if (replies.length < comment['childCount'])
|
||||
Center(
|
||||
child: TextButton(
|
||||
onPressed: () => fetchReplies(comment['id'], true),
|
||||
child: isLoadingReplies[comment['id']] == true ? CircularProgressIndicator() : Text('加载更多回复'),
|
||||
onPressed: () => fetchReplies(comment['commentId'], true),
|
||||
child: isLoadingReplies[comment['commentId']] == true ? CircularProgressIndicator() : Text('加载更多回复'),
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -1164,7 +1164,7 @@ class _AttentionModuleState extends State<AttentionModule> {
|
||||
),
|
||||
child: ClipOval(
|
||||
child: NetworkOrAssetImage(
|
||||
imageUrl: videoList[index]['commentUserFace'],
|
||||
imageUrl: videoList[index]['avatar'],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@ -296,8 +296,8 @@ class _CommentBottomSheetState extends State<CommentBottomSheet> {
|
||||
|
||||
final comment = commentList[index];
|
||||
final hasReplies = comment['childCount'] > 0;
|
||||
final isExpanded = expandedReplies[comment['id']] == true;
|
||||
final replies = replyData[comment['id']] ?? [];
|
||||
final isExpanded = expandedReplies[comment['commentId']] == true;
|
||||
final replies = replyData[comment['commentId']] ?? [];
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
@ -328,7 +328,7 @@ class _CommentBottomSheetState extends State<CommentBottomSheet> {
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
replyingCommentId = comment['id'];
|
||||
replyingCommentId = comment['commentId'];
|
||||
replyingCommentUser = comment['commentUserNickname'] ?? '未知用户';
|
||||
});
|
||||
},
|
||||
@ -356,10 +356,10 @@ class _CommentBottomSheetState extends State<CommentBottomSheet> {
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
expandedReplies[comment['id']] = !isExpanded;
|
||||
if (expandedReplies[comment['id']] == true &&
|
||||
(replyData[comment['id']] == null || replyData[comment['id']]!.isEmpty)) {
|
||||
fetchReplies(comment['id'], false);
|
||||
expandedReplies[comment['commentId']] = !isExpanded;
|
||||
if (expandedReplies[comment['commentId']] == true &&
|
||||
(replyData[comment['commentId']] == null || replyData[comment['commentId']]!.isEmpty)) {
|
||||
fetchReplies(comment['commentId'], false);
|
||||
}
|
||||
});
|
||||
},
|
||||
@ -420,7 +420,7 @@ class _CommentBottomSheetState extends State<CommentBottomSheet> {
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
replyingCommentId = comment['id'];
|
||||
replyingCommentId = comment['commentId'];
|
||||
replyingCommentUser = reply['commentUserNickname'] ?? '未知用户';
|
||||
});
|
||||
},
|
||||
@ -454,8 +454,8 @@ class _CommentBottomSheetState extends State<CommentBottomSheet> {
|
||||
if (replies.length < comment['childCount'])
|
||||
Center(
|
||||
child: TextButton(
|
||||
onPressed: () => fetchReplies(comment['id'], true),
|
||||
child: isLoadingReplies[comment['id']] == true ? CircularProgressIndicator() : Text('加载更多回复'),
|
||||
onPressed: () => fetchReplies(comment['commentId'], true),
|
||||
child: isLoadingReplies[comment['commentId']] == true ? CircularProgressIndicator() : Text('加载更多回复'),
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -1169,7 +1169,7 @@ class _FriendModuleState extends State<FriendModule> {
|
||||
),
|
||||
child: ClipOval(
|
||||
child: NetworkOrAssetImage(
|
||||
imageUrl: videoList[index]['commentUserFace'],
|
||||
imageUrl: videoList[index]['avatar'],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@ -332,7 +332,7 @@ class _CommentBottomSheetState extends State<CommentBottomSheet> {
|
||||
onTap: () {
|
||||
setState(() {
|
||||
logger.e(comment);
|
||||
// replyingCommentId = comment['id']; //null
|
||||
|
||||
replyingCommentId = comment['commentId'];
|
||||
replyingCommentUser = comment['commentUserNickname'] ?? '未知用户';
|
||||
});
|
||||
@ -427,7 +427,7 @@ class _CommentBottomSheetState extends State<CommentBottomSheet> {
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
replyingCommentId = comment['id'];
|
||||
replyingCommentId = comment['commentId'];
|
||||
replyingCommentUser = reply['commentUserNickname'] ?? '未知用户';
|
||||
});
|
||||
},
|
||||
@ -461,8 +461,8 @@ class _CommentBottomSheetState extends State<CommentBottomSheet> {
|
||||
if (replies.length < comment['childCount'])
|
||||
Center(
|
||||
child: TextButton(
|
||||
onPressed: () => fetchReplies(comment['id'], true),
|
||||
child: isLoadingReplies[comment['id']] == true ? CircularProgressIndicator() : Text('加载更多回复'),
|
||||
onPressed: () => fetchReplies(comment['commentId'], true),
|
||||
child: isLoadingReplies[comment['commentId']] == true ? CircularProgressIndicator() : Text('加载更多回复'),
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -1169,13 +1169,14 @@ class _RecommendModuleState extends State<RecommendModule> {
|
||||
),
|
||||
child: ClipOval(
|
||||
child: NetworkOrAssetImage(
|
||||
imageUrl: videoList[index]['commentUserFace'],
|
||||
imageUrl: videoList[index]['avatar'],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// 关注区域
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
left: 15.0,
|
||||
|
||||
@ -22,7 +22,7 @@ class UpgradeService {
|
||||
});
|
||||
if (!state.mounted) return;
|
||||
|
||||
logger.w(res);
|
||||
logger.e(res);
|
||||
final result = res['data']['records'] as List;
|
||||
if (result.isEmpty) return;
|
||||
final data = result.first;
|
||||
|
||||
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:loopin/IM/im_service.dart';
|
||||
import 'package:loopin/components/network_or_asset_image.dart';
|
||||
import 'package:loopin/models/conversation_type.dart';
|
||||
import 'package:loopin/styles/index.dart';
|
||||
import 'package:loopin/utils/parse_message_summary.dart';
|
||||
import 'package:shirne_dialog/shirne_dialog.dart';
|
||||
@ -20,6 +21,8 @@ class NotificationBanner {
|
||||
name = gpInfo?.groupName ?? "未知群名";
|
||||
avatar = gpInfo?.faceUrl ?? "";
|
||||
} else {
|
||||
logger.e('获取群名称失败');
|
||||
logger.e(msg.toJson());
|
||||
name = '获取群名称失败';
|
||||
}
|
||||
} else {
|
||||
@ -71,18 +74,25 @@ class NotificationBanner {
|
||||
),
|
||||
onTap: (_) async {
|
||||
Get.closeCurrentSnackbar();
|
||||
String? conversationID;
|
||||
if (msg.groupID != null && msg.groupID!.isNotEmpty) {
|
||||
conversationID = 'group_${msg.groupID}';
|
||||
} else if (msg.userID != null && msg.userID!.isNotEmpty) {
|
||||
conversationID = 'c2c_${msg.userID}';
|
||||
// 这里得单独处理一下消息通知
|
||||
bool isGroup = msg.groupID != null && msg.groupID!.isNotEmpty;
|
||||
String id = isGroup ? (msg.groupID ?? '') : (msg.userID ?? '');
|
||||
String conversationID = isGroup ? 'group_$id' : 'c2c_$id';
|
||||
String? router;
|
||||
// 如果是群聊,直接走,不是群聊鉴别一下
|
||||
final cRes = await ImService.instance.getConversation(conversationID: conversationID);
|
||||
if (!isGroup) {
|
||||
// 不是群聊,去匹配是不是系统通知
|
||||
router = conversationTypeFromString(msg.userID); //这里就是解析用于发送消息的管理员的userID
|
||||
}
|
||||
final cRes = await ImService.instance.getConversation(conversationID: conversationID!);
|
||||
if (cRes.success) {
|
||||
if (msg.userID != null) {
|
||||
Get.toNamed('/chat', arguments: cRes.data);
|
||||
} else if (msg.groupID != null) {
|
||||
if (router != null) {
|
||||
// 取对应的系统通知界面
|
||||
Get.toNamed('/$router', arguments: cRes.data);
|
||||
} else if (isGroup) {
|
||||
Get.toNamed('/chatGroup', arguments: cRes.data);
|
||||
} else {
|
||||
Get.toNamed('/chat', arguments: cRes.data);
|
||||
}
|
||||
} else {
|
||||
MyDialog.toast(
|
||||
|
||||
@ -233,6 +233,8 @@ String _parseCustomMessage(V2TimMessage? msg) {
|
||||
|
||||
///系统推广类的先不管了
|
||||
return elment!.desc!;
|
||||
|
||||
// interaction required key={type} value={interactionComment} 对应类型的枚举值
|
||||
case NotifyMessageTypeConstants.interactionComment:
|
||||
// 评论视频
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# In Windows, build-name is used as the major, minor, and patch parts
|
||||
# of the product and file versions while build-number is used as the build suffix.
|
||||
version: 4.1.0+407
|
||||
version: 4.1.1+413
|
||||
|
||||
environment:
|
||||
sdk: ^3.6.0
|
||||
@ -206,6 +206,9 @@ flutter_native_splash:
|
||||
fullscreen: true #隐藏通知栏
|
||||
|
||||
android_12:
|
||||
color: "#000000"
|
||||
color_dark: "#000000"
|
||||
|
||||
image: assets/images/logo/androidlogo.png
|
||||
icon_background_color: "#000000"
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user