修改bug
This commit is contained in:
parent
f025c18211
commit
b045b3b784
@ -1275,11 +1275,15 @@ class _MessageItem extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (cpStatusLineText != null) _buildCpStatusLine(cpStatusLineText),
|
||||
if (cpRelationFormedCard != null)
|
||||
cpRelationFormedCard
|
||||
else if (cpStatusLineText != null)
|
||||
_buildCpStatusLine(cpStatusLineText)
|
||||
else
|
||||
Padding(
|
||||
padding: EdgeInsets.only(
|
||||
top: cpStatusLineText == null ? 0 : 10.w,
|
||||
),
|
||||
child: cpRelationFormedCard,
|
||||
)
|
||||
else if (cpStatusLineText == null)
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@ -1647,12 +1651,14 @@ class _MessageItem extends StatelessWidget {
|
||||
return null;
|
||||
}
|
||||
final state = _cpInviteStateFromData(data);
|
||||
if (state == _CpInviteMessageState.pending ||
|
||||
state == _CpInviteMessageState.accepted) {
|
||||
if (state == _CpInviteMessageState.pending) {
|
||||
return null;
|
||||
}
|
||||
final localizations = SCAppLocalizations.of(context)!;
|
||||
final relationType = _cpRelationTypeFromMessageData(data);
|
||||
if (state == _CpInviteMessageState.accepted) {
|
||||
return _cpAcceptedStatusLineText(relationType);
|
||||
}
|
||||
if (state == _CpInviteMessageState.expired) {
|
||||
if (relationType != "CP") {
|
||||
return "The ${scCpRelationPossessiveLabel(relationType)} invitation timed out.";
|
||||
@ -1670,6 +1676,19 @@ class _MessageItem extends StatelessWidget {
|
||||
: "You declined the other party's $relationLabel invitation.";
|
||||
}
|
||||
|
||||
String _cpAcceptedStatusLineText(String relationType) {
|
||||
final localizations = SCAppLocalizations.of(context)!;
|
||||
switch (scNormalizeCpRelationType(relationType)) {
|
||||
case "BROTHER":
|
||||
return "Have become sworn brothers";
|
||||
case "SISTERS":
|
||||
return "Have become sisters";
|
||||
case "CP":
|
||||
default:
|
||||
return localizations.closeFriendsHaveBecome;
|
||||
}
|
||||
}
|
||||
|
||||
void _showCpInviteDialogFromMessage(
|
||||
Map<String, dynamic> data,
|
||||
SCSystemInvitMessageRes? cpInvite,
|
||||
|
||||
@ -370,11 +370,15 @@ class _MessageItem extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (cpStatusLineText != null) _buildCpStatusLine(cpStatusLineText),
|
||||
if (cpRelationFormedCard != null)
|
||||
cpRelationFormedCard
|
||||
else if (cpStatusLineText != null)
|
||||
_buildCpStatusLine(cpStatusLineText)
|
||||
else
|
||||
Padding(
|
||||
padding: EdgeInsets.only(
|
||||
top: cpStatusLineText == null ? 0 : 10.w,
|
||||
),
|
||||
child: cpRelationFormedCard,
|
||||
)
|
||||
else if (cpStatusLineText == null)
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
@ -834,10 +838,6 @@ class _MessageItem extends StatelessWidget {
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
final noticeType = data["noticeType"]?.toString() ?? "";
|
||||
if (noticeType == SCSysytemMessageType.CP_BUILD.name) {
|
||||
return null;
|
||||
}
|
||||
final state = _cpInviteStateFromData(data);
|
||||
if (state == _CpInviteMessageState.pending || !_isCpInvitePayload(data)) {
|
||||
return null;
|
||||
@ -846,10 +846,10 @@ class _MessageItem extends StatelessWidget {
|
||||
if (state == _CpInviteMessageState.expired) {
|
||||
return localizations.closeFriendInviteTimedOut;
|
||||
}
|
||||
final inviterView = _isCurrentUserCpInviter(data);
|
||||
if (state == _CpInviteMessageState.accepted) {
|
||||
return null;
|
||||
return _cpAcceptedStatusLineText(_cpRelationTypeFromMessageData(data));
|
||||
}
|
||||
final inviterView = _isCurrentUserCpInviter(data);
|
||||
return inviterView
|
||||
? localizations.otherDeclinedCloseFriendInvite
|
||||
: localizations.youDeclinedCloseFriendInvite;
|
||||
@ -1147,6 +1147,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 {
|
||||
@ -1202,6 +1216,19 @@ class _MessageItem extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
String _cpAcceptedStatusLineText(String relationType) {
|
||||
final localizations = SCAppLocalizations.of(context)!;
|
||||
switch (scNormalizeCpRelationType(relationType)) {
|
||||
case "BROTHER":
|
||||
return "Have become sworn brothers";
|
||||
case "SISTERS":
|
||||
return "Have become sisters";
|
||||
case "CP":
|
||||
default:
|
||||
return localizations.closeFriendsHaveBecome;
|
||||
}
|
||||
}
|
||||
|
||||
String _cpDisplayName({
|
||||
String? nickname,
|
||||
String? account,
|
||||
|
||||
@ -33,14 +33,25 @@ import 'package:yumi/shared/business_logic/models/res/sc_sign_in_reward_res.dart
|
||||
import 'package:yumi/shared/business_logic/models/res/sc_sign_in_res.dart';
|
||||
import 'package:yumi/shared/business_logic/models/res/sc_violation_handle_res.dart';
|
||||
import 'package:yumi/shared/business_logic/repositories/user_repository.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/local/user_manager.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/remote/net/api.dart'
|
||||
show BaseNetworkClient;
|
||||
import 'package:yumi/shared/data_sources/sources/remote/net/network_client.dart';
|
||||
import 'package:yumi/shared/tools/sc_mobile_login_context.dart';
|
||||
import 'package:yumi/shared/tools/sc_room_profile_cache.dart';
|
||||
|
||||
class _CpRequestCacheEntry<T> {
|
||||
const _CpRequestCacheEntry(this.value, this.createdAt);
|
||||
|
||||
final T value;
|
||||
final DateTime createdAt;
|
||||
|
||||
bool isFresh(Duration ttl) => DateTime.now().difference(createdAt) < ttl;
|
||||
}
|
||||
|
||||
class SCAccountRepository implements SocialChatUserRepository {
|
||||
static SCAccountRepository? _instance;
|
||||
static const Duration _cpRelationRequestCacheTtl = Duration(seconds: 2);
|
||||
|
||||
SCAccountRepository._internal();
|
||||
|
||||
@ -48,6 +59,12 @@ class SCAccountRepository implements SocialChatUserRepository {
|
||||
return _instance ??= SCAccountRepository._internal();
|
||||
}
|
||||
|
||||
final Map<String, _CpRequestCacheEntry<List<CPRes>>> _cpPairsCache = {};
|
||||
final Map<String, Future<List<CPRes>>> _cpPairsInFlight = {};
|
||||
final Map<String, _CpRequestCacheEntry<SCCpCabinRes>> _cpCabinCache = {};
|
||||
final Map<String, Future<SCCpCabinRes>> _cpCabinInFlight = {};
|
||||
int _cpRelationCacheEpoch = 0;
|
||||
|
||||
void _cpDebugLog(String message) {
|
||||
if (kDebugMode) {
|
||||
debugPrint('[CP][API] $message');
|
||||
@ -78,6 +95,52 @@ class SCAccountRepository implements SocialChatUserRepository {
|
||||
'levels=${config.levels.map((level) => "{level=${level.level}, name=${level.levelName}, required=${level.requiredIntimacyValue}, rights=${level.rights.length}, unlocked=${level.unlocked}}").toList()}}';
|
||||
}
|
||||
|
||||
String _currentCpCacheSessionKey() {
|
||||
final currentUserId =
|
||||
AccountStorage().getCurrentUser()?.userProfile?.id?.trim() ?? '';
|
||||
if (currentUserId.isNotEmpty) {
|
||||
return currentUserId;
|
||||
}
|
||||
final token = AccountStorage().getToken().trim();
|
||||
return token.isEmpty ? 'anonymous' : token;
|
||||
}
|
||||
|
||||
String _normalizedCpRelationType(String relationType) {
|
||||
final normalized = relationType.trim().toUpperCase();
|
||||
return normalized.isEmpty ? 'CP' : normalized;
|
||||
}
|
||||
|
||||
String _cpPairsCacheKey(String relationType) {
|
||||
return '${_currentCpCacheSessionKey()}|${_normalizedCpRelationType(relationType)}';
|
||||
}
|
||||
|
||||
String _cpCabinCacheKey(String userId, String relationType) {
|
||||
return '${_currentCpCacheSessionKey()}|${userId.trim()}|${_normalizedCpRelationType(relationType)}';
|
||||
}
|
||||
|
||||
T? _freshCpCacheValue<T>(
|
||||
Map<String, _CpRequestCacheEntry<T>> cache,
|
||||
String key,
|
||||
) {
|
||||
final entry = cache[key];
|
||||
if (entry == null) {
|
||||
return null;
|
||||
}
|
||||
if (entry.isFresh(_cpRelationRequestCacheTtl)) {
|
||||
return entry.value;
|
||||
}
|
||||
cache.remove(key);
|
||||
return null;
|
||||
}
|
||||
|
||||
void _clearCpRelationRequestCache() {
|
||||
_cpRelationCacheEpoch++;
|
||||
_cpPairsCache.clear();
|
||||
_cpPairsInFlight.clear();
|
||||
_cpCabinCache.clear();
|
||||
_cpCabinInFlight.clear();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SocialChatLoginRes> getUser(String id) async {
|
||||
final result = await http.get(
|
||||
@ -1272,23 +1335,55 @@ class SCAccountRepository implements SocialChatUserRepository {
|
||||
///user/cp-relationship/pair
|
||||
@override
|
||||
Future<List<CPRes>> cpRelationshipPairs({String relationType = 'CP'}) async {
|
||||
_cpDebugLog('pair request relationType=$relationType');
|
||||
try {
|
||||
final result = await http.get<List<CPRes>>(
|
||||
"/user/cp-relationship/pair",
|
||||
queryParams: {"relationType": relationType},
|
||||
fromJson:
|
||||
(json) => (json as List).map((e) => CPRes.fromJson(e)).toList(),
|
||||
);
|
||||
_cpDebugLog(
|
||||
'pair response relationType=$relationType count=${result.length} '
|
||||
'pairs=${result.map(_cpPairSummary).toList()}',
|
||||
);
|
||||
return result;
|
||||
} catch (error) {
|
||||
_cpDebugLog('pair failed relationType=$relationType error=$error');
|
||||
rethrow;
|
||||
final normalizedRelationType = _normalizedCpRelationType(relationType);
|
||||
final cacheKey = _cpPairsCacheKey(normalizedRelationType);
|
||||
final cached = _freshCpCacheValue(_cpPairsCache, cacheKey);
|
||||
if (cached != null) {
|
||||
_cpDebugLog('pair cache hit relationType=$normalizedRelationType');
|
||||
return cached;
|
||||
}
|
||||
final inFlight = _cpPairsInFlight[cacheKey];
|
||||
if (inFlight != null) {
|
||||
_cpDebugLog('pair join in-flight relationType=$normalizedRelationType');
|
||||
return inFlight;
|
||||
}
|
||||
|
||||
_cpDebugLog('pair request relationType=$normalizedRelationType');
|
||||
final requestEpoch = _cpRelationCacheEpoch;
|
||||
late final Future<List<CPRes>> trackedRequest;
|
||||
trackedRequest = http
|
||||
.get<List<CPRes>>(
|
||||
"/user/cp-relationship/pair",
|
||||
queryParams: {"relationType": normalizedRelationType},
|
||||
fromJson:
|
||||
(json) => (json as List).map((e) => CPRes.fromJson(e)).toList(),
|
||||
)
|
||||
.then((result) {
|
||||
if (requestEpoch == _cpRelationCacheEpoch) {
|
||||
_cpPairsCache[cacheKey] = _CpRequestCacheEntry(
|
||||
result,
|
||||
DateTime.now(),
|
||||
);
|
||||
}
|
||||
_cpDebugLog(
|
||||
'pair response relationType=$normalizedRelationType count=${result.length} '
|
||||
'pairs=${result.map(_cpPairSummary).toList()}',
|
||||
);
|
||||
return result;
|
||||
})
|
||||
.catchError((error) {
|
||||
_cpDebugLog(
|
||||
'pair failed relationType=$normalizedRelationType error=$error',
|
||||
);
|
||||
throw error;
|
||||
})
|
||||
.whenComplete(() {
|
||||
if (_cpPairsInFlight[cacheKey] == trackedRequest) {
|
||||
_cpPairsInFlight.remove(cacheKey);
|
||||
}
|
||||
});
|
||||
_cpPairsInFlight[cacheKey] = trackedRequest;
|
||||
return trackedRequest;
|
||||
}
|
||||
|
||||
///user/cp-relationship/send-apply
|
||||
@ -1308,6 +1403,7 @@ class SCAccountRepository implements SocialChatUserRepository {
|
||||
allowNullBody: true,
|
||||
fromJson: (json) => json,
|
||||
);
|
||||
_clearCpRelationRequestCache();
|
||||
_cpDebugLog('sendApply success data=$parm');
|
||||
return true;
|
||||
} catch (error) {
|
||||
@ -1330,6 +1426,7 @@ class SCAccountRepository implements SocialChatUserRepository {
|
||||
allowNullBody: true,
|
||||
fromJson: (json) => json,
|
||||
);
|
||||
_clearCpRelationRequestCache();
|
||||
_cpDebugLog('processApply success data=$parm');
|
||||
return true;
|
||||
} catch (error) {
|
||||
@ -1355,6 +1452,7 @@ class SCAccountRepository implements SocialChatUserRepository {
|
||||
allowNullBody: true,
|
||||
fromJson: (json) => json,
|
||||
);
|
||||
_clearCpRelationRequestCache();
|
||||
_cpDebugLog('dismissApply success query=$parm');
|
||||
return true;
|
||||
} catch (error) {
|
||||
@ -1413,22 +1511,52 @@ class SCAccountRepository implements SocialChatUserRepository {
|
||||
String userId, {
|
||||
String relationType = 'CP',
|
||||
}) async {
|
||||
final query = {"userId": userId, "relationType": relationType};
|
||||
_cpDebugLog('cabin request query=$query');
|
||||
try {
|
||||
final result = await http.get<SCCpCabinRes>(
|
||||
"/user/cp/cabin",
|
||||
queryParams: query,
|
||||
fromJson: (json) => SCCpCabinRes.fromJson(json),
|
||||
);
|
||||
_cpDebugLog(
|
||||
'cabin response query=$query result=${_cpCabinSummary(result)}',
|
||||
);
|
||||
return result;
|
||||
} catch (error) {
|
||||
_cpDebugLog('cabin failed query=$query error=$error');
|
||||
rethrow;
|
||||
final normalizedRelationType = _normalizedCpRelationType(relationType);
|
||||
final query = {"userId": userId, "relationType": normalizedRelationType};
|
||||
final cacheKey = _cpCabinCacheKey(userId, normalizedRelationType);
|
||||
final cached = _freshCpCacheValue(_cpCabinCache, cacheKey);
|
||||
if (cached != null) {
|
||||
_cpDebugLog('cabin cache hit query=$query');
|
||||
return cached;
|
||||
}
|
||||
final inFlight = _cpCabinInFlight[cacheKey];
|
||||
if (inFlight != null) {
|
||||
_cpDebugLog('cabin join in-flight query=$query');
|
||||
return inFlight;
|
||||
}
|
||||
|
||||
_cpDebugLog('cabin request query=$query');
|
||||
final requestEpoch = _cpRelationCacheEpoch;
|
||||
late final Future<SCCpCabinRes> trackedRequest;
|
||||
trackedRequest = http
|
||||
.get<SCCpCabinRes>(
|
||||
"/user/cp/cabin",
|
||||
queryParams: query,
|
||||
fromJson: (json) => SCCpCabinRes.fromJson(json),
|
||||
)
|
||||
.then((result) {
|
||||
if (requestEpoch == _cpRelationCacheEpoch) {
|
||||
_cpCabinCache[cacheKey] = _CpRequestCacheEntry(
|
||||
result,
|
||||
DateTime.now(),
|
||||
);
|
||||
}
|
||||
_cpDebugLog(
|
||||
'cabin response query=$query result=${_cpCabinSummary(result)}',
|
||||
);
|
||||
return result;
|
||||
})
|
||||
.catchError((error) {
|
||||
_cpDebugLog('cabin failed query=$query error=$error');
|
||||
throw error;
|
||||
})
|
||||
.whenComplete(() {
|
||||
if (_cpCabinInFlight[cacheKey] == trackedRequest) {
|
||||
_cpCabinInFlight.remove(cacheKey);
|
||||
}
|
||||
});
|
||||
_cpCabinInFlight[cacheKey] = trackedRequest;
|
||||
return trackedRequest;
|
||||
}
|
||||
|
||||
///user/cp/cabin/value
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user