Compare commits
No commits in common. "f8e13f31ba70ea758265268d54384975cffa8089" and "bc3cbabfd11ead50b3a0d89b70921d26f4a433d5" have entirely different histories.
f8e13f31ba
...
bc3cbabfd1
@ -1224,11 +1224,6 @@ class _MessageItem extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
final customData = _customDataFromMessage(message);
|
|
||||||
if (customData != null &&
|
|
||||||
_isDuplicateCpResultMessageForConversation(customData)) {
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
}
|
|
||||||
final cpRelationFormedCard = _cpRelationFormedMessageCard();
|
final cpRelationFormedCard = _cpRelationFormedMessageCard();
|
||||||
final cpStatusLineText = _cpStatusLineTextForMessage();
|
final cpStatusLineText = _cpStatusLineTextForMessage();
|
||||||
return Container(
|
return Container(
|
||||||
@ -1386,7 +1381,7 @@ class _MessageItem extends StatelessWidget {
|
|||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onLongPress: () => _showMsgItemMenu(ct, ""),
|
onLongPress: () => _showMsgItemMenu(ct, ""),
|
||||||
onTap:
|
onTap:
|
||||||
() => _openCpInviteDialogFromMessage(data, cpInvite, actionState),
|
() => _showCpInviteDialogFromMessage(data, cpInvite, actionState),
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 251.w,
|
width: 251.w,
|
||||||
height: 64.w,
|
height: 64.w,
|
||||||
@ -1456,30 +1451,6 @@ 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) {
|
Widget _buildCpInviteGiftThumb(String giftCover) {
|
||||||
final child =
|
final child =
|
||||||
giftCover.isNotEmpty
|
giftCover.isNotEmpty
|
||||||
@ -1652,22 +1623,12 @@ class _MessageItem extends StatelessWidget {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final localizations = SCAppLocalizations.of(context)!;
|
final localizations = SCAppLocalizations.of(context)!;
|
||||||
final relationType = _cpRelationTypeFromMessageData(data);
|
|
||||||
if (state == _CpInviteMessageState.expired) {
|
if (state == _CpInviteMessageState.expired) {
|
||||||
if (relationType != "CP") {
|
|
||||||
return "The ${scCpRelationPossessiveLabel(relationType)} invitation timed out.";
|
|
||||||
}
|
|
||||||
return localizations.closeFriendInviteTimedOut;
|
return localizations.closeFriendInviteTimedOut;
|
||||||
}
|
}
|
||||||
if (relationType == "CP") {
|
|
||||||
return _isCurrentUserCpInviter(data)
|
|
||||||
? localizations.otherDeclinedCloseFriendInvite
|
|
||||||
: localizations.youDeclinedCloseFriendInvite;
|
|
||||||
}
|
|
||||||
final relationLabel = scCpRelationPossessiveLabel(relationType);
|
|
||||||
return _isCurrentUserCpInviter(data)
|
return _isCurrentUserCpInviter(data)
|
||||||
? "The other party declined your $relationLabel invitation."
|
? localizations.otherDeclinedCloseFriendInvite
|
||||||
: "You declined the other party's $relationLabel invitation.";
|
: localizations.youDeclinedCloseFriendInvite;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showCpInviteDialogFromMessage(
|
void _showCpInviteDialogFromMessage(
|
||||||
@ -1821,15 +1782,14 @@ class _MessageItem extends StatelessWidget {
|
|||||||
cpInvite != null &&
|
cpInvite != null &&
|
||||||
actionState == RoomCpInviteActionState.pending &&
|
actionState == RoomCpInviteActionState.pending &&
|
||||||
applyId.isNotEmpty
|
applyId.isNotEmpty
|
||||||
? () => _processCpInviteFromMessage(applyId, cpInvite, true, data)
|
? () => _processCpInviteFromMessage(applyId, cpInvite, true)
|
||||||
: null,
|
: null,
|
||||||
onReject:
|
onReject:
|
||||||
!isInviter &&
|
!isInviter &&
|
||||||
cpInvite != null &&
|
cpInvite != null &&
|
||||||
actionState == RoomCpInviteActionState.pending &&
|
actionState == RoomCpInviteActionState.pending &&
|
||||||
applyId.isNotEmpty
|
applyId.isNotEmpty
|
||||||
? () =>
|
? () => _processCpInviteFromMessage(applyId, cpInvite, false)
|
||||||
_processCpInviteFromMessage(applyId, cpInvite, false, data)
|
|
||||||
: null,
|
: null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1838,37 +1798,16 @@ class _MessageItem extends StatelessWidget {
|
|||||||
String applyId,
|
String applyId,
|
||||||
SCSystemInvitMessageRes invite,
|
SCSystemInvitMessageRes invite,
|
||||||
bool agree,
|
bool agree,
|
||||||
Map<String, dynamic> data,
|
|
||||||
) {
|
) {
|
||||||
unawaited(_processCpInviteFromMessageAsync(applyId, invite, agree, data));
|
unawaited(_processCpInviteFromMessageAsync(applyId, invite, agree));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _processCpInviteFromMessageAsync(
|
Future<void> _processCpInviteFromMessageAsync(
|
||||||
String applyId,
|
String applyId,
|
||||||
SCSystemInvitMessageRes invite,
|
SCSystemInvitMessageRes invite,
|
||||||
bool agree,
|
bool agree,
|
||||||
Map<String, dynamic> data,
|
|
||||||
) async {
|
) async {
|
||||||
_cpMessageLog('process applyId=$applyId agree=$agree');
|
_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>(
|
final profileManager = Provider.of<SocialChatUserProfileManager>(
|
||||||
context,
|
context,
|
||||||
listen: false,
|
listen: false,
|
||||||
@ -1882,9 +1821,6 @@ class _MessageItem extends StatelessWidget {
|
|||||||
_cpMessageLog('process failed applyId=$applyId agree=$agree');
|
_cpMessageLog('process failed applyId=$applyId agree=$agree');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!context.mounted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SmartDialog.dismiss(tag: RoomCpInviteDialog.dialogTag);
|
SmartDialog.dismiss(tag: RoomCpInviteDialog.dialogTag);
|
||||||
_cpMessageLog(
|
_cpMessageLog(
|
||||||
'process submitted applyId=$applyId agree=$agree '
|
'process submitted applyId=$applyId agree=$agree '
|
||||||
@ -1894,58 +1830,6 @@ class _MessageItem extends StatelessWidget {
|
|||||||
updateCall();
|
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) {
|
Map<String, dynamic>? _customDataFromMessage(V2TimMessage msg) {
|
||||||
if (msg.elemType != MessageElemType.V2TIM_ELEM_TYPE_CUSTOM) {
|
if (msg.elemType != MessageElemType.V2TIM_ELEM_TYPE_CUSTOM) {
|
||||||
return null;
|
return null;
|
||||||
@ -2007,60 +1891,6 @@ class _MessageItem extends StatelessWidget {
|
|||||||
return _CpInviteMessageState.pending;
|
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) {
|
_CpInviteMessageState _cpInviteStateFromData(Map<String, dynamic> data) {
|
||||||
final content = _cpContentMap(data);
|
final content = _cpContentMap(data);
|
||||||
final values = <String>[
|
final values = <String>[
|
||||||
@ -2315,20 +2145,6 @@ class _MessageItem extends StatelessWidget {
|
|||||||
], fallback: "");
|
], 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) {
|
Map<String, dynamic> _cpContentMap(Map<String, dynamic> data) {
|
||||||
final content = data["content"];
|
final content = data["content"];
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -458,7 +458,7 @@ class _MessageItem extends StatelessWidget {
|
|||||||
showMsgItemMenu(ct, "");
|
showMsgItemMenu(ct, "");
|
||||||
},
|
},
|
||||||
onTap: () {
|
onTap: () {
|
||||||
_openCpInviteDialogFromMessage(data, cpInvite, actionState);
|
_showCpInviteDialogFromMessage(data, cpInvite, actionState);
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 251.w,
|
width: 251.w,
|
||||||
@ -529,30 +529,6 @@ 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) {
|
Widget _buildCpInviteGiftThumb(String giftCover) {
|
||||||
final child =
|
final child =
|
||||||
giftCover.isNotEmpty
|
giftCover.isNotEmpty
|
||||||
@ -812,7 +788,6 @@ class _MessageItem extends StatelessWidget {
|
|||||||
applyId,
|
applyId,
|
||||||
SCSysytemMessageType.CP_BUILD.name,
|
SCSysytemMessageType.CP_BUILD.name,
|
||||||
cpInvite: cpInvite,
|
cpInvite: cpInvite,
|
||||||
cpData: data,
|
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
onReject:
|
onReject:
|
||||||
@ -823,7 +798,6 @@ class _MessageItem extends StatelessWidget {
|
|||||||
applyId,
|
applyId,
|
||||||
SCSysytemMessageType.CP_BUILD.name,
|
SCSysytemMessageType.CP_BUILD.name,
|
||||||
cpInvite: cpInvite,
|
cpInvite: cpInvite,
|
||||||
cpData: data,
|
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
);
|
);
|
||||||
@ -882,56 +856,6 @@ class _MessageItem extends StatelessWidget {
|
|||||||
: _CpInviteMessageState.pending;
|
: _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(
|
_CpInviteMessageState _cpInviteStateFromConversation(
|
||||||
Map<String, dynamic> currentData,
|
Map<String, dynamic> currentData,
|
||||||
) {
|
) {
|
||||||
@ -1939,14 +1863,7 @@ class _MessageItem extends StatelessWidget {
|
|||||||
Future<void> _acceptCpInviteDirect(
|
Future<void> _acceptCpInviteDirect(
|
||||||
String id,
|
String id,
|
||||||
SCSystemInvitMessageRes? cpInvite,
|
SCSystemInvitMessageRes? cpInvite,
|
||||||
Map<String, dynamic>? cpData,
|
|
||||||
) async {
|
) async {
|
||||||
if (!await _shouldProcessCpInvite(id, cpInvite, cpData)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!context.mounted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final profileManager = Provider.of<SocialChatUserProfileManager>(
|
final profileManager = Provider.of<SocialChatUserProfileManager>(
|
||||||
context,
|
context,
|
||||||
listen: false,
|
listen: false,
|
||||||
@ -1965,14 +1882,7 @@ class _MessageItem extends StatelessWidget {
|
|||||||
Future<void> _rejectCpInviteDirect(
|
Future<void> _rejectCpInviteDirect(
|
||||||
String id,
|
String id,
|
||||||
SCSystemInvitMessageRes? cpInvite,
|
SCSystemInvitMessageRes? cpInvite,
|
||||||
Map<String, dynamic>? cpData,
|
|
||||||
) async {
|
) async {
|
||||||
if (!await _shouldProcessCpInvite(id, cpInvite, cpData)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!context.mounted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final profileManager = Provider.of<SocialChatUserProfileManager>(
|
final profileManager = Provider.of<SocialChatUserProfileManager>(
|
||||||
context,
|
context,
|
||||||
listen: false,
|
listen: false,
|
||||||
@ -1988,62 +1898,9 @@ class _MessageItem extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> _shouldProcessCpInvite(
|
void acceptOpt(String id, String type, {SCSystemInvitMessageRes? cpInvite}) {
|
||||||
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) {
|
if (type == SCSysytemMessageType.CP_BUILD.name) {
|
||||||
unawaited(_acceptCpInviteDirect(id, cpInvite, cpData));
|
unawaited(_acceptCpInviteDirect(id, cpInvite));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SmartDialog.show(
|
SmartDialog.show(
|
||||||
@ -2091,14 +1948,9 @@ class _MessageItem extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rejectOpt(
|
void rejectOpt(String id, String type, {SCSystemInvitMessageRes? cpInvite}) {
|
||||||
String id,
|
|
||||||
String type, {
|
|
||||||
SCSystemInvitMessageRes? cpInvite,
|
|
||||||
Map<String, dynamic>? cpData,
|
|
||||||
}) {
|
|
||||||
if (type == SCSysytemMessageType.CP_BUILD.name) {
|
if (type == SCSysytemMessageType.CP_BUILD.name) {
|
||||||
unawaited(_rejectCpInviteDirect(id, cpInvite, cpData));
|
unawaited(_rejectCpInviteDirect(id, cpInvite));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SmartDialog.show(
|
SmartDialog.show(
|
||||||
|
|||||||
@ -434,10 +434,8 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
|||||||
.addConversationListener(
|
.addConversationListener(
|
||||||
listener: V2TimConversationListener(
|
listener: V2TimConversationListener(
|
||||||
onNewConversation: (conversationList) {
|
onNewConversation: (conversationList) {
|
||||||
_onRefreshConversation(conversationList);
|
// _onRefreshConversation(conversationList);
|
||||||
},
|
initConversation();
|
||||||
onConversationChanged: (conversationList) {
|
|
||||||
_onRefreshConversation(conversationList);
|
|
||||||
},
|
},
|
||||||
onTotalUnreadMessageCountChanged: (int totalUnreadCount) {
|
onTotalUnreadMessageCountChanged: (int totalUnreadCount) {
|
||||||
messageUnReadCount = totalUnreadCount;
|
messageUnReadCount = totalUnreadCount;
|
||||||
@ -607,11 +605,7 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
|||||||
conversationMap.clear();
|
conversationMap.clear();
|
||||||
if (conversationList != null) {
|
if (conversationList != null) {
|
||||||
for (V2TimConversation? conversation in conversationList) {
|
for (V2TimConversation? conversation in conversationList) {
|
||||||
if (conversation == null) {
|
conversationMap[conversation!.conversationID] = conversation;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
conversationMap[conversation.conversationID] = conversation;
|
|
||||||
_handleCpBuildFromConversation(conversation);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getConversationList();
|
getConversationList();
|
||||||
@ -859,13 +853,6 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
|||||||
if (data == null) {
|
if (data == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final relationNoticePeerId = _cpRelationNoticePeerIdFromData(
|
|
||||||
data,
|
|
||||||
message: message,
|
|
||||||
);
|
|
||||||
if (relationNoticePeerId != null) {
|
|
||||||
return relationNoticePeerId;
|
|
||||||
}
|
|
||||||
final invite = _cpInviteFromMessageData(data);
|
final invite = _cpInviteFromMessageData(data);
|
||||||
final currentProfile = AccountStorage().getCurrentUser()?.userProfile;
|
final currentProfile = AccountStorage().getCurrentUser()?.userProfile;
|
||||||
if (invite == null || currentProfile == null) {
|
if (invite == null || currentProfile == null) {
|
||||||
@ -943,9 +930,6 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
|||||||
if (_handleCpInviteResultMessage(data, msgId: message?.msgID)) {
|
if (_handleCpInviteResultMessage(data, msgId: message?.msgID)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_handleCpRelationRefreshNoticeMessage(data, message: message)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (noticeType != SCSysytemMessageType.CP_BUILD.name) {
|
if (noticeType != SCSysytemMessageType.CP_BUILD.name) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1257,47 +1241,6 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
|||||||
return true;
|
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({
|
Future<void> _showCpInviteResultDialog({
|
||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
required Map<String, dynamic> data,
|
required Map<String, dynamic> data,
|
||||||
@ -2096,88 +2039,13 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
|||||||
content["type"]?.toString(),
|
content["type"]?.toString(),
|
||||||
])?.toUpperCase() ??
|
])?.toUpperCase() ??
|
||||||
"";
|
"";
|
||||||
if (noticeType == SCSysytemMessageType.CP_BUILD.name ||
|
if (noticeType == SCSysytemMessageType.CP_BUILD.name) {
|
||||||
_isCpRelationRefreshNoticeType(noticeType)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return _cpInviteApplyIdFromData(data).isNotEmpty &&
|
return _cpInviteApplyIdFromData(data).isNotEmpty &&
|
||||||
_cpInviteResultFromMessageData(data) != null;
|
_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) {
|
void _cpInviteLog(String message) {
|
||||||
debugPrint('[CP][Invite] $message');
|
debugPrint('[CP][Invite] $message');
|
||||||
}
|
}
|
||||||
@ -2185,23 +2053,10 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
|||||||
void _onRefreshConversation(List<V2TimConversation> conversations) {
|
void _onRefreshConversation(List<V2TimConversation> conversations) {
|
||||||
for (V2TimConversation conversation in conversations) {
|
for (V2TimConversation conversation in conversations) {
|
||||||
conversationMap[conversation.conversationID] = conversation;
|
conversationMap[conversation.conversationID] = conversation;
|
||||||
_handleCpBuildFromConversation(conversation);
|
|
||||||
}
|
}
|
||||||
getConversationList();
|
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群聊
|
///创建房间im群聊
|
||||||
Future<V2TimValueCallback<String>> createRoomGroup(
|
Future<V2TimValueCallback<String>> createRoomGroup(
|
||||||
String groupID,
|
String groupID,
|
||||||
|
|||||||
@ -178,28 +178,22 @@ class SocialChatUserProfileManager extends ChangeNotifier {
|
|||||||
if (userId.trim().isEmpty) {
|
if (userId.trim().isEmpty) {
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
final fallbackCpPairs = <CPRes>[];
|
final cpPairs = <CPRes>[];
|
||||||
final fallbackCloseFriendPairs = <CPRes>[];
|
final closeFriendPairs = <CPRes>[];
|
||||||
_addCpRelationPairs(
|
_addCpRelationPairs(
|
||||||
cpPairs: fallbackCpPairs,
|
cpPairs: cpPairs,
|
||||||
closeFriendPairs: fallbackCloseFriendPairs,
|
closeFriendPairs: closeFriendPairs,
|
||||||
relations: profile.cpList,
|
relations: profile.cpList,
|
||||||
fallbackRelationType: 'CP',
|
fallbackRelationType: 'CP',
|
||||||
);
|
);
|
||||||
_addCpRelationPairs(
|
_addCpRelationPairs(
|
||||||
cpPairs: fallbackCpPairs,
|
cpPairs: cpPairs,
|
||||||
closeFriendPairs: fallbackCloseFriendPairs,
|
closeFriendPairs: closeFriendPairs,
|
||||||
relations: profile.closeFriendList,
|
relations: profile.closeFriendList,
|
||||||
);
|
);
|
||||||
final cpPairs = <CPRes>[];
|
|
||||||
final closeFriendPairs = <CPRes>[];
|
|
||||||
var loadedAnyCabin = false;
|
|
||||||
await Future.wait(
|
await Future.wait(
|
||||||
_cpProfileRelationTypes.map((relationType) async {
|
_cpProfileRelationTypes.map((relationType) async {
|
||||||
final cabin = await _safeLoadCpCabin(userId, relationType);
|
final cabin = await _safeLoadCpCabin(userId, relationType);
|
||||||
if (cabin != null) {
|
|
||||||
loadedAnyCabin = true;
|
|
||||||
}
|
|
||||||
final cpPair = cabin?.cpPairUserProfileCO;
|
final cpPair = cabin?.cpPairUserProfileCO;
|
||||||
if (cpPair == null || !_hasCpPair(cpPair)) {
|
if (cpPair == null || !_hasCpPair(cpPair)) {
|
||||||
return;
|
return;
|
||||||
@ -237,12 +231,6 @@ class SocialChatUserProfileManager extends ChangeNotifier {
|
|||||||
'closeFriends=${closeFriendPairs.length}',
|
'closeFriends=${closeFriendPairs.length}',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!loadedAnyCabin) {
|
|
||||||
return profile.copyWith(
|
|
||||||
cpList: fallbackCpPairs,
|
|
||||||
closeFriendList: fallbackCloseFriendPairs,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return profile.copyWith(
|
return profile.copyWith(
|
||||||
cpList: cpPairs,
|
cpList: cpPairs,
|
||||||
closeFriendList: closeFriendPairs,
|
closeFriendList: closeFriendPairs,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user