bug。fix
This commit is contained in:
parent
71993f438b
commit
6da7e28fbc
@ -48,7 +48,7 @@ class _RoomCpProgressDialogPreviewPage extends StatelessWidget {
|
||||
const RoomCpProgressDialog(
|
||||
daysValue: '999',
|
||||
daysLabel: 'Days',
|
||||
levelText: 'Lv.1 Simple Love',
|
||||
levelText: 'Lv.0',
|
||||
currentValue: 1,
|
||||
targetValue: 1,
|
||||
expAwayText: '1,000',
|
||||
|
||||
@ -1676,6 +1676,14 @@ class _GiftPageState extends State<GiftPage> with TickerProviderStateMixin {
|
||||
if (!_isCpGift(request.gift)) {
|
||||
return;
|
||||
}
|
||||
if (request.isSelfRecipientRequest) {
|
||||
_giftFxLog(
|
||||
'skip local CP waiting dialog reason=self_recipient '
|
||||
'giftId=${request.gift.id} '
|
||||
'acceptUserIds=${request.acceptUserIds.join(",")}',
|
||||
);
|
||||
return;
|
||||
}
|
||||
final context = navigatorKey.currentState?.context;
|
||||
final currentProfile = AccountStorage().getCurrentUser()?.userProfile;
|
||||
final receiverProfile =
|
||||
@ -2359,9 +2367,40 @@ class _GiftSendRequest {
|
||||
if (!scIsCpGift(gift)) {
|
||||
return null;
|
||||
}
|
||||
if (isSelfRecipientRequest) {
|
||||
return null;
|
||||
}
|
||||
return scCpRelationTypeForGift(gift);
|
||||
}
|
||||
|
||||
bool get isSelfRecipientRequest {
|
||||
final currentProfile = AccountStorage().getCurrentUser()?.userProfile;
|
||||
final currentKeys = _profileIdentityKeys(currentProfile);
|
||||
if (currentKeys.isEmpty) {
|
||||
return false;
|
||||
}
|
||||
for (final userId in acceptUserIds) {
|
||||
if (currentKeys.contains(userId.trim())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (final acceptUser in acceptUsers) {
|
||||
final acceptKeys = _profileIdentityKeys(acceptUser.user);
|
||||
if (acceptKeys.any(currentKeys.contains)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Set<String> _profileIdentityKeys(SocialChatUserProfile? profile) {
|
||||
return <String>{
|
||||
profile?.id?.trim() ?? "",
|
||||
profile?.account?.trim() ?? "",
|
||||
profile?.getID().trim() ?? "",
|
||||
}..remove("");
|
||||
}
|
||||
|
||||
String get batchKey {
|
||||
final sortedAcceptUserIds = List<String>.from(acceptUserIds)..sort();
|
||||
final type =
|
||||
|
||||
@ -1449,19 +1449,7 @@ class _PersonDetailPageState extends State<PersonDetailPage> {
|
||||
}
|
||||
|
||||
String _normalizeProfileRelationType(String? relationType) {
|
||||
final value = relationType?.trim().toUpperCase() ?? "";
|
||||
switch (value) {
|
||||
case "BROTHER":
|
||||
case "BROTHERS":
|
||||
case "SWORN_BROTHER":
|
||||
case "SWORN_BROTHERS":
|
||||
return "BROTHER";
|
||||
case "SISTER":
|
||||
case "SISTERS":
|
||||
return "SISTERS";
|
||||
default:
|
||||
return "CP";
|
||||
}
|
||||
return scNormalizeCpRelationType(relationType);
|
||||
}
|
||||
|
||||
bool _isOwnProfile(SocialChatUserProfile? profile) {
|
||||
@ -1639,7 +1627,12 @@ class _PersonDetailPageState extends State<PersonDetailPage> {
|
||||
}
|
||||
|
||||
String _profileCpLevelAsset(CPRes relation) {
|
||||
return "$_cpProfileAssetBase/sc_cp_profile_cp_level_${_profileRelationLevel(relation)}.png";
|
||||
return "$_cpProfileAssetBase/sc_cp_profile_cp_level_${_profileRelationAssetLevel(relation)}.png";
|
||||
}
|
||||
|
||||
int _profileRelationAssetLevel(CPRes relation) {
|
||||
final level = _profileRelationLevel(relation);
|
||||
return level <= 0 ? 1 : level;
|
||||
}
|
||||
|
||||
int _profileRelationLevel(CPRes relation) {
|
||||
@ -1648,7 +1641,7 @@ class _PersonDetailPageState extends State<PersonDetailPage> {
|
||||
|
||||
String _profileRelationLevelText(CPRes relation) {
|
||||
return _profileRelationLevelDisplayText(
|
||||
_firstNonBlankProfileValue([relation.levelText, "Lv.1 Simple Love"]),
|
||||
_firstNonBlankProfileValue([relation.levelText, "Lv.0"]),
|
||||
relation,
|
||||
);
|
||||
}
|
||||
@ -2639,10 +2632,7 @@ class _ProfileRelationProgressData {
|
||||
) {
|
||||
final currentValue = payload.cpValue;
|
||||
return _ProfileRelationProgressData(
|
||||
levelText:
|
||||
payload.levelText.trim().isEmpty
|
||||
? "Lv.1 Simple Love"
|
||||
: payload.levelText,
|
||||
levelText: scCpRelationLevelDisplayText(payload.levelText),
|
||||
currentValue: currentValue,
|
||||
targetValue: currentValue > 0 ? currentValue : 1,
|
||||
expAwayText: SCStringUtils.formatCompactNumber(0),
|
||||
@ -2762,16 +2752,19 @@ class _ProfileRelationProgressData {
|
||||
) {
|
||||
final fallbackText = fallback.trim();
|
||||
if (level == null) {
|
||||
return fallbackText.isEmpty ? "Lv.1 Simple Love" : fallbackText;
|
||||
return scCpRelationLevelDisplayText(fallbackText);
|
||||
}
|
||||
final levelName = level.levelName?.trim();
|
||||
if (level.level != null && levelName != null && levelName.isNotEmpty) {
|
||||
return scCpRelationLevelDisplayText("Lv.${level.level} $levelName");
|
||||
}
|
||||
if (levelName != null && levelName.isNotEmpty) {
|
||||
return levelName;
|
||||
return scCpRelationLevelDisplayText(levelName);
|
||||
}
|
||||
if (level.level != null) {
|
||||
return "Lv.${level.level}";
|
||||
}
|
||||
return fallbackText.isEmpty ? "Lv.1 Simple Love" : fallbackText;
|
||||
return scCpRelationLevelDisplayText(fallbackText);
|
||||
}
|
||||
|
||||
static String _levelShortText(int? level, {String? fallback}) {
|
||||
@ -2780,9 +2773,9 @@ class _ProfileRelationProgressData {
|
||||
}
|
||||
final fallbackText = fallback?.trim() ?? "";
|
||||
if (fallbackText.isNotEmpty) {
|
||||
return fallbackText;
|
||||
return scCpRelationLevelDisplayText(fallbackText);
|
||||
}
|
||||
return "Lv. 1";
|
||||
return "Lv. 0";
|
||||
}
|
||||
|
||||
static int _levelIndex(String levelText) {
|
||||
@ -2790,7 +2783,7 @@ class _ProfileRelationProgressData {
|
||||
}
|
||||
|
||||
static int _nextLevelIndex(int level) {
|
||||
return (level + 1).clamp(1, 5).toInt();
|
||||
return (level + 1).clamp(0, 5).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -324,9 +324,11 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
static const String _roomRocketRewardDialogTag = 'showRoomRocketRewardDialog';
|
||||
static const String _roomRocketPagLaunchDialogTag =
|
||||
'showRoomRocketPagLaunchDialog';
|
||||
static const Duration _roomRocketGiftRefreshDelay = Duration(
|
||||
milliseconds: 700,
|
||||
);
|
||||
static const List<Duration> _roomRocketGiftRefreshDelays = [
|
||||
Duration(milliseconds: 700),
|
||||
Duration(milliseconds: 1600),
|
||||
Duration(milliseconds: 3200),
|
||||
];
|
||||
static const List<Duration> _roomRocketPostLaunchRefreshDelays = [
|
||||
Duration(milliseconds: 800),
|
||||
Duration(seconds: 2),
|
||||
@ -389,7 +391,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
Timer? _roomEntryEffectTimer;
|
||||
Timer? _roomRocketLaunchAnimationTimer;
|
||||
ValueNotifier<String?>? _roomRocketLaunchTopAvatarNotifier;
|
||||
Timer? _roomRocketGiftRefreshTimer;
|
||||
final List<Timer> _roomRocketGiftRefreshTimers = [];
|
||||
final List<Timer> _roomRocketPostLaunchRefreshTimers = [];
|
||||
final List<Timer> _roomRocketEntryReadyFallbackTimers = [];
|
||||
Timer? _roomRedPacketPresenceTimer;
|
||||
@ -546,8 +548,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
_roomRocketLaunchAnimationTimer = null;
|
||||
SmartDialog.dismiss(tag: _roomRocketPagLaunchDialogTag);
|
||||
_releaseRoomRocketLaunchTopAvatarNotifier();
|
||||
_roomRocketGiftRefreshTimer?.cancel();
|
||||
_roomRocketGiftRefreshTimer = null;
|
||||
_cancelRoomRocketGiftStatusRefresh();
|
||||
_cancelRoomRocketEntryReadyFallbacks();
|
||||
_cancelRoomRocketPostLaunchStatusRefresh();
|
||||
}
|
||||
@ -3602,6 +3603,45 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
_scheduleRoomRocketAssetPreload(resolvedRoomId, res);
|
||||
}
|
||||
|
||||
void updateRoomRocketStatusFromRealtime(
|
||||
SCRoomRocketStatusRes update, {
|
||||
String? roomId,
|
||||
}) {
|
||||
final resolvedRoomId =
|
||||
(roomId ??
|
||||
update.roomId ??
|
||||
currenRoom?.roomProfile?.roomProfile?.id ??
|
||||
"")
|
||||
.trim();
|
||||
if (resolvedRoomId.isEmpty ||
|
||||
resolvedRoomId !=
|
||||
(currenRoom?.roomProfile?.roomProfile?.id ?? "").trim()) {
|
||||
return;
|
||||
}
|
||||
if (!_hasRoomRocketRealtimeStatusFields(update)) {
|
||||
return;
|
||||
}
|
||||
final merged =
|
||||
roomRocketStatus?.mergeRealtimeUpdate(update, roomId: resolvedRoomId) ??
|
||||
update;
|
||||
roomRocketStatus = merged;
|
||||
notifyListeners();
|
||||
if (!merged.isEnabled) {
|
||||
return;
|
||||
}
|
||||
_scheduleRoomRocketAssetPreload(resolvedRoomId, merged);
|
||||
}
|
||||
|
||||
bool _hasRoomRocketRealtimeStatusFields(SCRoomRocketStatusRes update) {
|
||||
return update.currentLevel != null ||
|
||||
update.level != null ||
|
||||
update.currentEnergy != null ||
|
||||
update.maxEnergy != null ||
|
||||
update.displayPercent != null ||
|
||||
update.energyPercent != null ||
|
||||
(update.levels?.isNotEmpty ?? false);
|
||||
}
|
||||
|
||||
void _scheduleRoomRocketAssetPreload(
|
||||
String roomId,
|
||||
SCRoomRocketStatusRes status, {
|
||||
@ -3639,11 +3679,25 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
if (resolvedRoomId.isEmpty) {
|
||||
return;
|
||||
}
|
||||
_roomRocketGiftRefreshTimer?.cancel();
|
||||
_roomRocketGiftRefreshTimer = Timer(_roomRocketGiftRefreshDelay, () {
|
||||
_roomRocketGiftRefreshTimer = null;
|
||||
unawaited(refreshRoomRocketStatus(roomId: resolvedRoomId));
|
||||
});
|
||||
_cancelRoomRocketGiftStatusRefresh();
|
||||
for (final delay in _roomRocketGiftRefreshDelays) {
|
||||
final timer = Timer(delay, () {
|
||||
_roomRocketGiftRefreshTimers.removeWhere((item) => !item.isActive);
|
||||
if (resolvedRoomId !=
|
||||
(currenRoom?.roomProfile?.roomProfile?.id ?? "").trim()) {
|
||||
return;
|
||||
}
|
||||
unawaited(refreshRoomRocketStatus(roomId: resolvedRoomId));
|
||||
});
|
||||
_roomRocketGiftRefreshTimers.add(timer);
|
||||
}
|
||||
}
|
||||
|
||||
void _cancelRoomRocketGiftStatusRefresh() {
|
||||
for (final timer in _roomRocketGiftRefreshTimers) {
|
||||
timer.cancel();
|
||||
}
|
||||
_roomRocketGiftRefreshTimers.clear();
|
||||
}
|
||||
|
||||
void _scheduleRoomRocketEntryReadyFallback(String roomId) {
|
||||
@ -4464,8 +4518,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
_roomRocketLaunchAnimationTimer = null;
|
||||
SmartDialog.dismiss(tag: _roomRocketPagLaunchDialogTag);
|
||||
_releaseRoomRocketLaunchTopAvatarNotifier();
|
||||
_roomRocketGiftRefreshTimer?.cancel();
|
||||
_roomRocketGiftRefreshTimer = null;
|
||||
_cancelRoomRocketGiftStatusRefresh();
|
||||
_cancelRoomRocketPostLaunchStatusRefresh();
|
||||
RoomRocketAssetPreloader.cancelCurrentRoom();
|
||||
_stopRoomRedPacketPresenceHeartbeat();
|
||||
@ -4528,6 +4581,9 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
@override
|
||||
void dispose() {
|
||||
_stopRoomStatePolling();
|
||||
_cancelRoomRocketGiftStatusRefresh();
|
||||
_cancelRoomRocketPostLaunchStatusRefresh();
|
||||
_cancelRoomRocketEntryReadyFallbacks();
|
||||
_clearRoomMusicPublishingStates();
|
||||
unawaited(releaseRtcEngineForAppTermination());
|
||||
super.dispose();
|
||||
|
||||
@ -55,6 +55,7 @@ import 'package:yumi/shared/data_sources/models/message/room_rocket_launch_broad
|
||||
import 'package:yumi/shared/data_sources/models/message/sc_floating_message.dart';
|
||||
import 'package:yumi/shared/business_logic/models/res/sc_broad_cast_luck_gift_push.dart';
|
||||
import 'package:yumi/shared/business_logic/models/res/sc_room_rocket_api_res.dart';
|
||||
import 'package:yumi/shared/business_logic/models/res/sc_room_rocket_status_res.dart';
|
||||
import 'package:yumi/shared/business_logic/models/res/broad_cast_mic_change_push.dart'
|
||||
hide Data;
|
||||
import 'package:yumi/shared/business_logic/models/res/gift_res.dart';
|
||||
@ -934,6 +935,18 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (_cpInviteTargetsCurrentAsSenderAndReceiver(
|
||||
invite,
|
||||
currentProfile,
|
||||
data,
|
||||
)) {
|
||||
_cpInviteLog(
|
||||
'skip CP_BUILD reason=self_recipient applyId=$applyId '
|
||||
'relationType=${invite.relationType}',
|
||||
);
|
||||
await SmartDialog.dismiss(tag: RoomCpInviteDialog.dialogTag);
|
||||
return;
|
||||
}
|
||||
final isSender = _cpInviteSenderMatchesCurrent(
|
||||
invite,
|
||||
currentProfile,
|
||||
@ -1124,6 +1137,17 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
}
|
||||
final currentProfile = AccountStorage().getCurrentUser()?.userProfile;
|
||||
if (context != null && invite != null && currentProfile != null) {
|
||||
if (_cpInviteTargetsCurrentAsSenderAndReceiver(
|
||||
invite,
|
||||
currentProfile,
|
||||
data,
|
||||
)) {
|
||||
_cpInviteLog(
|
||||
'skip CP invite result reason=self_recipient applyId=$applyId '
|
||||
'result=${result.name}',
|
||||
);
|
||||
return true;
|
||||
}
|
||||
final isSender = _cpInviteSenderMatchesCurrent(
|
||||
invite,
|
||||
currentProfile,
|
||||
@ -1759,6 +1783,33 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
return currentIds.any(inviteIds.contains);
|
||||
}
|
||||
|
||||
bool _cpInviteTargetsCurrentAsSenderAndReceiver(
|
||||
SCSystemInvitMessageRes invite,
|
||||
SocialChatUserProfile currentProfile,
|
||||
Map<String, dynamic> data,
|
||||
) {
|
||||
final currentIds = _cpInviteProfileIdentityValues(currentProfile);
|
||||
if (currentIds.isEmpty) {
|
||||
return false;
|
||||
}
|
||||
final inviterIds = <String>{
|
||||
..._cpInviteInviterIdentityValues(data),
|
||||
invite.actualAccount?.trim() ?? "",
|
||||
invite.account?.trim() ?? "",
|
||||
}..remove("");
|
||||
final receiverIds = _cpInviteReceiverIdentityValues(data);
|
||||
return inviterIds.any(currentIds.contains) &&
|
||||
receiverIds.any(currentIds.contains);
|
||||
}
|
||||
|
||||
Set<String> _cpInviteProfileIdentityValues(SocialChatUserProfile profile) {
|
||||
return <String>{
|
||||
profile.id?.trim() ?? "",
|
||||
profile.account?.trim() ?? "",
|
||||
profile.getID().trim(),
|
||||
}..remove("");
|
||||
}
|
||||
|
||||
Set<String> _cpInviteInviterIdentityValues(Map<String, dynamic> data) {
|
||||
final content = _cpInviteContentMap(data);
|
||||
final values = <String?>[
|
||||
@ -3671,7 +3722,11 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
_publishRoomRocketRegionBroadcastIfNeeded(launch);
|
||||
}
|
||||
}
|
||||
unawaited(rtcProvider.refreshRoomRocketStatus(roomId: roomId));
|
||||
rtcProvider.updateRoomRocketStatusFromRealtime(
|
||||
SCRoomRocketStatusRes.fromJson(data),
|
||||
roomId: roomId,
|
||||
);
|
||||
rtcProvider.scheduleRoomRocketStatusRefreshForGift(roomId: roomId);
|
||||
}
|
||||
|
||||
void _handleVoiceRoomRocketLaunchBroadcast(
|
||||
|
||||
@ -13,6 +13,7 @@ import 'package:yumi/shared/business_logic/models/res/room_user_card_res.dart';
|
||||
import 'package:yumi/shared/business_logic/models/res/sc_user_identity_res.dart';
|
||||
import 'package:yumi/shared/business_logic/models/res/sc_vip_res.dart';
|
||||
import 'package:yumi/shared/tools/sc_cp_relation_level_utils.dart';
|
||||
import 'package:yumi/shared/tools/sc_cp_relation_notice_utils.dart';
|
||||
|
||||
class SocialChatUserProfileManager extends ChangeNotifier {
|
||||
static const List<String> _cpProfileRelationTypes = [
|
||||
@ -306,19 +307,7 @@ class SocialChatUserProfileManager extends ChangeNotifier {
|
||||
}
|
||||
|
||||
String _normalizeCpRelationType(String? relationType) {
|
||||
final value = relationType?.trim().toUpperCase() ?? "";
|
||||
switch (value) {
|
||||
case "BROTHER":
|
||||
case "BROTHERS":
|
||||
case "SWORN_BROTHER":
|
||||
case "SWORN_BROTHERS":
|
||||
return "BROTHER";
|
||||
case "SISTER":
|
||||
case "SISTERS":
|
||||
return "SISTERS";
|
||||
default:
|
||||
return "CP";
|
||||
}
|
||||
return scNormalizeCpRelationType(relationType);
|
||||
}
|
||||
|
||||
int? _cpDismissCostFromCabin(SCCpCabinRes? cabin) {
|
||||
|
||||
@ -1157,7 +1157,19 @@ class CPRes {
|
||||
_days = _asString(source['days']);
|
||||
_firstDay = _asString(source['firstDay']);
|
||||
_cpValue = _asDouble(source['cpValue']);
|
||||
_relationType = _asString(source['relationType']);
|
||||
_relationType = _asString(
|
||||
_firstValue(source, const [
|
||||
'relationType',
|
||||
'relation_type',
|
||||
'cpRelationType',
|
||||
'cp_relation_type',
|
||||
'relationshipType',
|
||||
'relationship_type',
|
||||
'relation',
|
||||
'cpType',
|
||||
'cp_type',
|
||||
]),
|
||||
);
|
||||
_status = _asString(source['status']);
|
||||
_levelText = _asString(
|
||||
source['levelText'] ??
|
||||
|
||||
@ -104,13 +104,27 @@ class SCRoomRocketStatusRes {
|
||||
_date = json['date'] ?? json['dayKey'] ?? json['day_key'];
|
||||
_roundNo = _intValue(json['roundNo'] ?? json['round_no']);
|
||||
_displayRound = _boolValue(json['displayRound'] ?? json['display_round']);
|
||||
_currentLevel = _intValue(json['currentLevel'] ?? json['current_level']);
|
||||
_currentLevel = _intValue(
|
||||
json['currentLevel'] ??
|
||||
json['current_level'] ??
|
||||
json['toLevel'] ??
|
||||
json['to_level'] ??
|
||||
json['nextLevel'] ??
|
||||
json['next_level'],
|
||||
);
|
||||
_needEnergy = _intValue(json['needEnergy'] ?? json['need_energy']);
|
||||
_displayPercent = _numValue(
|
||||
json['displayPercent'] ?? json['display_percent'],
|
||||
);
|
||||
_shake = _boolValue(json['shake']);
|
||||
_level = json['level'] ?? json['rocket_level'] ?? _currentLevel;
|
||||
_level =
|
||||
json['level'] ??
|
||||
json['rocket_level'] ??
|
||||
json['toLevel'] ??
|
||||
json['to_level'] ??
|
||||
json['nextLevel'] ??
|
||||
json['next_level'] ??
|
||||
_currentLevel;
|
||||
_levelName = json['levelName'] ?? json['level_name'];
|
||||
_currentEnergy = _intValue(json['currentEnergy'] ?? json['current_energy']);
|
||||
_maxEnergy =
|
||||
@ -346,6 +360,67 @@ class SCRoomRocketStatusRes {
|
||||
return null;
|
||||
}
|
||||
|
||||
SCRoomRocketStatusRes mergeRealtimeUpdate(
|
||||
SCRoomRocketStatusRes update, {
|
||||
String? roomId,
|
||||
}) {
|
||||
final updateLevels = update.levels;
|
||||
final updateRewardPreviewByLevel = update.rewardPreviewByLevel;
|
||||
final updateRocketKings = update.rocketKings;
|
||||
final updateRocketKingsByLevel = update.rocketKingsByLevel;
|
||||
return SCRoomRocketStatusRes(
|
||||
roomId: update.roomId ?? roomId ?? _roomId,
|
||||
date: update.date ?? _date,
|
||||
level: update.level ?? _level,
|
||||
levelName: update.levelName ?? _levelName,
|
||||
currentEnergy: update.currentEnergy ?? _currentEnergy,
|
||||
maxEnergy: update.maxEnergy ?? _maxEnergy,
|
||||
energyPercent: update.energyPercent ?? _energyPercent,
|
||||
status: update.status ?? _status,
|
||||
statusDesc: update.statusDesc ?? _statusDesc,
|
||||
totalContributors: update.totalContributors ?? _totalContributors,
|
||||
claimExpireTime: update.claimExpireTime ?? _claimExpireTime,
|
||||
claimCount: update.claimCount ?? _claimCount,
|
||||
canClaim: update.canClaim ?? _canClaim,
|
||||
hasClaimed: update.hasClaimed ?? _hasClaimed,
|
||||
myContribution: update.myContribution ?? _myContribution,
|
||||
myContributionRate: update.myContributionRate ?? _myContributionRate,
|
||||
configured: update.configured ?? _configured,
|
||||
enabled: update.enabled ?? _enabled,
|
||||
roundNo: update.roundNo ?? _roundNo,
|
||||
displayRound: update.displayRound ?? _displayRound,
|
||||
currentLevel:
|
||||
update.currentLevel ?? update.level?.toInt() ?? _currentLevel,
|
||||
needEnergy: update.needEnergy ?? _needEnergy,
|
||||
displayPercent: update.displayPercent ?? _displayPercent,
|
||||
shake: update.shake ?? _shake,
|
||||
levels:
|
||||
updateLevels != null && updateLevels.isNotEmpty
|
||||
? updateLevels
|
||||
: _levels,
|
||||
rewardPreview: update.rewardPreview ?? _rewardPreview,
|
||||
rewardPreviewByLevel:
|
||||
updateRewardPreviewByLevel != null &&
|
||||
updateRewardPreviewByLevel.isNotEmpty
|
||||
? updateRewardPreviewByLevel
|
||||
: _rewardPreviewByLevel,
|
||||
rocketKings:
|
||||
updateRocketKings != null && updateRocketKings.isNotEmpty
|
||||
? updateRocketKings
|
||||
: _rocketKings,
|
||||
rocketKingsByLevel:
|
||||
updateRocketKingsByLevel != null &&
|
||||
updateRocketKingsByLevel.isNotEmpty
|
||||
? updateRocketKingsByLevel
|
||||
: _rocketKingsByLevel,
|
||||
timezone: update.timezone ?? _timezone,
|
||||
resetRemainingSeconds:
|
||||
update.resetRemainingSeconds ?? _resetRemainingSeconds,
|
||||
resetTime: update.resetTime ?? _resetTime,
|
||||
serverTime: update.serverTime ?? _serverTime,
|
||||
);
|
||||
}
|
||||
|
||||
List<SCRoomRocketKingUserRes> rocketKingsForLevel(int level) {
|
||||
final normalizedLevel = level.clamp(1, 99).toInt();
|
||||
final byLevel = _rocketKingsByLevel?[normalizedLevel];
|
||||
|
||||
@ -58,20 +58,23 @@ String scCpRelationLevelDisplayText(String? rawText) {
|
||||
final text = rawText?.trim() ?? '';
|
||||
final level = scCpRelationLevelIndexOrNull(text);
|
||||
if (text.isEmpty) {
|
||||
return 'Lv.1 Simple Love';
|
||||
return 'Lv.0';
|
||||
}
|
||||
if (_isSimpleLoveLevelOneText(text, level)) {
|
||||
return 'Lv.1';
|
||||
}
|
||||
final compactLevelPattern = RegExp(
|
||||
r'^(?:Lv\.?|Level)?\s*\d+$',
|
||||
caseSensitive: false,
|
||||
);
|
||||
if (compactLevelPattern.hasMatch(text) && level == 1) {
|
||||
return 'Lv.1 Simple Love';
|
||||
if (compactLevelPattern.hasMatch(text) && level != null) {
|
||||
return 'Lv.$level';
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
int scCpRelationLevelIndex(String? levelText) {
|
||||
return scCpRelationLevelIndexOrNull(levelText) ?? 1;
|
||||
return scCpRelationLevelIndexOrNull(levelText) ?? 0;
|
||||
}
|
||||
|
||||
int? scCpRelationLevelIndexOrNull(String? levelText) {
|
||||
@ -80,14 +83,14 @@ int? scCpRelationLevelIndexOrNull(String? levelText) {
|
||||
return null;
|
||||
}
|
||||
final levelMatch = RegExp(
|
||||
r'(?:Lv\.?|Level|等级|级)\s*([1-5])|([1-5])\s*(?:级|Level)',
|
||||
r'(?:Lv\.?|Level|等级|级)\s*([0-5])|([0-5])\s*(?:级|Level)',
|
||||
caseSensitive: false,
|
||||
).firstMatch(text);
|
||||
final fallbackMatch = RegExp(r'[1-5]').firstMatch(text);
|
||||
final fallbackMatch = RegExp(r'[0-5]').firstMatch(text);
|
||||
final rawLevel =
|
||||
levelMatch?.group(1) ?? levelMatch?.group(2) ?? fallbackMatch?.group(0);
|
||||
final level = int.tryParse(rawLevel ?? '');
|
||||
return level?.clamp(1, 5).toInt();
|
||||
return level?.clamp(0, 5).toInt();
|
||||
}
|
||||
|
||||
_CpRelationLevelSource? _currentLevelFromDynamicConfigs(
|
||||
@ -136,10 +139,13 @@ _CpRelationLevelSource? _currentLevelFromSources(
|
||||
|
||||
String? _formattedLevelText({int? level, String? name}) {
|
||||
final levelName = name?.trim() ?? '';
|
||||
if (level == 1 && _isSimpleLoveName(levelName)) {
|
||||
return 'Lv.1';
|
||||
}
|
||||
if (level != null && levelName.isNotEmpty) {
|
||||
final nameLevel = scCpRelationLevelIndexOrNull(levelName);
|
||||
if (nameLevel == level) {
|
||||
return levelName;
|
||||
return scCpRelationLevelDisplayText(levelName);
|
||||
}
|
||||
return 'Lv.$level $levelName';
|
||||
}
|
||||
@ -149,6 +155,23 @@ String? _formattedLevelText({int? level, String? name}) {
|
||||
return _blankAsNull(levelName);
|
||||
}
|
||||
|
||||
bool _isSimpleLoveLevelOneText(String text, int? level) {
|
||||
if (level != 1) {
|
||||
return false;
|
||||
}
|
||||
return RegExp(
|
||||
r'^(?:Lv\.?|Level)?\s*1\s+Simple\s+Love$',
|
||||
caseSensitive: false,
|
||||
).hasMatch(text.trim());
|
||||
}
|
||||
|
||||
bool _isSimpleLoveName(String text) {
|
||||
return RegExp(
|
||||
r'^(?:Lv\.?|Level)?\s*1?\s*Simple\s+Love$',
|
||||
caseSensitive: false,
|
||||
).hasMatch(text.trim());
|
||||
}
|
||||
|
||||
String? _blankAsNull(String? value) {
|
||||
final text = value?.trim() ?? '';
|
||||
return text.isEmpty ? null : text;
|
||||
|
||||
@ -99,5 +99,5 @@ String scBuildCpRelationEntryBroadcastText({
|
||||
required String? relationType,
|
||||
}) {
|
||||
return "$ownerName's ${scCpRelationEntryLabel(relationType)} "
|
||||
"$joinedName enter the room";
|
||||
"$joinedName has joined the party";
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ import 'dart:math' as math;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:yumi/shared/tools/sc_cp_relation_level_utils.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_compontent.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_debounce_widget.dart';
|
||||
|
||||
@ -31,11 +32,11 @@ class RoomCpProgressDialog extends StatelessWidget {
|
||||
required this.rightUser,
|
||||
this.daysValue = '999',
|
||||
this.daysLabel = 'Days',
|
||||
this.levelText = 'Lv.1 Simple Love',
|
||||
this.levelText = 'Lv.0',
|
||||
this.currentValue = 0,
|
||||
this.targetValue = 1,
|
||||
this.expAwayText = '0',
|
||||
this.nextLevelText = 'Lv. 2',
|
||||
this.nextLevelText = 'Lv. 1',
|
||||
this.cancelText = 'Cancel',
|
||||
this.dismissTag = dialogTag,
|
||||
this.onCancel,
|
||||
@ -62,11 +63,11 @@ class RoomCpProgressDialog extends StatelessWidget {
|
||||
required RoomCpProgressDialogUser rightUser,
|
||||
String daysValue = '999',
|
||||
String daysLabel = 'Days',
|
||||
String levelText = 'Lv.1 Simple Love',
|
||||
String levelText = 'Lv.0',
|
||||
double currentValue = 0,
|
||||
double targetValue = 1,
|
||||
String expAwayText = '0',
|
||||
String nextLevelText = 'Lv. 2',
|
||||
String nextLevelText = 'Lv. 1',
|
||||
String cancelText = 'Cancel',
|
||||
String dismissTag = dialogTag,
|
||||
VoidCallback? onCancel,
|
||||
@ -164,6 +165,7 @@ class RoomCpProgressDialog extends StatelessWidget {
|
||||
right: 0,
|
||||
top: 180.w,
|
||||
child: _ExpAwayText(
|
||||
levelText: levelText,
|
||||
expAwayText: expAwayText,
|
||||
nextLevelText: nextLevelText,
|
||||
),
|
||||
@ -203,7 +205,9 @@ class _DaysBadge extends StatelessWidget {
|
||||
final value = daysValue.trim().isEmpty ? '--' : daysValue.trim();
|
||||
final label = daysLabel.trim().isEmpty ? 'Days' : daysLabel.trim();
|
||||
final level =
|
||||
levelText.trim().isEmpty ? 'Lv.1 Simple Love' : levelText.trim();
|
||||
levelText.trim().isEmpty
|
||||
? 'Lv.0'
|
||||
: scCpRelationLevelDisplayText(levelText);
|
||||
|
||||
return SizedBox(
|
||||
width: 114.w,
|
||||
@ -407,16 +411,39 @@ class _ProgressBar extends StatelessWidget {
|
||||
}
|
||||
|
||||
class _ExpAwayText extends StatelessWidget {
|
||||
const _ExpAwayText({required this.expAwayText, required this.nextLevelText});
|
||||
const _ExpAwayText({
|
||||
required this.levelText,
|
||||
required this.expAwayText,
|
||||
required this.nextLevelText,
|
||||
});
|
||||
|
||||
final String levelText;
|
||||
final String expAwayText;
|
||||
final String nextLevelText;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (scCpRelationLevelIndex(levelText) >= 5) {
|
||||
return Text(
|
||||
'Maximum level reached.',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: const Color(0xff67576F),
|
||||
fontSize: 10.sp,
|
||||
fontWeight: FontWeight.w400,
|
||||
height: 1,
|
||||
decoration: TextDecoration.none,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final exp = expAwayText.trim().isEmpty ? '0' : expAwayText.trim();
|
||||
final nextLevel =
|
||||
nextLevelText.trim().isEmpty ? 'Lv. 2' : nextLevelText.trim();
|
||||
nextLevelText.trim().isEmpty
|
||||
? 'Lv. 1'
|
||||
: scCpRelationLevelDisplayText(nextLevelText);
|
||||
|
||||
return Text.rich(
|
||||
TextSpan(
|
||||
|
||||
@ -6,25 +6,22 @@ class SCCpCornerLabel extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ShaderMask(
|
||||
blendMode: BlendMode.srcIn,
|
||||
shaderCallback: (bounds) {
|
||||
return const LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [Color(0xffFF91A4), Color(0xffFF3164)],
|
||||
).createShader(bounds);
|
||||
},
|
||||
child: Text(
|
||||
"CP",
|
||||
textScaler: TextScaler.noScaling,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 10.sp,
|
||||
height: 1,
|
||||
fontWeight: FontWeight.w700,
|
||||
decoration: TextDecoration.none,
|
||||
),
|
||||
return Text(
|
||||
"CP",
|
||||
textScaler: TextScaler.noScaling,
|
||||
style: TextStyle(
|
||||
foreground:
|
||||
Paint()
|
||||
..shader = const LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [Color(0xffFF91A4), Color(0xffFF3164)],
|
||||
).createShader(Rect.fromLTWH(0, 0, 20.w, 10.w)),
|
||||
fontSize: 10.sp,
|
||||
height: 1,
|
||||
fontWeight: FontWeight.w700,
|
||||
decoration: TextDecoration.none,
|
||||
shadows: const <Shadow>[],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ class RoomPlayWidget extends StatefulWidget {
|
||||
|
||||
class _RoomPlayWidgetState extends State<RoomPlayWidget> {
|
||||
static const double _railEnd = 8;
|
||||
static const double _railBottom = 15;
|
||||
static const double _railBottom = 30;
|
||||
static const double _railWidth = 58;
|
||||
static const double _railVerticalPadding = 8;
|
||||
static const double _actionExtent = 56;
|
||||
@ -69,6 +69,7 @@ class _RoomPlayWidgetState extends State<RoomPlayWidget> {
|
||||
final fullHeight = _railHeight(
|
||||
actionCount: actions.length,
|
||||
showToggle: false,
|
||||
showBackground: false,
|
||||
);
|
||||
final availableHeight =
|
||||
(constraints.maxHeight - _railBottom.w)
|
||||
@ -78,17 +79,20 @@ class _RoomPlayWidgetState extends State<RoomPlayWidget> {
|
||||
actions.length > _compactActionCount &&
|
||||
availableHeight < fullHeight;
|
||||
final isExpanded = !shouldFold || _rightActionsExpanded;
|
||||
final isCollapsed = shouldFold && !isExpanded;
|
||||
final visibleActions =
|
||||
isExpanded ? actions : actions.take(_compactActionCount).toList();
|
||||
final railHeight = _railHeight(
|
||||
actionCount: visibleActions.length,
|
||||
showToggle: shouldFold,
|
||||
showBackground: isCollapsed,
|
||||
);
|
||||
|
||||
Widget rail = _RoomSideActionRail(
|
||||
actions: visibleActions,
|
||||
showToggle: shouldFold,
|
||||
expanded: isExpanded,
|
||||
showBackground: isCollapsed,
|
||||
onToggle: () {
|
||||
setState(() {
|
||||
_rightActionsExpanded = !_rightActionsExpanded;
|
||||
@ -144,11 +148,16 @@ class _RoomPlayWidgetState extends State<RoomPlayWidget> {
|
||||
false;
|
||||
}
|
||||
|
||||
double _railHeight({required int actionCount, required bool showToggle}) {
|
||||
double _railHeight({
|
||||
required int actionCount,
|
||||
required bool showToggle,
|
||||
required bool showBackground,
|
||||
}) {
|
||||
final actionGaps = actionCount > 1 ? actionCount - 1 : 0;
|
||||
final toggleHeight =
|
||||
showToggle ? _toggleExtent + (actionCount > 0 ? _actionGap : 0) : 0.0;
|
||||
return (_railVerticalPadding * 2 +
|
||||
final verticalPadding = showBackground ? _railVerticalPadding * 2 : 0.0;
|
||||
return (verticalPadding +
|
||||
toggleHeight +
|
||||
actionCount * _actionExtent +
|
||||
actionGaps * _actionGap)
|
||||
@ -180,6 +189,7 @@ class _RoomSideActionRail extends StatelessWidget {
|
||||
required this.actions,
|
||||
required this.showToggle,
|
||||
required this.expanded,
|
||||
required this.showBackground,
|
||||
required this.onToggle,
|
||||
required this.actionBuilder,
|
||||
});
|
||||
@ -187,6 +197,7 @@ class _RoomSideActionRail extends StatelessWidget {
|
||||
final List<_RoomSideAction> actions;
|
||||
final bool showToggle;
|
||||
final bool expanded;
|
||||
final bool showBackground;
|
||||
final VoidCallback onToggle;
|
||||
final Widget Function(_RoomSideAction action) actionBuilder;
|
||||
|
||||
@ -223,12 +234,16 @@ class _RoomSideActionRail extends StatelessWidget {
|
||||
width: _RoomPlayWidgetState._railWidth.w,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 6.w,
|
||||
vertical: _RoomPlayWidgetState._railVerticalPadding.w,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black.withValues(alpha: 0.21),
|
||||
borderRadius: BorderRadius.circular(8.w),
|
||||
vertical:
|
||||
showBackground ? _RoomPlayWidgetState._railVerticalPadding.w : 0,
|
||||
),
|
||||
decoration:
|
||||
showBackground
|
||||
? BoxDecoration(
|
||||
color: Colors.black.withValues(alpha: 0.21),
|
||||
borderRadius: BorderRadius.circular(8.w),
|
||||
)
|
||||
: null,
|
||||
child: Column(mainAxisSize: MainAxisSize.min, children: children),
|
||||
);
|
||||
}
|
||||
|
||||
@ -760,9 +760,7 @@ class _RoomUserInfoCardState extends State<RoomUserInfoCard> {
|
||||
levelText:
|
||||
cp == null
|
||||
? ""
|
||||
: _cpLevelDisplayText(
|
||||
_firstNonBlank([cp.levelText, "Lv.1 Simple Love"]),
|
||||
),
|
||||
: _cpLevelDisplayText(_firstNonBlank([cp.levelText, "Lv.0"])),
|
||||
);
|
||||
}
|
||||
|
||||
@ -835,7 +833,12 @@ class _RoomUserInfoCardState extends State<RoomUserInfoCard> {
|
||||
}
|
||||
|
||||
String _cpLevelAsset(String levelText) {
|
||||
return "$_cpProfileAssetBase/sc_cp_profile_cp_level_${_cpLevelIndex(levelText)}.png";
|
||||
return "$_cpProfileAssetBase/sc_cp_profile_cp_level_${_cpLevelAssetIndex(levelText)}.png";
|
||||
}
|
||||
|
||||
int _cpLevelAssetIndex(String levelText) {
|
||||
final level = _cpLevelIndex(levelText);
|
||||
return level <= 0 ? 1 : level;
|
||||
}
|
||||
|
||||
int _cpLevelIndex(String levelText) {
|
||||
@ -910,19 +913,7 @@ class _RoomUserInfoCardState extends State<RoomUserInfoCard> {
|
||||
}
|
||||
|
||||
String _normalizeCpRelationType(String? relationType) {
|
||||
final value = relationType?.trim().toUpperCase() ?? "";
|
||||
switch (value) {
|
||||
case "BROTHER":
|
||||
case "BROTHERS":
|
||||
case "SWORN_BROTHER":
|
||||
case "SWORN_BROTHERS":
|
||||
return "BROTHER";
|
||||
case "SISTER":
|
||||
case "SISTERS":
|
||||
return "SISTERS";
|
||||
default:
|
||||
return "CP";
|
||||
}
|
||||
return scNormalizeCpRelationType(relationType);
|
||||
}
|
||||
|
||||
String _avatarFallback(String? avatarUrl) {
|
||||
@ -1818,8 +1809,7 @@ class _RoomCpProgressData {
|
||||
factory _RoomCpProgressData.fallback(_RoomProfileCpData cp) {
|
||||
final currentValue = cp.cpValue;
|
||||
return _RoomCpProgressData(
|
||||
levelText:
|
||||
cp.levelText.trim().isEmpty ? "Lv.1 Simple Love" : cp.levelText,
|
||||
levelText: scCpRelationLevelDisplayText(cp.levelText),
|
||||
currentValue: currentValue,
|
||||
targetValue: currentValue > 0 ? currentValue : 1,
|
||||
expAwayText: SCStringUtils.formatCompactNumber(0),
|
||||
@ -1932,16 +1922,19 @@ class _RoomCpProgressData {
|
||||
static String _levelDisplayText(_CpProgressLevel? level, String fallback) {
|
||||
final fallbackText = fallback.trim();
|
||||
if (level == null) {
|
||||
return fallbackText.isEmpty ? "Lv.1 Simple Love" : fallbackText;
|
||||
return scCpRelationLevelDisplayText(fallbackText);
|
||||
}
|
||||
final levelName = level.levelName?.trim();
|
||||
if (level.level != null && levelName != null && levelName.isNotEmpty) {
|
||||
return scCpRelationLevelDisplayText("Lv.${level.level} $levelName");
|
||||
}
|
||||
if (levelName != null && levelName.isNotEmpty) {
|
||||
return levelName;
|
||||
return scCpRelationLevelDisplayText(levelName);
|
||||
}
|
||||
if (level.level != null) {
|
||||
return "Lv.${level.level}";
|
||||
}
|
||||
return fallbackText.isEmpty ? "Lv.1 Simple Love" : fallbackText;
|
||||
return scCpRelationLevelDisplayText(fallbackText);
|
||||
}
|
||||
|
||||
static String _levelShortText(int? level, {String? fallback}) {
|
||||
@ -1950,9 +1943,9 @@ class _RoomCpProgressData {
|
||||
}
|
||||
final fallbackText = fallback?.trim() ?? "";
|
||||
if (fallbackText.isNotEmpty) {
|
||||
return fallbackText;
|
||||
return scCpRelationLevelDisplayText(fallbackText);
|
||||
}
|
||||
return "Lv. 1";
|
||||
return "Lv. 0";
|
||||
}
|
||||
|
||||
static int _levelIndex(String levelText) {
|
||||
@ -1960,7 +1953,7 @@ class _RoomCpProgressData {
|
||||
}
|
||||
|
||||
static int _nextLevelIndex(int level) {
|
||||
return (level + 1).clamp(1, 5).toInt();
|
||||
return (level + 1).clamp(0, 5).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -165,7 +165,7 @@ class _RoomMicRelationEffectState extends State<RoomMicRelationEffect> {
|
||||
}
|
||||
|
||||
List<_RoomMicRelationAsset> _cpAssetsForLevel(int? cpLevel) {
|
||||
final level = (cpLevel ?? 1).clamp(1, 5).toInt();
|
||||
final level = (cpLevel ?? 0).clamp(0, 5).toInt();
|
||||
switch (level) {
|
||||
case 2:
|
||||
return const [
|
||||
|
||||
@ -715,16 +715,6 @@ Widget _buildBagCardSkeleton(double progress, {required bool showTitle}) {
|
||||
),
|
||||
),
|
||||
),
|
||||
PositionedDirectional(
|
||||
bottom: 0,
|
||||
end: 0,
|
||||
child: _buildStoreBagSkeletonBone(
|
||||
progress,
|
||||
width: 18.w,
|
||||
height: 18.w,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
),
|
||||
Column(
|
||||
mainAxisSize: showTitle ? MainAxisSize.max : MainAxisSize.min,
|
||||
children: [
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
package io.flutter.plugins;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
import androidx.annotation.NonNull;
|
||||
import io.flutter.Log;
|
||||
|
||||
import io.flutter.embedding.engine.FlutterEngine;
|
||||
|
||||
/**
|
||||
* Generated file. Do not edit.
|
||||
* This file is generated by the Flutter tool based on the
|
||||
* plugins that support the Android platform.
|
||||
*/
|
||||
@Keep
|
||||
public final class GeneratedPluginRegistrant {
|
||||
private static final String TAG = "GeneratedPluginRegistrant";
|
||||
public static void registerWith(@NonNull FlutterEngine flutterEngine) {
|
||||
try {
|
||||
flutterEngine.getPlugins().add(new com.example.flutter_pag_plugin.FlutterPagPlugin());
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error registering plugin pag, com.example.flutter_pag_plugin.FlutterPagPlugin", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
sdk.dir=/Users/nigger/Library/Android/sdk
|
||||
flutter.sdk=/Users/nigger/Desktop/develop/flutter
|
||||
@ -0,0 +1,14 @@
|
||||
// This is a generated file; do not edit or check into version control.
|
||||
FLUTTER_ROOT=/Users/nigger/Desktop/develop/flutter
|
||||
FLUTTER_APPLICATION_PATH=/Users/nigger/Documents/GitHub/chatapp3-flutter/local_packages/pag-1.0.7-patched/example
|
||||
COCOAPODS_PARALLEL_CODE_SIGN=true
|
||||
FLUTTER_TARGET=lib/main.dart
|
||||
FLUTTER_BUILD_DIR=build
|
||||
FLUTTER_BUILD_NAME=1.0.0
|
||||
FLUTTER_BUILD_NUMBER=1
|
||||
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
|
||||
EXCLUDED_ARCHS[sdk=iphoneos*]=armv7
|
||||
DART_OBFUSCATION=false
|
||||
TRACK_WIDGET_CREATION=true
|
||||
TREE_SHAKE_ICONS=false
|
||||
PACKAGE_CONFIG=.dart_tool/package_config.json
|
||||
@ -0,0 +1,32 @@
|
||||
#
|
||||
# Generated file, do not edit.
|
||||
#
|
||||
|
||||
import lldb
|
||||
|
||||
def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_dict):
|
||||
"""Intercept NOTIFY_DEBUGGER_ABOUT_RX_PAGES and touch the pages."""
|
||||
base = frame.register["x0"].GetValueAsAddress()
|
||||
page_len = frame.register["x1"].GetValueAsUnsigned()
|
||||
|
||||
# Note: NOTIFY_DEBUGGER_ABOUT_RX_PAGES will check contents of the
|
||||
# first page to see if handled it correctly. This makes diagnosing
|
||||
# misconfiguration (e.g. missing breakpoint) easier.
|
||||
data = bytearray(page_len)
|
||||
data[0:8] = b'IHELPED!'
|
||||
|
||||
error = lldb.SBError()
|
||||
frame.GetThread().GetProcess().WriteMemory(base, data, error)
|
||||
if not error.Success():
|
||||
print(f'Failed to write into {base}[+{page_len}]', error)
|
||||
return
|
||||
|
||||
def __lldb_init_module(debugger: lldb.SBDebugger, _):
|
||||
target = debugger.GetDummyTarget()
|
||||
# Caveat: must use BreakpointCreateByRegEx here and not
|
||||
# BreakpointCreateByName. For some reasons callback function does not
|
||||
# get carried over from dummy target for the later.
|
||||
bp = target.BreakpointCreateByRegex("^NOTIFY_DEBUGGER_ABOUT_RX_PAGES$")
|
||||
bp.SetScriptCallbackFunction('{}.handle_new_rx_page'.format(__name__))
|
||||
bp.SetAutoContinue(True)
|
||||
print("-- LLDB integration loaded --")
|
||||
@ -0,0 +1,5 @@
|
||||
#
|
||||
# Generated file, do not edit.
|
||||
#
|
||||
|
||||
command script import --relative-to-command-file flutter_lldb_helper.py
|
||||
@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
# This is a generated file; do not edit or check into version control.
|
||||
export "FLUTTER_ROOT=/Users/nigger/Desktop/develop/flutter"
|
||||
export "FLUTTER_APPLICATION_PATH=/Users/nigger/Documents/GitHub/chatapp3-flutter/local_packages/pag-1.0.7-patched/example"
|
||||
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
|
||||
export "FLUTTER_TARGET=lib/main.dart"
|
||||
export "FLUTTER_BUILD_DIR=build"
|
||||
export "FLUTTER_BUILD_NAME=1.0.0"
|
||||
export "FLUTTER_BUILD_NUMBER=1"
|
||||
export "DART_OBFUSCATION=false"
|
||||
export "TRACK_WIDGET_CREATION=true"
|
||||
export "TREE_SHAKE_ICONS=false"
|
||||
export "PACKAGE_CONFIG=.dart_tool/package_config.json"
|
||||
@ -0,0 +1,19 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifndef GeneratedPluginRegistrant_h
|
||||
#define GeneratedPluginRegistrant_h
|
||||
|
||||
#import <Flutter/Flutter.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface GeneratedPluginRegistrant : NSObject
|
||||
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
#endif /* GeneratedPluginRegistrant_h */
|
||||
@ -0,0 +1,21 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#import "GeneratedPluginRegistrant.h"
|
||||
|
||||
#if __has_include(<pag/FlutterPagPlugin.h>)
|
||||
#import <pag/FlutterPagPlugin.h>
|
||||
#else
|
||||
@import pag;
|
||||
#endif
|
||||
|
||||
@implementation GeneratedPluginRegistrant
|
||||
|
||||
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry {
|
||||
[FlutterPagPlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterPagPlugin"]];
|
||||
}
|
||||
|
||||
@end
|
||||
204
local_packages/pag-1.0.7-patched/example/pubspec.lock
Normal file
204
local_packages/pag-1.0.7-patched/example/pubspec.lock
Normal file
@ -0,0 +1,204 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.13.1"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.19.1"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: cupertino_icons
|
||||
sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.9"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.3.3"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "11.0.2"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.10"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_testing
|
||||
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.12.19"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.13.0"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.17.0"
|
||||
pag:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "1.0.7"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.10.2"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.12.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.2.2"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.7.10"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "15.2.0"
|
||||
sdks:
|
||||
dart: ">=3.9.0 <4.0.0"
|
||||
flutter: ">=3.18.0-18.0.pre.54"
|
||||
189
local_packages/pag-1.0.7-patched/pubspec.lock
Normal file
189
local_packages/pag-1.0.7-patched/pubspec.lock
Normal file
@ -0,0 +1,189 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.13.1"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.19.1"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.3.3"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "11.0.2"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.10"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_testing
|
||||
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.12.19"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.13.0"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.17.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.10.2"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.12.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.2.2"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.7.10"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "15.2.0"
|
||||
sdks:
|
||||
dart: ">=3.9.0-0 <4.0.0"
|
||||
flutter: ">=3.18.0-18.0.pre.54"
|
||||
@ -40,6 +40,17 @@ void main() {
|
||||
expect(scCpRelationDisplayDays('12'), '13');
|
||||
expect(scCpRelationDisplayDays(''), '1');
|
||||
});
|
||||
|
||||
test('relation entry notice uses party copy', () {
|
||||
expect(
|
||||
scBuildCpRelationEntryBroadcastText(
|
||||
ownerName: 'A',
|
||||
joinedName: 'B',
|
||||
relationType: 'CP',
|
||||
),
|
||||
"A's cp B has joined the party",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('scCpRelationTypeForGift', () {
|
||||
|
||||
@ -195,6 +195,52 @@ void main() {
|
||||
expect(levels?.last.progressImageUrl, 'progress-2');
|
||||
});
|
||||
|
||||
test('parses realtime level advancement payloads', () {
|
||||
final status = SCRoomRocketStatusRes.fromJson({
|
||||
'room_id': 'room-1',
|
||||
'from_level': 1,
|
||||
'to_level': 2,
|
||||
'display_percent': 0,
|
||||
});
|
||||
|
||||
expect(status.currentLevel, 2);
|
||||
expect(status.level, 2);
|
||||
expect(status.displayPercent, 0);
|
||||
});
|
||||
|
||||
test('merges realtime rocket status without dropping level assets', () {
|
||||
final current = SCRoomRocketStatusRes.fromJson({
|
||||
'room_id': 'room-1',
|
||||
'current_level': 1,
|
||||
'display_percent': 98,
|
||||
'levels': [
|
||||
{
|
||||
'level': 1,
|
||||
'rocket_icon_url': 'icon-1',
|
||||
'progress_bar_url': 'progress-1',
|
||||
},
|
||||
{
|
||||
'level': 2,
|
||||
'rocket_icon_url': 'icon-2',
|
||||
'progress_bar_url': 'progress-2',
|
||||
},
|
||||
],
|
||||
});
|
||||
final realtimeUpdate = SCRoomRocketStatusRes.fromJson({
|
||||
'room_id': 'room-1',
|
||||
'to_level': 2,
|
||||
'display_percent': 0,
|
||||
});
|
||||
|
||||
final merged = current.mergeRealtimeUpdate(realtimeUpdate);
|
||||
final levels = RoomRocketApiMapper.levelsFromStatus(merged);
|
||||
|
||||
expect(merged.currentLevel, 2);
|
||||
expect(merged.displayPercent, 0);
|
||||
expect(levels?.last.imageUrl, 'icon-2');
|
||||
expect(levels?.last.progressImageUrl, 'progress-2');
|
||||
});
|
||||
|
||||
test('parses disabled rocket status from go api', () {
|
||||
final status = SCRoomRocketStatusRes.fromJson({
|
||||
'configured': true,
|
||||
|
||||
@ -53,6 +53,22 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
test('detects close-friend relation aliases parsed from payload', () {
|
||||
final left = SocialChatUserProfile(id: '300');
|
||||
final right = SocialChatUserProfile(
|
||||
id: '400',
|
||||
closeFriendList: [
|
||||
CPRes.fromJson({
|
||||
'meUserId': '300',
|
||||
'cpUserId': '400',
|
||||
'cpRelationType': 'sis',
|
||||
}),
|
||||
],
|
||||
);
|
||||
|
||||
expect(scCpRelationTypeBetweenProfiles(left, right), 'SISTERS');
|
||||
});
|
||||
|
||||
test('does not match unrelated profiles', () {
|
||||
final left = SocialChatUserProfile(
|
||||
id: '100',
|
||||
@ -78,5 +94,34 @@ void main() {
|
||||
|
||||
expect(scCpRelationLevelTextFromCabin(cabin), 'Lv.2 Sweet Love');
|
||||
});
|
||||
|
||||
test(
|
||||
'supports zero based CP levels and hides hardcoded simple love copy',
|
||||
() {
|
||||
expect(scCpRelationLevelIndex('Lv.0'), 0);
|
||||
expect(scCpRelationLevelDisplayText(null), 'Lv.0');
|
||||
expect(scCpRelationLevelDisplayText('Lv.1 Simple Love'), 'Lv.1');
|
||||
|
||||
final cabin = SCCpCabinRes(
|
||||
cpVal: 0,
|
||||
cpCabinConfigCO: const [
|
||||
{'level': 0, 'levelName': 'Start', 'requiredCpValue': 0},
|
||||
{'level': 1, 'levelName': 'Simple Love', 'requiredCpValue': 100},
|
||||
],
|
||||
);
|
||||
|
||||
expect(scCpRelationLevelTextFromCabin(cabin), 'Lv.0 Start');
|
||||
|
||||
final levelOneCabin = SCCpCabinRes(
|
||||
cpVal: 100,
|
||||
cpCabinConfigCO: const [
|
||||
{'level': 0, 'levelName': 'Start', 'requiredCpValue': 0},
|
||||
{'level': 1, 'levelName': 'Simple Love', 'requiredCpValue': 100},
|
||||
],
|
||||
);
|
||||
|
||||
expect(scCpRelationLevelTextFromCabin(levelOneCabin), 'Lv.1');
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user