import 'package:flutter/cupertino.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:yumi/app/constants/sc_global_config.dart'; import 'package:yumi/main.dart'; import 'package:provider/provider.dart'; import 'package:yumi/shared/tools/sc_entrance_vap_svga_manager.dart'; import 'package:yumi/services/audio/rtc_manager.dart'; import 'package:yumi/ui_kit/widgets/room/floating/floating_game_screen_widget.dart'; import 'package:yumi/ui_kit/widgets/room/floating/floating_gift_screen_widget.dart'; import 'package:yumi/ui_kit/widgets/room/floating/floating_luck_gift_screen_widget.dart'; import 'package:yumi/ui_kit/widgets/room/floating/floating_room_redenvelope_screen_widget.dart'; import 'package:yumi/ui_kit/widgets/room/floating/floating_room_rocket_screen_widget.dart'; import 'package:yumi/shared/data_sources/models/message/sc_floating_message.dart'; typedef FloatingScreenManager = OverlayManager; class OverlayManager { final SCPriorityQueue _messageQueue = SCPriorityQueue( (a, b) => b.priority.compareTo(a.priority), ); bool _isPlaying = false; OverlayEntry? _currentOverlayEntry; bool _isProcessing = false; bool _isDisposed = false; static final OverlayManager _instance = OverlayManager._internal(); factory OverlayManager() => _instance; OverlayManager._internal(); void addMessage(SCFloatingMessage message) { if (_isDisposed) return; if (SCGlobalConfig.isFloatingAnimationInGlobal) { _messageQueue.add(message); _safeScheduleNext(); } else { _messageQueue.clear(); _isPlaying = false; _isProcessing = false; _isDisposed = false; } } void _safeScheduleNext() { if (_isProcessing || _isPlaying || _messageQueue.isEmpty) return; _isProcessing = true; try { _scheduleNext(); } finally { _isProcessing = false; } } void _scheduleNext() { if (_isPlaying || _messageQueue.isEmpty || _isDisposed) return; try { final context = navigatorKey.currentState?.context; if (context == null || !context.mounted) return; // 安全地获取第一个消息 if (_messageQueue.isEmpty) return; final messageToProcess = _messageQueue.first; if (messageToProcess?.type == 1) { final rtcProvider = Provider.of(context, listen: false); if (rtcProvider.currenRoom == null) { // 从队列中移除第一个元素 _messageQueue.removeFirst(); _safeScheduleNext(); return; } } // 安全地移除并播放消息 final messageToPlay = _messageQueue.removeFirst(); _playMessage(messageToPlay); } catch (e) { debugPrint('播放悬浮消息出错: $e'); _isPlaying = false; _safeScheduleNext(); } } void _playMessage(SCFloatingMessage message) { _isPlaying = true; final context = navigatorKey.currentState?.context; if (context == null || !context.mounted) { _isPlaying = false; _safeScheduleNext(); return; } _currentOverlayEntry = OverlayEntry( builder: (_) => Align( alignment: AlignmentDirectional.topStart, child: Transform.translate( offset: Offset(0, 70.w), child: _buildScreenWidget(message), ), ), ); Overlay.of(context)?.insert(_currentOverlayEntry!); } Widget _buildScreenWidget(SCFloatingMessage message) { bool completed = false; void onComplete() { if (completed) return; completed = true; try { _currentOverlayEntry?.remove(); _currentOverlayEntry = null; _isPlaying = false; _safeScheduleNext(); } catch (e) { debugPrint('清理悬浮消息出错: $e'); _isPlaying = false; _safeScheduleNext(); } } switch (message.type) { case 0: return FloatingLuckGiftScreenWidget( message: message, onAnimationCompleted: onComplete, ); case 1: //房间礼物 return FloatingGiftScreenWidget( message: message, onAnimationCompleted: onComplete, ); case 2: //游戏中奖 return FloatingGameScreenWidget( message: message, onAnimationCompleted: onComplete, ); case 3: //火箭 return FloatingRoomRocketScreenWidget( message: message, onAnimationCompleted: onComplete, ); case 4: //红包 return FloatingRoomRedenvelopeScreenWidget( message: message, onAnimationCompleted: onComplete, ); default: onComplete(); return Container(); } } void activate() { _isDisposed = false; } void dispose() { _isDisposed = true; _currentOverlayEntry?.remove(); _currentOverlayEntry = null; _messageQueue.clear(); _isPlaying = false; _isProcessing = false; } void removeRoom() { // 正确地从 PriorityQueue 中移除特定类型的消息 _removeMessagesByType(1); } // 辅助方法:移除特定类型的消息 void _removeMessagesByType(int type) { // 由于 PriorityQueue 没有直接的方法来移除特定元素, // 我们需要重建队列,排除指定类型的消息 final newQueue = SCPriorityQueue( (a, b) => b.priority.compareTo(a.priority), ); // 遍历原始队列,只添加非指定类型的消息 while (_messageQueue.isNotEmpty) { final message = _messageQueue.removeFirst(); if (message.type != type) { newQueue.add(message); } } // 将新队列赋值给原队列 while (newQueue.isNotEmpty) { _messageQueue.add(newQueue.removeFirst()); } } // 辅助方法:获取队列信息 int get queueLength => _messageQueue.length; bool get isPlaying => _isPlaying; }