Merge branch 'feature' of gitea.haiyihy.com:hy/chatapp3-flutter into feature

This commit is contained in:
zhx 2026-05-16 04:40:26 +08:00
commit faaeeded32
6 changed files with 398 additions and 41 deletions

View File

@ -724,7 +724,7 @@
"roomRocketNoteTitle": "Note",
"roomRocketNoteSectionTitle": "Each time a VIP",
"roomRocketNoteSectionBody": "1. Each time a VIP level is purchased, it is valid for 30 days, and can be manually renewed after expiration.",
"roomRocketRewardEmptyText": "No rewards earned. Better luck next time.",
"roomRocketRewardEmptyText": "No reward",
"roomRocketRecordEmptyText": "No reward records",
"launchRocket": "Launch Rocket",
"roomRocketFuelFullNotice": "Rocket fuel is full! Launching in {1}s!"

View File

@ -560,7 +560,6 @@ class _VoiceRoomPageState extends State<VoiceRoomPage>
///
_floatingGiftListener(Msg msg) {
final rtcProvider = Provider.of<RtcProvider>(context, listen: false);
rtcProvider.scheduleRoomRocketStatusRefreshForGift();
if (!rtcProvider.shouldShowRoomVisualEffects) {
return;
}

View File

@ -305,6 +305,12 @@ class RealTimeCommunicationManager extends ChangeNotifier {
Duration(seconds: 5),
Duration(seconds: 10),
];
static const List<Duration> _roomRocketEntryReadyFallbackDelays = [
Duration(milliseconds: 300),
Duration(milliseconds: 900),
Duration(milliseconds: 1800),
Duration(milliseconds: 3200),
];
static const int _roomPasswordNotTrueErrorCode = 9005;
static const Duration _micListPollingInterval = Duration(seconds: 2);
@ -347,6 +353,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
ValueNotifier<String?>? _roomRocketLaunchTopAvatarNotifier;
Timer? _roomRocketGiftRefreshTimer;
final List<Timer> _roomRocketPostLaunchRefreshTimers = [];
final List<Timer> _roomRocketEntryReadyFallbackTimers = [];
Timer? _roomRedPacketPresenceTimer;
Future<void>? _rtcEnginePrewarmTask;
Future<void>? _pendingRoomSwitchRtcLeaveTask;
@ -495,6 +502,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
_releaseRoomRocketLaunchTopAvatarNotifier();
_roomRocketGiftRefreshTimer?.cancel();
_roomRocketGiftRefreshTimer = null;
_cancelRoomRocketEntryReadyFallbacks();
_cancelRoomRocketPostLaunchStatusRefresh();
}
_roomVisualEffectsEnabled = enabled;
@ -506,7 +514,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
if (visible) {
final roomId = (currenRoom?.roomProfile?.roomProfile?.id ?? "").trim();
if (roomId.isNotEmpty) {
rtmProvider?.handleVoiceRoomReadyForRocketRewards(roomId);
_scheduleRoomRocketEntryReadyFallback(roomId);
}
}
}
@ -2603,6 +2611,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
setRoomVisualEffectsEnabled(true);
if (shouldOpenRoomPage) {
VoiceRoomRoute.openVoiceRoom(context!);
setVoiceRoomRouteVisible(true);
}
unawaited(
_bootstrapEnteredVoiceRoomSession(
@ -2703,7 +2712,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
roomId: roomId,
);
_loadRoomSecondaryData();
rtmProvider?.handleVoiceRoomReadyForRocketRewards(roomId);
_scheduleRoomRocketEntryReadyFallback(roomId);
} catch (error, stackTrace) {
if (!_isActiveRoomStartup(entryRequestSerial, roomId)) {
return;
@ -2825,6 +2834,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
roomRocketStatus = res;
notifyListeners();
_scheduleRoomRocketAssetPreload(roomId, res, afterRoomEntry: true);
_scheduleRoomRocketEntryReadyFallback(roomId);
})
.catchError((e) {});
_loadRoomRocketRewardPopups(roomId);
@ -2947,6 +2957,42 @@ class RealTimeCommunicationManager extends ChangeNotifier {
});
}
void _scheduleRoomRocketEntryReadyFallback(String roomId) {
final normalizedRoomId = roomId.trim();
if (normalizedRoomId.isEmpty) {
return;
}
_notifyRoomRocketEntryReadyIfCurrent(normalizedRoomId);
for (final delay in _roomRocketEntryReadyFallbackDelays) {
final timer = Timer(delay, () {
_roomRocketEntryReadyFallbackTimers.removeWhere(
(item) => !item.isActive,
);
_notifyRoomRocketEntryReadyIfCurrent(normalizedRoomId);
});
_roomRocketEntryReadyFallbackTimers.add(timer);
}
}
void _notifyRoomRocketEntryReadyIfCurrent(String roomId) {
final normalizedRoomId = roomId.trim();
final currentRoomId =
currenRoom?.roomProfile?.roomProfile?.id?.trim() ?? "";
if (normalizedRoomId.isEmpty ||
currentRoomId != normalizedRoomId ||
!_voiceRoomRouteVisible) {
return;
}
rtmProvider?.handleVoiceRoomReadyForRocketRewards(normalizedRoomId);
}
void _cancelRoomRocketEntryReadyFallbacks() {
for (final timer in _roomRocketEntryReadyFallbackTimers) {
timer.cancel();
}
_roomRocketEntryReadyFallbackTimers.clear();
}
void scheduleRoomRocketPostLaunchStatusRefresh({String? roomId}) {
final resolvedRoomId =
(roomId ?? currenRoom?.roomProfile?.roomProfile?.id ?? "").trim();
@ -3482,9 +3528,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
final exitRtmProvider = rtmProvider;
final navigationContext = context;
try {
exitRtmProvider?.msgAllListener = null;
exitRtmProvider?.msgChatListener = null;
exitRtmProvider?.msgGiftListener = null;
SCGiftVapSvgaManager().stopPlayback();
setRoomVisualEffectsEnabled(false);
SCHeartbeatUtils.cancelTimer();
@ -3520,9 +3563,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
final isPreviewOnlyExit = _currentRoomIsEntryPreview;
final exitRtmProvider = rtmProvider;
try {
exitRtmProvider?.msgAllListener = null;
exitRtmProvider?.msgChatListener = null;
exitRtmProvider?.msgGiftListener = null;
SCGiftVapSvgaManager().stopPlayback();
setRoomVisualEffectsEnabled(false);
SCHeartbeatUtils.cancelTimer();

View File

@ -135,6 +135,7 @@ class RealTimeMessagingManager extends ChangeNotifier {
static const int _roomRocketRegionBroadcastRecentTtlMs = 90000;
static const int _roomRocketRewardPendingTtlMs = 120000;
static const int _roomRocketRewardProbeTtlMs = 120000;
static const int _roomRocketLaunchCountdownRetainMs = 10000;
static const Duration _createRoomGroupTimeout = Duration(seconds: 12);
static const List<Duration> _roomRocketRewardPopupRetryDelays = [
Duration(milliseconds: 700),
@ -262,6 +263,12 @@ class RealTimeMessagingManager extends ChangeNotifier {
final _pendingRoomRocketRewardPopups =
<String, _PendingRoomRocketRewardPopup>{};
final Map<String, int> _recentRoomRocketRewardProbeTimes = <String, int>{};
final Map<String, int> _roomRocketLaunchCountdownDueTimes = <String, int>{};
final Map<String, String> _roomRocketLaunchCountdownKeysByRoom =
<String, String>{};
final _pendingRoomRocketCountdownLaunches =
<String, RoomRocketLaunchBroadcastMessage>{};
final Map<String, Timer> _roomRocketLaunchEffectTimers = <String, Timer>{};
Timer? _roomRocketRewardPopupRetryTimer;
Timer? _roomRocketRoomReadyRewardRetryTimer;
int get currentLuckGiftBurstPlaybackToken => _luckGiftPushPlaybackToken;
@ -1163,6 +1170,7 @@ class RealTimeMessagingManager extends ChangeNotifier {
}
addMsg(Msg msg) {
_scheduleRoomRocketStatusRefreshForGiftMessage(msg);
final mergedGiftMsg = _mergeGiftMessageIfNeeded(msg);
if (mergedGiftMsg != null) {
msgAllListener?.call(mergedGiftMsg);
@ -1249,6 +1257,33 @@ class RealTimeMessagingManager extends ChangeNotifier {
}
}
void _scheduleRoomRocketStatusRefreshForGiftMessage(Msg msg) {
if (msg.type != SCRoomMsgType.gift &&
msg.type != SCRoomMsgType.luckGiftAnimOther) {
return;
}
final currentContext = context;
if (currentContext == null || !currentContext.mounted) {
return;
}
final rtcProvider = Provider.of<RealTimeCommunicationManager>(
currentContext,
listen: false,
);
final currentRoomId =
(rtcProvider.currenRoom?.roomProfile?.roomProfile?.id ?? '').trim();
if (currentRoomId.isEmpty) {
return;
}
final messageRoomId = msg.type == SCRoomMsgType.gift ? msg.msg?.trim() : '';
if (messageRoomId != null &&
messageRoomId.isNotEmpty &&
messageRoomId != currentRoomId) {
return;
}
rtcProvider.scheduleRoomRocketStatusRefreshForGift(roomId: currentRoomId);
}
void _cacheRoomRedPacketMessage(Msg msg) {
try {
final decoded = jsonDecode(msg.msg ?? '');
@ -1985,6 +2020,7 @@ class RealTimeMessagingManager extends ChangeNotifier {
publishRegionBroadcast: true,
);
} else {
_rememberRoomRocketLaunchCountdown(launch);
_markRoomRocketRewardProbe(launch.roomId);
_publishRoomRocketRegionBroadcastIfNeeded(launch);
}
@ -2002,6 +2038,7 @@ class RealTimeMessagingManager extends ChangeNotifier {
if (!launch.isValid) {
return;
}
_rememberRoomRocketLaunchCountdown(launch);
var isCurrentRoom = false;
var isCurrentVisibleRoom = false;
@ -2092,14 +2129,22 @@ class RealTimeMessagingManager extends ChangeNotifier {
final pending = _pendingRoomRocketRewardPopups[normalizedRoomId];
final hasProbe =
_recentRoomRocketRewardProbeTimes[normalizedRoomId] != null;
if (pending == null && !hasProbe) {
final hasLaunch =
_pendingRoomRocketCountdownLaunches[normalizedRoomId] != null;
if (pending == null && !hasProbe && !hasLaunch) {
return;
}
if (!_isCurrentVisibleVoiceRoom(normalizedRoomId)) {
_scheduleRoomRocketReadyRewardRetry(normalizedRoomId, attempt);
return;
}
if (pending == null && attempt == 0) {
final resumedLaunch = _resumeRoomRocketLaunchForCurrentRoom(
normalizedRoomId,
);
if (pending == null && !hasProbe) {
return;
}
if (!resumedLaunch && pending == null && attempt == 0) {
_scheduleRoomRocketReadyRewardRetry(normalizedRoomId, attempt);
return;
}
@ -2180,15 +2225,219 @@ class RealTimeMessagingManager extends ChangeNotifier {
_recentRoomRocketRewardProbeTimes.clear();
_roomRocketRoomReadyRewardRetryTimer?.cancel();
_roomRocketRoomReadyRewardRetryTimer = null;
_clearRoomRocketLaunchCountdownState();
}
void _rememberRoomRocketLaunchCountdown(
RoomRocketLaunchBroadcastMessage launch,
) {
if (!launch.isValid) {
return;
}
final now = DateTime.now().millisecondsSinceEpoch;
_pruneRoomRocketLaunchCountdowns(now);
final key = _roomRocketLaunchCountdownKey(launch);
final existingDueAt = _roomRocketLaunchCountdownDueTimes[key];
final dueAt =
existingDueAt != null && existingDueAt > now
? existingDueAt
: now + _roomRocketLaunchCountdownDelay(launch).inMilliseconds;
_roomRocketLaunchCountdownDueTimes[key] = dueAt;
_roomRocketLaunchCountdownKeysByRoom[launch.roomId] = key;
_pendingRoomRocketCountdownLaunches[launch.roomId] = launch;
}
void _scheduleRoomRocketLaunchEffectsAfterCountdown(
RoomRocketLaunchBroadcastMessage launch,
) {
if (!launch.isValid) {
return;
}
_rememberRoomRocketLaunchCountdown(launch);
final key = _roomRocketLaunchCountdownKey(launch);
final delay = _roomRocketLaunchCountdownRemaining(launch.roomId);
final dueAt =
_roomRocketLaunchCountdownDueTimes[key] ??
DateTime.now().millisecondsSinceEpoch;
_roomRocketLaunchEffectTimers[key]?.cancel();
_roomRocketLaunchEffectTimers[key] = Timer(delay, () {
_roomRocketLaunchEffectTimers.remove(key);
if (_roomRocketLaunchCountdownDueTimes[key] != dueAt) {
return;
}
_roomRocketLaunchCountdownDueTimes.remove(key);
if (_roomRocketLaunchCountdownKeysByRoom[launch.roomId] == key) {
_roomRocketLaunchCountdownKeysByRoom.remove(launch.roomId);
}
final pendingLaunch =
_pendingRoomRocketCountdownLaunches.remove(launch.roomId) ?? launch;
_playRoomRocketLaunchEffectsAndReward(pendingLaunch);
});
}
void _playRoomRocketLaunchEffectsAndReward(
RoomRocketLaunchBroadcastMessage launch,
) {
_clearRoomRocketLaunchCountdownForRoom(launch.roomId);
if (!_isCurrentVisibleVoiceRoom(launch.roomId)) {
_markRoomRocketRewardProbe(launch.roomId);
return;
}
final currentContext = context;
if (currentContext == null || !currentContext.mounted) {
_markRoomRocketRewardProbe(launch.roomId);
return;
}
final rtcProvider = Provider.of<RealTimeCommunicationManager>(
currentContext,
listen: false,
);
final shouldFetchReward =
_pendingRoomRocketRewardPopups.containsKey(launch.roomId) ||
_recentRoomRocketRewardProbeTimes.containsKey(launch.roomId);
final pending = _pendingRoomRocketRewardPopups.remove(launch.roomId);
_recentRoomRocketRewardProbeTimes.remove(launch.roomId);
rtcProvider.handleRoomRocketLaunchBroadcast(launch);
if (shouldFetchReward) {
unawaited(
_showRoomRocketRewardPopupDialog(
launch.roomId,
initialRoomRecords:
pending?.initialRoomRecords ??
const <SCRoomRocketRewardRecordRes>[],
),
);
}
}
bool _resumeRoomRocketLaunchForCurrentRoom(String roomId) {
final normalizedRoomId = roomId.trim();
final launch = _pendingRoomRocketCountdownLaunches[normalizedRoomId];
if (launch == null || !_isCurrentVisibleVoiceRoom(normalizedRoomId)) {
return false;
}
final currentContext = context;
if (currentContext == null || !currentContext.mounted) {
return false;
}
final rtcProvider = Provider.of<RealTimeCommunicationManager>(
currentContext,
listen: false,
);
final remaining = _roomRocketLaunchCountdownRemaining(normalizedRoomId);
if (remaining > Duration.zero) {
_addRoomRocketLaunchNoticeIfNeeded(
rtcProvider: rtcProvider,
launch: launch,
secondsOverride: _roomRocketRemainingSeconds(remaining),
);
_scheduleRoomRocketLaunchEffectsAfterCountdown(launch);
} else {
_playRoomRocketLaunchEffectsAndReward(launch);
}
return true;
}
int _roomRocketRemainingSeconds(Duration duration) {
final seconds = (duration.inMilliseconds / 1000).ceil();
return seconds.clamp(1, 60).toInt();
}
Duration _roomRocketLaunchCountdownRemaining(String roomId) {
final normalizedRoomId = roomId.trim();
if (normalizedRoomId.isEmpty) {
return Duration.zero;
}
final now = DateTime.now().millisecondsSinceEpoch;
_pruneRoomRocketLaunchCountdowns(now);
final key = _roomRocketLaunchCountdownKeysByRoom[normalizedRoomId];
final dueAt = key == null ? null : _roomRocketLaunchCountdownDueTimes[key];
if (dueAt == null || dueAt <= now) {
return Duration.zero;
}
return Duration(milliseconds: dueAt - now);
}
Duration _roomRocketLaunchCountdownDelay(
RoomRocketLaunchBroadcastMessage launch,
) {
final seconds = launch.durationSeconds <= 0 ? 10 : launch.durationSeconds;
return Duration(seconds: seconds.clamp(0, 60).toInt());
}
String _roomRocketLaunchCountdownKey(
RoomRocketLaunchBroadcastMessage launch,
) {
final launchKey = _roomRocketLaunchNoticeKey(launch);
if (launchKey.isNotEmpty) {
return launchKey;
}
return 'rocket_launch_countdown|${launch.roomId}';
}
void _pruneRoomRocketLaunchCountdowns(int now) {
final expiredKeys = <String>{};
_roomRocketLaunchCountdownDueTimes.removeWhere((key, dueAt) {
final expired = now - dueAt > _roomRocketLaunchCountdownRetainMs;
if (expired) {
expiredKeys.add(key);
}
return expired;
});
if (expiredKeys.isEmpty) {
return;
}
_roomRocketLaunchCountdownKeysByRoom.removeWhere(
(_, key) => expiredKeys.contains(key),
);
_pendingRoomRocketCountdownLaunches.removeWhere(
(roomId, _) => !_roomRocketLaunchCountdownKeysByRoom.containsKey(roomId),
);
}
void _clearRoomRocketLaunchCountdownState() {
_roomRocketLaunchCountdownDueTimes.clear();
_roomRocketLaunchCountdownKeysByRoom.clear();
_pendingRoomRocketCountdownLaunches.clear();
for (final timer in _roomRocketLaunchEffectTimers.values) {
timer.cancel();
}
_roomRocketLaunchEffectTimers.clear();
}
void _clearRoomRocketLaunchCountdownForRoom(String roomId) {
final normalizedRoomId = roomId.trim();
final key = _roomRocketLaunchCountdownKeysByRoom.remove(normalizedRoomId);
if (key != null) {
_roomRocketLaunchCountdownDueTimes.remove(key);
_roomRocketLaunchEffectTimers.remove(key)?.cancel();
}
_pendingRoomRocketCountdownLaunches.remove(normalizedRoomId);
}
void _handleCurrentVisibleRoomRocketLaunch({
required RealTimeCommunicationManager rtcProvider,
required RoomRocketLaunchBroadcastMessage launch,
bool publishRegionBroadcast = false,
}) {
if (_addRoomRocketLaunchNoticeIfNeeded(
rtcProvider: rtcProvider,
launch: launch,
publishRegionBroadcast: publishRegionBroadcast,
)) {
_markRoomRocketRewardProbe(launch.roomId);
_scheduleRoomRocketLaunchEffectsAfterCountdown(launch);
}
}
bool _addRoomRocketLaunchNoticeIfNeeded({
required RealTimeCommunicationManager rtcProvider,
required RoomRocketLaunchBroadcastMessage launch,
bool publishRegionBroadcast = false,
int? secondsOverride,
}) {
if (!_isCurrentVisibleVoiceRoom(launch.roomId)) {
return;
return false;
}
final launchKey = _roomRocketLaunchNoticeKey(launch);
final looseLaunchKey = _roomRocketLaunchLooseKey(launch);
@ -2199,26 +2448,27 @@ class RealTimeMessagingManager extends ChangeNotifier {
_recentRoomRocketLaunchTimes.containsKey(launchKey)) ||
(looseLaunchKey.isNotEmpty &&
_recentRoomRocketLaunchLooseTimes.containsKey(looseLaunchKey));
if (!alreadyHandled && launchKey.isNotEmpty) {
_recentRoomRocketLaunchTimes[launchKey] = now;
if (looseLaunchKey.isNotEmpty) {
_recentRoomRocketLaunchLooseTimes[looseLaunchKey] = now;
}
addMsg(
_buildRoomRocketLaunchNoticeMsg(
_firstNonBlank([
rtcProvider.currenRoom?.roomProfile?.roomProfile?.roomAccount,
launch.roomAccount,
]),
launch,
),
);
if (publishRegionBroadcast) {
_publishRoomRocketRegionBroadcastIfNeeded(launch);
}
rtcProvider.handleRoomRocketLaunchBroadcast(launch);
if (alreadyHandled || launchKey.isEmpty) {
return false;
}
unawaited(_showRoomRocketRewardPopupDialog(launch.roomId));
_recentRoomRocketLaunchTimes[launchKey] = now;
if (looseLaunchKey.isNotEmpty) {
_recentRoomRocketLaunchLooseTimes[looseLaunchKey] = now;
}
addMsg(
_buildRoomRocketLaunchNoticeMsg(
_firstNonBlank([
rtcProvider.currenRoom?.roomProfile?.roomProfile?.roomAccount,
launch.roomAccount,
]),
launch,
secondsOverride: secondsOverride,
),
);
if (publishRegionBroadcast) {
_publishRoomRocketRegionBroadcastIfNeeded(launch);
}
return true;
}
void _publishRoomRocketRegionBroadcastIfNeeded(
@ -2294,7 +2544,9 @@ class RealTimeMessagingManager extends ChangeNotifier {
if (!_isCurrentVisibleVoiceRoom(roomId)) {
return;
}
if (res.records.isEmpty && initialRoomRecords.isEmpty) {
if (res.records.isEmpty &&
initialRoomRecords.isEmpty &&
attempt < _roomRocketRewardPopupRetryDelays.length) {
_scheduleRoomRocketRewardPopupRetry(
roomId,
attempt,
@ -2453,9 +2705,12 @@ class RealTimeMessagingManager extends ChangeNotifier {
Msg _buildRoomRocketLaunchNoticeMsg(
String groupId,
RoomRocketLaunchBroadcastMessage launch,
) {
final seconds = launch.durationSeconds <= 0 ? 10 : launch.durationSeconds;
RoomRocketLaunchBroadcastMessage launch, {
int? secondsOverride,
}) {
final seconds =
secondsOverride ??
(launch.durationSeconds <= 0 ? 10 : launch.durationSeconds);
return Msg(
groupId: groupId,
msg: seconds.toString(),

View File

@ -35,7 +35,7 @@ class RoomRocketRewardDialog extends StatelessWidget {
final emptyText = _translate(
localizations,
'roomRocketRewardEmptyText',
'No rewards earned. Better luck next time.',
'No reward',
);
final contentDirection = Directionality.of(context);
final resolvedRewards = _normalizeRewards(
@ -257,7 +257,7 @@ class _RewardDialogCanvas extends StatelessWidget {
if (isEmpty)
_buildEmptyState()
else ...[
_buildRewardGrid(),
rewards.isEmpty ? _buildRewardEmptyState() : _buildRewardGrid(),
_buildWinnerList(),
],
_buildLoadingText(),
@ -380,9 +380,6 @@ class _RewardDialogCanvas extends StatelessWidget {
}
Widget _buildRewardGrid() {
if (rewards.isEmpty) {
return const SizedBox.shrink();
}
final columns = math.max(3, (rewards.length / 2).ceil());
return Positioned(
left: s(28),
@ -425,6 +422,45 @@ class _RewardDialogCanvas extends StatelessWidget {
);
}
Widget _buildRewardEmptyState() {
return Positioned(
left: s(0),
top: s(268),
width: s(_designWidth),
height: s(178),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
_RewardDialogAssets.empty,
width: s(72),
height: s(72),
fit: BoxFit.contain,
),
SizedBox(height: s(10)),
SizedBox(
width: s(250),
child: Text(
emptyText,
textDirection: contentDirection,
textScaler: TextScaler.noScaling,
maxLines: 2,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white.withValues(alpha: 0.72),
fontSize: s(13),
height: 1.25,
fontWeight: FontWeight.w600,
decoration: TextDecoration.none,
),
),
),
],
),
);
}
Widget _buildWinnerList() {
return Positioned(
left: s(12),

View File

@ -1,5 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:yumi/shared/business_logic/models/res/sc_room_rocket_api_res.dart';
import 'package:yumi/ui_kit/widgets/room/rocket/room_rocket_dialog.dart';
import 'package:yumi/ui_kit/widgets/room/rocket/room_rocket_reward_dialog.dart';
import 'package:yumi/ui_kit/widgets/room/rocket/room_rocket_reward_dialog_loader.dart';
void main() {
@ -27,6 +30,30 @@ void main() {
expect(records.map((item) => item.rewardAmount), [5000, 5200]);
});
});
group('room rocket reward dialog', () {
testWidgets('shows reward empty state when room winners exist', (
tester,
) async {
await tester.pumpWidget(
const MaterialApp(
home: Scaffold(
body: RoomRocketRewardDialog(
rewards: <RoomRocketRewardItem>[],
winners: <RoomRocketRewardWinner>[
RoomRocketRewardWinner(nickname: 'test man'),
],
loadingText: '',
useMockFallback: false,
),
),
),
);
expect(find.text('No reward'), findsOneWidget);
expect(find.text('test man'), findsOneWidget);
});
});
}
SCRoomRocketRewardRecordRes _rewardRecord({