上下麦UI无法更新修复

This commit is contained in:
roxy 2026-06-03 18:10:10 +08:00
parent c190d95ec1
commit ef11d0f01b
4 changed files with 70 additions and 26 deletions

View File

@ -481,6 +481,24 @@ class RealTimeCommunicationManager extends ChangeNotifier {
/// ///
bool isMic = true; bool isMic = true;
bool _setSelfMicMuted(bool value) {
if (isMic == value) {
return false;
}
isMic = value;
return true;
}
void _notifySelfMicUiState({bool? muted, bool notifyIfUnchanged = false}) {
var changed = false;
if (muted != null) {
changed = _setSelfMicMuted(muted) || changed;
}
if (changed || notifyIfUnchanged) {
notifyListeners();
}
}
bool shouldShowSeatSoundWave(num index) { bool shouldShowSeatSoundWave(num index) {
final seat = roomWheatMap[index]; final seat = roomWheatMap[index];
final userId = (seat?.user?.id ?? "").trim(); final userId = (seat?.user?.id ?? "").trim();
@ -2530,8 +2548,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
} }
Future<void> setSelfMicMutedFromBottom(bool muted) async { Future<void> setSelfMicMutedFromBottom(bool muted) async {
isMic = muted; _notifySelfMicUiState(muted: muted);
notifyListeners();
final currentUserId = final currentUserId =
(AccountStorage().getCurrentUser()?.userProfile?.id ?? "").trim(); (AccountStorage().getCurrentUser()?.userProfile?.id ?? "").trim();
final seatIndex = final seatIndex =
@ -2539,7 +2556,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
? userOnMaiInIndex(currentUserId) ? userOnMaiInIndex(currentUserId)
: (_currentUserMicSeat()?.micIndex ?? -1); : (_currentUserMicSeat()?.micIndex ?? -1);
if (seatIndex < 0) { if (seatIndex < 0) {
notifyListeners();
return; return;
} }
final seat = roomWheatMap[seatIndex]; final seat = roomWheatMap[seatIndex];
@ -2557,6 +2573,10 @@ class RealTimeCommunicationManager extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
Future<void> toggleSelfMicMutedFromBottom() {
return setSelfMicMutedFromBottom(!isMic);
}
Future<void> handleSelfMicRemovedByRemote({ Future<void> handleSelfMicRemovedByRemote({
bool refreshMicList = true, bool refreshMicList = true,
}) async { }) async {
@ -2564,6 +2584,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
final currentUserId = final currentUserId =
(AccountStorage().getCurrentUser()?.userProfile?.id ?? "").trim(); (AccountStorage().getCurrentUser()?.userProfile?.id ?? "").trim();
if (currentUserKeys.isEmpty) { if (currentUserKeys.isEmpty) {
_notifySelfMicUiState(muted: true, notifyIfUnchanged: true);
await _switchRoomRtcToAudience(); await _switchRoomRtcToAudience();
return; return;
} }
@ -2572,7 +2593,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
currentUserId.isNotEmpty currentUserId.isNotEmpty
? userOnMaiInIndex(currentUserId) ? userOnMaiInIndex(currentUserId)
: (_currentUserMicSeat()?.micIndex ?? -1); : (_currentUserMicSeat()?.micIndex ?? -1);
isMic = true; _setSelfMicMuted(true);
_clearSelfMicSwitchGuard(clearPreferredIndex: true); _clearSelfMicSwitchGuard(clearPreferredIndex: true);
_clearSelfMicGoUpGuard(clearPreferredIndex: true); _clearSelfMicGoUpGuard(clearPreferredIndex: true);
if (currentSeatIndex > -1) { if (currentSeatIndex > -1) {
@ -2584,7 +2605,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
_roomRtcRoleIsBroadcaster = false; _roomRtcRoleIsBroadcaster = false;
_syncSelfMicRuntimeState(); _syncSelfMicRuntimeState();
_clearConfirmedSelfMicIdentity(); _clearConfirmedSelfMicIdentity();
notifyListeners(); _notifySelfMicUiState(notifyIfUnchanged: true);
await _switchRoomRtcToAudience(); await _switchRoomRtcToAudience();
if (refreshMicList) { if (refreshMicList) {
@ -5079,7 +5100,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
_roomVisualEffectsEnabled = false; _roomVisualEffectsEnabled = false;
_voiceRoomRouteVisible = false; _voiceRoomRouteVisible = false;
_isExitingCurrentVoiceRoomSession = false; _isExitingCurrentVoiceRoomSession = false;
isMic = true; _setSelfMicMuted(true);
isMusicPlaying = false; isMusicPlaying = false;
if (clearPersistedRoomMarker) { if (clearPersistedRoomMarker) {
DataPersistence.setLastTimeRoomId(""); DataPersistence.setLastTimeRoomId("");
@ -5292,7 +5313,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
user: currentUser, user: currentUser,
roomToken: micGoUpRes.roomToken, roomToken: micGoUpRes.roomToken,
); );
isMic = selfMicMuted; _setSelfMicMuted(selfMicMuted);
_syncSelfMicRuntimeState(); _syncSelfMicRuntimeState();
} }
@ -5447,6 +5468,8 @@ class RealTimeCommunicationManager extends ChangeNotifier {
selfMicMuted: selfMicMuted, selfMicMuted: selfMicMuted,
); );
notifyListeners(); notifyListeners();
} else {
_refreshMicListSilently(notifyIfUnchanged: true);
} }
final switched = await _switchRoomRtcToBroadcaster( final switched = await _switchRoomRtcToBroadcaster(
@ -5508,7 +5531,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
roomWheatMap[index]?.user, roomWheatMap[index]?.user,
currentUserKeys, currentUserKeys,
)) { )) {
isMic = true; _setSelfMicMuted(true);
} }
_clearSelfMicSwitchGuard(clearPreferredIndex: true); _clearSelfMicSwitchGuard(clearPreferredIndex: true);
_clearSelfMicGoUpGuard(clearPreferredIndex: true); _clearSelfMicGoUpGuard(clearPreferredIndex: true);
@ -5519,11 +5542,10 @@ class RealTimeCommunicationManager extends ChangeNotifier {
} }
SCHeartbeatUtils.cancelAnchorTimer(); SCHeartbeatUtils.cancelAnchorTimer();
await _switchRoomRtcToAudience();
_clearCurrentUserFromSeats(); _clearCurrentUserFromSeats();
_syncSelfMicRuntimeState(); _syncSelfMicRuntimeState();
_clearConfirmedSelfMicIdentity(); _clearConfirmedSelfMicIdentity();
notifyListeners(); _notifySelfMicUiState(notifyIfUnchanged: true);
requestMicrophoneListRefresh( requestMicrophoneListRefresh(
notifyIfUnchanged: false, notifyIfUnchanged: false,
minInterval: const Duration(milliseconds: 350), minInterval: const Duration(milliseconds: 350),

View File

@ -122,7 +122,7 @@ class _FloatingLuckyGiftGlobalScreenWidgetState
resource: FloatingLuckyGiftGlobalScreenWidget.backgroundPagAssetPath, resource: FloatingLuckyGiftGlobalScreenWidget.backgroundPagAssetPath,
width: FloatingLuckyGiftGlobalScreenWidget.bannerWidth.w, width: FloatingLuckyGiftGlobalScreenWidget.bannerWidth.w,
height: FloatingLuckyGiftGlobalScreenWidget.bannerHeight.w, height: FloatingLuckyGiftGlobalScreenWidget.bannerHeight.w,
fit: BoxFit.fill, fit: BoxFit.contain,
clipBehavior: Clip.none, clipBehavior: Clip.none,
defaultBuilder: (_) => _buildFallbackBackground(), defaultBuilder: (_) => _buildFallbackBackground(),
); );

View File

@ -38,9 +38,11 @@ class RoomGiftComboFloatingLayer extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Selector<RtcProvider, bool>( final provider = context.read<RtcProvider>();
selector: (context, provider) => _shouldShowRoomBottomMic(provider), return AnimatedBuilder(
builder: (context, showMic, child) { animation: provider,
builder: (context, child) {
final showMic = _shouldShowRoomBottomMic(provider);
return LayoutBuilder( return LayoutBuilder(
builder: (context, constraints) { builder: (context, constraints) {
final inputWidth = _resolveRoomBottomInputWidth( final inputWidth = _resolveRoomBottomInputWidth(
@ -81,15 +83,16 @@ class _RoomBottomWidgetState extends State<RoomBottomWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final provider = context.read<RtcProvider>();
return SizedBox( return SizedBox(
height: _floatingButtonHostHeight.w, height: _floatingButtonHostHeight.w,
child: Selector<RtcProvider, _RoomBottomSnapshot>( child: AnimatedBuilder(
selector: animation: provider,
(context, provider) => _RoomBottomSnapshot( builder: (context, child) {
showMic: _shouldShowRoomBottomMic(provider), final bottomSnapshot = _RoomBottomSnapshot(
isMic: provider.isMic, showMic: _shouldShowRoomBottomMic(provider),
), isMic: provider.isMic,
builder: (context, bottomSnapshot, child) { );
return LayoutBuilder( return LayoutBuilder(
builder: (context, constraints) { builder: (context, constraints) {
final inputWidth = _resolveRoomBottomInputWidth( final inputWidth = _resolveRoomBottomInputWidth(
@ -323,11 +326,7 @@ class _RoomBottomWidgetState extends State<RoomBottomWidget> {
return GestureDetector( return GestureDetector(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap: () { onTap: () {
final provider = context.read<RtcProvider>(); unawaited(context.read<RtcProvider>().toggleSelfMicMutedFromBottom());
setState(() {
provider.isMic = !provider.isMic;
});
unawaited(provider.setSelfMicMutedFromBottom(provider.isMic));
}, },
child: RoomBottomCircleAction( child: RoomBottomCircleAction(
child: Image.asset( child: Image.asset(

View File

@ -117,4 +117,27 @@ void main() {
expect(rtcProvider.roomWheatMap[5]?.user?.id, 'server-seat-id'); expect(rtcProvider.roomWheatMap[5]?.user?.id, 'server-seat-id');
expect(rtcProvider.roomWheatMap[5]?.user?.account, 'server-seat-account'); expect(rtcProvider.roomWheatMap[5]?.user?.account, 'server-seat-account');
}); });
test('self mic state follows microphone list snapshots', () {
SharedPreferences.setMockInitialValues({});
AccountStorage().setCurrentUser(
SocialChatLoginRes(
userProfile: SocialChatUserProfile(id: 'user-1', userNickname: 'Me'),
),
);
final rtcProvider = RealTimeCommunicationManager();
rtcProvider.debugApplyMicListSnapshot([
MicRes(
micIndex: 2,
user: SocialChatUserProfile(id: 'user-1', userNickname: 'Me'),
),
], notifyIfUnchanged: false);
expect(rtcProvider.isOnMai(), isTrue);
rtcProvider.debugApplyMicListSnapshot([
MicRes(micIndex: 2),
], notifyIfUnchanged: false);
expect(rtcProvider.isOnMai(), isFalse);
});
} }