修改消息和rtc
This commit is contained in:
parent
1e7261927e
commit
8f95b72fd0
@ -1224,6 +1224,11 @@ class _MessageItem extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
final customData = _customDataFromMessage(message);
|
||||
if (customData != null &&
|
||||
_isDuplicateCpResultMessageForConversation(customData)) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
final cpRelationFormedCard = _cpRelationFormedMessageCard();
|
||||
final cpStatusLineText = _cpStatusLineTextForMessage();
|
||||
return Container(
|
||||
@ -1381,7 +1386,7 @@ class _MessageItem extends StatelessWidget {
|
||||
return GestureDetector(
|
||||
onLongPress: () => _showMsgItemMenu(ct, ""),
|
||||
onTap:
|
||||
() => _showCpInviteDialogFromMessage(data, cpInvite, actionState),
|
||||
() => _openCpInviteDialogFromMessage(data, cpInvite, actionState),
|
||||
child: Container(
|
||||
width: 251.w,
|
||||
height: 64.w,
|
||||
@ -1451,6 +1456,30 @@ class _MessageItem extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
void _openCpInviteDialogFromMessage(
|
||||
Map<String, dynamic> data,
|
||||
SCSystemInvitMessageRes? cpInvite,
|
||||
RoomCpInviteActionState actionState,
|
||||
) {
|
||||
unawaited(_openCpInviteDialogFromMessageAsync(data, cpInvite, actionState));
|
||||
}
|
||||
|
||||
Future<void> _openCpInviteDialogFromMessageAsync(
|
||||
Map<String, dynamic> data,
|
||||
SCSystemInvitMessageRes? cpInvite,
|
||||
RoomCpInviteActionState actionState,
|
||||
) async {
|
||||
final latestState = await _latestCpInviteStateForMessage(data);
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
final resolvedActionState =
|
||||
latestState == _CpInviteMessageState.pending
|
||||
? actionState
|
||||
: _cpInviteActionState(latestState);
|
||||
_showCpInviteDialogFromMessage(data, cpInvite, resolvedActionState);
|
||||
}
|
||||
|
||||
Widget _buildCpInviteGiftThumb(String giftCover) {
|
||||
final child =
|
||||
giftCover.isNotEmpty
|
||||
@ -1623,12 +1652,22 @@ class _MessageItem extends StatelessWidget {
|
||||
return null;
|
||||
}
|
||||
final localizations = SCAppLocalizations.of(context)!;
|
||||
final relationType = _cpRelationTypeFromMessageData(data);
|
||||
if (state == _CpInviteMessageState.expired) {
|
||||
if (relationType != "CP") {
|
||||
return "The ${scCpRelationPossessiveLabel(relationType)} invitation timed out.";
|
||||
}
|
||||
return localizations.closeFriendInviteTimedOut;
|
||||
}
|
||||
if (relationType == "CP") {
|
||||
return _isCurrentUserCpInviter(data)
|
||||
? localizations.otherDeclinedCloseFriendInvite
|
||||
: localizations.youDeclinedCloseFriendInvite;
|
||||
}
|
||||
final relationLabel = scCpRelationPossessiveLabel(relationType);
|
||||
return _isCurrentUserCpInviter(data)
|
||||
? localizations.otherDeclinedCloseFriendInvite
|
||||
: localizations.youDeclinedCloseFriendInvite;
|
||||
? "The other party declined your $relationLabel invitation."
|
||||
: "You declined the other party's $relationLabel invitation.";
|
||||
}
|
||||
|
||||
void _showCpInviteDialogFromMessage(
|
||||
@ -1782,14 +1821,15 @@ class _MessageItem extends StatelessWidget {
|
||||
cpInvite != null &&
|
||||
actionState == RoomCpInviteActionState.pending &&
|
||||
applyId.isNotEmpty
|
||||
? () => _processCpInviteFromMessage(applyId, cpInvite, true)
|
||||
? () => _processCpInviteFromMessage(applyId, cpInvite, true, data)
|
||||
: null,
|
||||
onReject:
|
||||
!isInviter &&
|
||||
cpInvite != null &&
|
||||
actionState == RoomCpInviteActionState.pending &&
|
||||
applyId.isNotEmpty
|
||||
? () => _processCpInviteFromMessage(applyId, cpInvite, false)
|
||||
? () =>
|
||||
_processCpInviteFromMessage(applyId, cpInvite, false, data)
|
||||
: null,
|
||||
);
|
||||
}
|
||||
@ -1798,16 +1838,37 @@ class _MessageItem extends StatelessWidget {
|
||||
String applyId,
|
||||
SCSystemInvitMessageRes invite,
|
||||
bool agree,
|
||||
Map<String, dynamic> data,
|
||||
) {
|
||||
unawaited(_processCpInviteFromMessageAsync(applyId, invite, agree));
|
||||
unawaited(_processCpInviteFromMessageAsync(applyId, invite, agree, data));
|
||||
}
|
||||
|
||||
Future<void> _processCpInviteFromMessageAsync(
|
||||
String applyId,
|
||||
SCSystemInvitMessageRes invite,
|
||||
bool agree,
|
||||
Map<String, dynamic> data,
|
||||
) async {
|
||||
_cpMessageLog('process applyId=$applyId agree=$agree');
|
||||
final latestState = await _latestCpInviteStateForMessage(data);
|
||||
if (latestState != _CpInviteMessageState.pending) {
|
||||
_cpMessageLog(
|
||||
'skip process applyId=$applyId agree=$agree latestState=$latestState',
|
||||
);
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
_showCpInviteDialogFromMessage(
|
||||
data,
|
||||
invite,
|
||||
_cpInviteActionState(latestState),
|
||||
);
|
||||
updateCall();
|
||||
return;
|
||||
}
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
final profileManager = Provider.of<SocialChatUserProfileManager>(
|
||||
context,
|
||||
listen: false,
|
||||
@ -1821,6 +1882,9 @@ class _MessageItem extends StatelessWidget {
|
||||
_cpMessageLog('process failed applyId=$applyId agree=$agree');
|
||||
return;
|
||||
}
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
SmartDialog.dismiss(tag: RoomCpInviteDialog.dialogTag);
|
||||
_cpMessageLog(
|
||||
'process submitted applyId=$applyId agree=$agree '
|
||||
@ -1830,6 +1894,58 @@ class _MessageItem extends StatelessWidget {
|
||||
updateCall();
|
||||
}
|
||||
|
||||
Future<_CpInviteMessageState> _latestCpInviteStateForMessage(
|
||||
Map<String, dynamic> data,
|
||||
) async {
|
||||
final localState = _cpInviteStateForMessage(data);
|
||||
if (localState != _CpInviteMessageState.pending) {
|
||||
return localState;
|
||||
}
|
||||
final applyId = _cpApplyIdFromData(data);
|
||||
if (applyId.isEmpty) {
|
||||
return localState;
|
||||
}
|
||||
try {
|
||||
final status = await SCAccountRepository().cpRelationshipApplyStatus(
|
||||
applyId,
|
||||
);
|
||||
final backendState = _cpInviteStateFromBackendStatus(status);
|
||||
if (backendState != null) {
|
||||
return backendState;
|
||||
}
|
||||
} catch (error) {
|
||||
_cpMessageLog('query apply status failed applyId=$applyId error=$error');
|
||||
}
|
||||
return _cpInviteSecondsLeft(data) <= 0
|
||||
? _CpInviteMessageState.expired
|
||||
: localState;
|
||||
}
|
||||
|
||||
_CpInviteMessageState? _cpInviteStateFromBackendStatus(String? status) {
|
||||
final text = status?.trim().toUpperCase() ?? "";
|
||||
if (text.isEmpty || text == "WAIT" || text == "WAITING") {
|
||||
return text.isEmpty ? null : _CpInviteMessageState.pending;
|
||||
}
|
||||
if (text.contains("EXPIRE") ||
|
||||
text.contains("TIMEOUT") ||
|
||||
text.contains("OVERDUE")) {
|
||||
return _CpInviteMessageState.expired;
|
||||
}
|
||||
if (text.contains("REFUSE") ||
|
||||
text.contains("REJECT") ||
|
||||
text.contains("DECLIN") ||
|
||||
text.contains("DENY")) {
|
||||
return _CpInviteMessageState.rejected;
|
||||
}
|
||||
if (text.contains("AGREE") ||
|
||||
text.contains("ACCEPT") ||
|
||||
text.contains("APPROVE") ||
|
||||
text.contains("ESTABLISH")) {
|
||||
return _CpInviteMessageState.accepted;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<String, dynamic>? _customDataFromMessage(V2TimMessage msg) {
|
||||
if (msg.elemType != MessageElemType.V2TIM_ELEM_TYPE_CUSTOM) {
|
||||
return null;
|
||||
@ -1891,6 +2007,60 @@ class _MessageItem extends StatelessWidget {
|
||||
return _CpInviteMessageState.pending;
|
||||
}
|
||||
|
||||
bool _isDuplicateCpResultMessageForConversation(Map<String, dynamic> data) {
|
||||
final currentKey = _cpResultMessageDedupKey(data);
|
||||
if (currentKey.isEmpty) {
|
||||
return false;
|
||||
}
|
||||
final currentIndex = currentConversationMessageList.indexWhere(
|
||||
_isCurrentConversationMessage,
|
||||
);
|
||||
if (currentIndex <= 0) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0; i < currentIndex; i++) {
|
||||
final otherData = _customDataFromMessage(
|
||||
currentConversationMessageList[i],
|
||||
);
|
||||
if (otherData == null) {
|
||||
continue;
|
||||
}
|
||||
if (_cpResultMessageDedupKey(otherData) == currentKey) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool _isCurrentConversationMessage(V2TimMessage item) {
|
||||
final currentMsgId = message.msgID?.trim() ?? "";
|
||||
final itemMsgId = item.msgID?.trim() ?? "";
|
||||
if (currentMsgId.isNotEmpty && itemMsgId.isNotEmpty) {
|
||||
return currentMsgId == itemMsgId;
|
||||
}
|
||||
final currentSeq = message.seq?.trim() ?? "";
|
||||
final itemSeq = item.seq?.trim() ?? "";
|
||||
if (currentSeq.isNotEmpty && itemSeq.isNotEmpty) {
|
||||
return currentSeq == itemSeq && item.timestamp == message.timestamp;
|
||||
}
|
||||
return identical(item, message);
|
||||
}
|
||||
|
||||
String _cpResultMessageDedupKey(Map<String, dynamic> data) {
|
||||
if (!_isCpInvitePayload(data)) {
|
||||
return "";
|
||||
}
|
||||
final state = _cpInviteStateFromData(data);
|
||||
if (state == _CpInviteMessageState.pending) {
|
||||
return "";
|
||||
}
|
||||
final applyId = _cpApplyIdFromData(data);
|
||||
if (applyId.isEmpty) {
|
||||
return "";
|
||||
}
|
||||
return "$applyId|${state.name}";
|
||||
}
|
||||
|
||||
_CpInviteMessageState _cpInviteStateFromData(Map<String, dynamic> data) {
|
||||
final content = _cpContentMap(data);
|
||||
final values = <String>[
|
||||
@ -2145,6 +2315,20 @@ class _MessageItem extends StatelessWidget {
|
||||
], fallback: "");
|
||||
}
|
||||
|
||||
String _cpRelationTypeFromMessageData(Map<String, dynamic> data) {
|
||||
final invite = _cpInviteFromMessageData(data);
|
||||
final content = _cpContentMap(data);
|
||||
return scNormalizeCpRelationType(
|
||||
_firstNonBlankString([
|
||||
invite?.relationType,
|
||||
data["relationType"]?.toString(),
|
||||
data["relation_type"]?.toString(),
|
||||
content["relationType"]?.toString(),
|
||||
content["relation_type"]?.toString(),
|
||||
], fallback: "CP"),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _cpContentMap(Map<String, dynamic> data) {
|
||||
final content = data["content"];
|
||||
try {
|
||||
|
||||
@ -458,7 +458,7 @@ class _MessageItem extends StatelessWidget {
|
||||
showMsgItemMenu(ct, "");
|
||||
},
|
||||
onTap: () {
|
||||
_showCpInviteDialogFromMessage(data, cpInvite, actionState);
|
||||
_openCpInviteDialogFromMessage(data, cpInvite, actionState);
|
||||
},
|
||||
child: Container(
|
||||
width: 251.w,
|
||||
@ -529,6 +529,30 @@ class _MessageItem extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
void _openCpInviteDialogFromMessage(
|
||||
Map<String, dynamic> data,
|
||||
SCSystemInvitMessageRes? cpInvite,
|
||||
RoomCpInviteActionState actionState,
|
||||
) {
|
||||
unawaited(_openCpInviteDialogFromMessageAsync(data, cpInvite, actionState));
|
||||
}
|
||||
|
||||
Future<void> _openCpInviteDialogFromMessageAsync(
|
||||
Map<String, dynamic> data,
|
||||
SCSystemInvitMessageRes? cpInvite,
|
||||
RoomCpInviteActionState actionState,
|
||||
) async {
|
||||
final latestState = await _latestCpInviteStateForMessage(data);
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
final resolvedActionState =
|
||||
latestState == _CpInviteMessageState.pending
|
||||
? actionState
|
||||
: _cpInviteActionState(latestState);
|
||||
_showCpInviteDialogFromMessage(data, cpInvite, resolvedActionState);
|
||||
}
|
||||
|
||||
Widget _buildCpInviteGiftThumb(String giftCover) {
|
||||
final child =
|
||||
giftCover.isNotEmpty
|
||||
@ -788,6 +812,7 @@ class _MessageItem extends StatelessWidget {
|
||||
applyId,
|
||||
SCSysytemMessageType.CP_BUILD.name,
|
||||
cpInvite: cpInvite,
|
||||
cpData: data,
|
||||
)
|
||||
: null,
|
||||
onReject:
|
||||
@ -798,6 +823,7 @@ class _MessageItem extends StatelessWidget {
|
||||
applyId,
|
||||
SCSysytemMessageType.CP_BUILD.name,
|
||||
cpInvite: cpInvite,
|
||||
cpData: data,
|
||||
)
|
||||
: null,
|
||||
);
|
||||
@ -856,6 +882,56 @@ class _MessageItem extends StatelessWidget {
|
||||
: _CpInviteMessageState.pending;
|
||||
}
|
||||
|
||||
Future<_CpInviteMessageState> _latestCpInviteStateForMessage(
|
||||
Map<String, dynamic> data,
|
||||
) async {
|
||||
final localState = _cpInviteStateForMessage(data);
|
||||
if (localState != _CpInviteMessageState.pending) {
|
||||
return localState;
|
||||
}
|
||||
final applyId = _cpApplyIdFromData(data);
|
||||
if (applyId.isEmpty) {
|
||||
return localState;
|
||||
}
|
||||
try {
|
||||
final status = await SCAccountRepository().cpRelationshipApplyStatus(
|
||||
applyId,
|
||||
);
|
||||
final backendState = _cpInviteStateFromBackendStatus(status);
|
||||
if (backendState != null) {
|
||||
return backendState;
|
||||
}
|
||||
} catch (_) {}
|
||||
return _cpInviteSecondsLeft(data) <= 0
|
||||
? _CpInviteMessageState.expired
|
||||
: localState;
|
||||
}
|
||||
|
||||
_CpInviteMessageState? _cpInviteStateFromBackendStatus(String? status) {
|
||||
final text = status?.trim().toUpperCase() ?? "";
|
||||
if (text.isEmpty || text == "WAIT" || text == "WAITING") {
|
||||
return text.isEmpty ? null : _CpInviteMessageState.pending;
|
||||
}
|
||||
if (text.contains("EXPIRE") ||
|
||||
text.contains("TIMEOUT") ||
|
||||
text.contains("OVERDUE")) {
|
||||
return _CpInviteMessageState.expired;
|
||||
}
|
||||
if (text.contains("REFUSE") ||
|
||||
text.contains("REJECT") ||
|
||||
text.contains("DECLIN") ||
|
||||
text.contains("DENY")) {
|
||||
return _CpInviteMessageState.rejected;
|
||||
}
|
||||
if (text.contains("AGREE") ||
|
||||
text.contains("ACCEPT") ||
|
||||
text.contains("APPROVE") ||
|
||||
text.contains("ESTABLISH")) {
|
||||
return _CpInviteMessageState.accepted;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
_CpInviteMessageState _cpInviteStateFromConversation(
|
||||
Map<String, dynamic> currentData,
|
||||
) {
|
||||
@ -1863,7 +1939,14 @@ class _MessageItem extends StatelessWidget {
|
||||
Future<void> _acceptCpInviteDirect(
|
||||
String id,
|
||||
SCSystemInvitMessageRes? cpInvite,
|
||||
Map<String, dynamic>? cpData,
|
||||
) async {
|
||||
if (!await _shouldProcessCpInvite(id, cpInvite, cpData)) {
|
||||
return;
|
||||
}
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
final profileManager = Provider.of<SocialChatUserProfileManager>(
|
||||
context,
|
||||
listen: false,
|
||||
@ -1882,7 +1965,14 @@ class _MessageItem extends StatelessWidget {
|
||||
Future<void> _rejectCpInviteDirect(
|
||||
String id,
|
||||
SCSystemInvitMessageRes? cpInvite,
|
||||
Map<String, dynamic>? cpData,
|
||||
) async {
|
||||
if (!await _shouldProcessCpInvite(id, cpInvite, cpData)) {
|
||||
return;
|
||||
}
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
final profileManager = Provider.of<SocialChatUserProfileManager>(
|
||||
context,
|
||||
listen: false,
|
||||
@ -1898,9 +1988,62 @@ class _MessageItem extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
void acceptOpt(String id, String type, {SCSystemInvitMessageRes? cpInvite}) {
|
||||
Future<bool> _shouldProcessCpInvite(
|
||||
String applyId,
|
||||
SCSystemInvitMessageRes? cpInvite,
|
||||
Map<String, dynamic>? data,
|
||||
) async {
|
||||
final latestState =
|
||||
data == null
|
||||
? await _latestCpInviteStateForApplyId(applyId)
|
||||
: await _latestCpInviteStateForMessage(data);
|
||||
if (latestState == _CpInviteMessageState.pending) {
|
||||
return true;
|
||||
}
|
||||
if (!context.mounted) {
|
||||
return false;
|
||||
}
|
||||
if (data != null) {
|
||||
_showCpInviteDialogFromMessage(
|
||||
data,
|
||||
cpInvite,
|
||||
_cpInviteActionState(latestState),
|
||||
);
|
||||
} else {
|
||||
SmartDialog.dismiss(tag: RoomCpInviteDialog.dialogTag);
|
||||
if (latestState == _CpInviteMessageState.expired) {
|
||||
SCTts.show(SCAppLocalizations.of(context)!.closeFriendInviteTimedOut);
|
||||
}
|
||||
}
|
||||
updateCall();
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<_CpInviteMessageState> _latestCpInviteStateForApplyId(
|
||||
String applyId,
|
||||
) async {
|
||||
if (applyId.trim().isEmpty) {
|
||||
return _CpInviteMessageState.pending;
|
||||
}
|
||||
try {
|
||||
final status = await SCAccountRepository().cpRelationshipApplyStatus(
|
||||
applyId,
|
||||
);
|
||||
return _cpInviteStateFromBackendStatus(status) ??
|
||||
_CpInviteMessageState.pending;
|
||||
} catch (_) {
|
||||
return _CpInviteMessageState.pending;
|
||||
}
|
||||
}
|
||||
|
||||
void acceptOpt(
|
||||
String id,
|
||||
String type, {
|
||||
SCSystemInvitMessageRes? cpInvite,
|
||||
Map<String, dynamic>? cpData,
|
||||
}) {
|
||||
if (type == SCSysytemMessageType.CP_BUILD.name) {
|
||||
unawaited(_acceptCpInviteDirect(id, cpInvite));
|
||||
unawaited(_acceptCpInviteDirect(id, cpInvite, cpData));
|
||||
return;
|
||||
}
|
||||
SmartDialog.show(
|
||||
@ -1948,9 +2091,14 @@ class _MessageItem extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
void rejectOpt(String id, String type, {SCSystemInvitMessageRes? cpInvite}) {
|
||||
void rejectOpt(
|
||||
String id,
|
||||
String type, {
|
||||
SCSystemInvitMessageRes? cpInvite,
|
||||
Map<String, dynamic>? cpData,
|
||||
}) {
|
||||
if (type == SCSysytemMessageType.CP_BUILD.name) {
|
||||
unawaited(_rejectCpInviteDirect(id, cpInvite));
|
||||
unawaited(_rejectCpInviteDirect(id, cpInvite, cpData));
|
||||
return;
|
||||
}
|
||||
SmartDialog.show(
|
||||
|
||||
@ -434,8 +434,10 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
.addConversationListener(
|
||||
listener: V2TimConversationListener(
|
||||
onNewConversation: (conversationList) {
|
||||
// _onRefreshConversation(conversationList);
|
||||
initConversation();
|
||||
_onRefreshConversation(conversationList);
|
||||
},
|
||||
onConversationChanged: (conversationList) {
|
||||
_onRefreshConversation(conversationList);
|
||||
},
|
||||
onTotalUnreadMessageCountChanged: (int totalUnreadCount) {
|
||||
messageUnReadCount = totalUnreadCount;
|
||||
@ -605,7 +607,11 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
conversationMap.clear();
|
||||
if (conversationList != null) {
|
||||
for (V2TimConversation? conversation in conversationList) {
|
||||
conversationMap[conversation!.conversationID] = conversation;
|
||||
if (conversation == null) {
|
||||
continue;
|
||||
}
|
||||
conversationMap[conversation.conversationID] = conversation;
|
||||
_handleCpBuildFromConversation(conversation);
|
||||
}
|
||||
}
|
||||
getConversationList();
|
||||
@ -853,6 +859,13 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
final relationNoticePeerId = _cpRelationNoticePeerIdFromData(
|
||||
data,
|
||||
message: message,
|
||||
);
|
||||
if (relationNoticePeerId != null) {
|
||||
return relationNoticePeerId;
|
||||
}
|
||||
final invite = _cpInviteFromMessageData(data);
|
||||
final currentProfile = AccountStorage().getCurrentUser()?.userProfile;
|
||||
if (invite == null || currentProfile == null) {
|
||||
@ -930,6 +943,9 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
if (_handleCpInviteResultMessage(data, msgId: message?.msgID)) {
|
||||
return;
|
||||
}
|
||||
if (_handleCpRelationRefreshNoticeMessage(data, message: message)) {
|
||||
return;
|
||||
}
|
||||
if (noticeType != SCSysytemMessageType.CP_BUILD.name) {
|
||||
return;
|
||||
}
|
||||
@ -1241,6 +1257,47 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _handleCpRelationRefreshNoticeMessage(
|
||||
Map<String, dynamic> data, {
|
||||
V2TimMessage? message,
|
||||
}) {
|
||||
final noticeType = _cpRelationNoticeTypeFromData(data);
|
||||
if (!_isCpRelationRefreshNoticeType(noticeType)) {
|
||||
return false;
|
||||
}
|
||||
_cpInviteLog(
|
||||
'handle CP relation refresh notice noticeType=$noticeType raw=$data',
|
||||
);
|
||||
final context = navigatorKey.currentState?.context;
|
||||
if (context != null) {
|
||||
unawaited(
|
||||
Provider.of<SocialChatUserProfileManager>(
|
||||
context,
|
||||
listen: false,
|
||||
).refreshLoadedCpProfiles(),
|
||||
);
|
||||
if (noticeType == SCSysytemMessageType.CP_DISMISS.name) {
|
||||
final currentUserId =
|
||||
AccountStorage().getCurrentUser()?.userProfile?.id?.trim() ?? "";
|
||||
final peerUserId = _cpRelationNoticePeerIdFromData(
|
||||
data,
|
||||
message: message,
|
||||
);
|
||||
if (currentUserId.isNotEmpty && peerUserId != null) {
|
||||
Provider.of<RtcProvider?>(
|
||||
context,
|
||||
listen: false,
|
||||
)?.invalidateRoomMicRelationBetween(
|
||||
userId: currentUserId,
|
||||
peerUserId: peerUserId,
|
||||
relationType: _cpRelationTypeFromNoticeData(data),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<void> _showCpInviteResultDialog({
|
||||
required BuildContext context,
|
||||
required Map<String, dynamic> data,
|
||||
@ -2039,13 +2096,88 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
content["type"]?.toString(),
|
||||
])?.toUpperCase() ??
|
||||
"";
|
||||
if (noticeType == SCSysytemMessageType.CP_BUILD.name) {
|
||||
if (noticeType == SCSysytemMessageType.CP_BUILD.name ||
|
||||
_isCpRelationRefreshNoticeType(noticeType)) {
|
||||
return true;
|
||||
}
|
||||
return _cpInviteApplyIdFromData(data).isNotEmpty &&
|
||||
_cpInviteResultFromMessageData(data) != null;
|
||||
}
|
||||
|
||||
String _cpRelationNoticeTypeFromData(Map<String, dynamic> data) {
|
||||
final content = _cpInviteContentMap(data);
|
||||
return (_firstCpInviteValue([
|
||||
data["noticeType"]?.toString(),
|
||||
data["type"]?.toString(),
|
||||
content["noticeType"]?.toString(),
|
||||
content["type"]?.toString(),
|
||||
]) ??
|
||||
"")
|
||||
.toUpperCase();
|
||||
}
|
||||
|
||||
bool _isCpRelationRefreshNoticeType(String noticeType) {
|
||||
return noticeType == SCSysytemMessageType.CP_DISMISS.name ||
|
||||
noticeType == SCSysytemMessageType.CP_BLESS.name;
|
||||
}
|
||||
|
||||
String _cpRelationTypeFromNoticeData(Map<String, dynamic> data) {
|
||||
final content = _cpInviteContentMap(data);
|
||||
return scNormalizeCpRelationType(
|
||||
_firstCpInviteValue([
|
||||
data["relationType"]?.toString(),
|
||||
data["relation_type"]?.toString(),
|
||||
content["relationType"]?.toString(),
|
||||
content["relation_type"]?.toString(),
|
||||
]) ??
|
||||
"CP",
|
||||
);
|
||||
}
|
||||
|
||||
String? _cpRelationNoticePeerIdFromData(
|
||||
Map<String, dynamic> data, {
|
||||
V2TimMessage? message,
|
||||
}) {
|
||||
if (!_isCpRelationRefreshNoticeType(_cpRelationNoticeTypeFromData(data))) {
|
||||
return null;
|
||||
}
|
||||
final content = _cpInviteContentMap(data);
|
||||
final currentProfile = AccountStorage().getCurrentUser()?.userProfile;
|
||||
final currentIds =
|
||||
[currentProfile?.id, currentProfile?.account]
|
||||
.map((value) => value?.trim() ?? "")
|
||||
.where((value) => value.isNotEmpty)
|
||||
.toSet();
|
||||
final candidates = <String?>[
|
||||
data["expand"]?.toString(),
|
||||
content["expand"]?.toString(),
|
||||
data["peerUserId"]?.toString(),
|
||||
data["cpUserId"]?.toString(),
|
||||
data["targetUserId"]?.toString(),
|
||||
data["senderUserId"]?.toString(),
|
||||
data["fromUserId"]?.toString(),
|
||||
data["userId"]?.toString(),
|
||||
content["peerUserId"]?.toString(),
|
||||
content["cpUserId"]?.toString(),
|
||||
content["targetUserId"]?.toString(),
|
||||
content["senderUserId"]?.toString(),
|
||||
content["fromUserId"]?.toString(),
|
||||
content["userId"]?.toString(),
|
||||
message?.sender,
|
||||
message?.userID,
|
||||
];
|
||||
for (final candidate in candidates) {
|
||||
final userId = candidate?.trim() ?? "";
|
||||
if (userId.isEmpty ||
|
||||
currentIds.contains(userId) ||
|
||||
!scLooksLikeBackendUserId(userId)) {
|
||||
continue;
|
||||
}
|
||||
return userId;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void _cpInviteLog(String message) {
|
||||
debugPrint('[CP][Invite] $message');
|
||||
}
|
||||
@ -2053,10 +2185,23 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
void _onRefreshConversation(List<V2TimConversation> conversations) {
|
||||
for (V2TimConversation conversation in conversations) {
|
||||
conversationMap[conversation.conversationID] = conversation;
|
||||
_handleCpBuildFromConversation(conversation);
|
||||
}
|
||||
getConversationList();
|
||||
}
|
||||
|
||||
void _handleCpBuildFromConversation(V2TimConversation conversation) {
|
||||
final message = conversation.lastMessage;
|
||||
if (message == null || message.groupID != null) {
|
||||
return;
|
||||
}
|
||||
final data = _decodeCpSystemMessageData(message);
|
||||
if (!_isCpRelationInviteNoticeData(data)) {
|
||||
return;
|
||||
}
|
||||
unawaited(_handleIncomingCpBuildMessage(message));
|
||||
}
|
||||
|
||||
///创建房间im群聊
|
||||
Future<V2TimValueCallback<String>> createRoomGroup(
|
||||
String groupID,
|
||||
|
||||
@ -178,22 +178,28 @@ class SocialChatUserProfileManager extends ChangeNotifier {
|
||||
if (userId.trim().isEmpty) {
|
||||
return profile;
|
||||
}
|
||||
final cpPairs = <CPRes>[];
|
||||
final closeFriendPairs = <CPRes>[];
|
||||
final fallbackCpPairs = <CPRes>[];
|
||||
final fallbackCloseFriendPairs = <CPRes>[];
|
||||
_addCpRelationPairs(
|
||||
cpPairs: cpPairs,
|
||||
closeFriendPairs: closeFriendPairs,
|
||||
cpPairs: fallbackCpPairs,
|
||||
closeFriendPairs: fallbackCloseFriendPairs,
|
||||
relations: profile.cpList,
|
||||
fallbackRelationType: 'CP',
|
||||
);
|
||||
_addCpRelationPairs(
|
||||
cpPairs: cpPairs,
|
||||
closeFriendPairs: closeFriendPairs,
|
||||
cpPairs: fallbackCpPairs,
|
||||
closeFriendPairs: fallbackCloseFriendPairs,
|
||||
relations: profile.closeFriendList,
|
||||
);
|
||||
final cpPairs = <CPRes>[];
|
||||
final closeFriendPairs = <CPRes>[];
|
||||
var loadedAnyCabin = false;
|
||||
await Future.wait(
|
||||
_cpProfileRelationTypes.map((relationType) async {
|
||||
final cabin = await _safeLoadCpCabin(userId, relationType);
|
||||
if (cabin != null) {
|
||||
loadedAnyCabin = true;
|
||||
}
|
||||
final cpPair = cabin?.cpPairUserProfileCO;
|
||||
if (cpPair == null || !_hasCpPair(cpPair)) {
|
||||
return;
|
||||
@ -231,6 +237,12 @@ class SocialChatUserProfileManager extends ChangeNotifier {
|
||||
'closeFriends=${closeFriendPairs.length}',
|
||||
);
|
||||
}
|
||||
if (!loadedAnyCabin) {
|
||||
return profile.copyWith(
|
||||
cpList: fallbackCpPairs,
|
||||
closeFriendList: fallbackCloseFriendPairs,
|
||||
);
|
||||
}
|
||||
return profile.copyWith(
|
||||
cpList: cpPairs,
|
||||
closeFriendList: closeFriendPairs,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user