import 'package:flutter/animation.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter_svga/flutter_svga.dart'; import 'package:yumi/app/constants/sc_global_config.dart'; import 'package:yumi/shared/tools/sc_path_utils.dart'; import 'package:yumi/shared/data_sources/sources/local/file_cache_manager.dart'; import 'package:tancent_vap/utils/constant.dart'; import 'package:tancent_vap/widgets/vap_view.dart'; import 'package:yumi/shared/data_sources/sources/local/data_persistence.dart'; class SCGiftVapSvgaManager { Map videoItemCache = {}; static SCGiftVapSvgaManager? _inst; SCGiftVapSvgaManager._internal(); factory SCGiftVapSvgaManager() => _inst ??= SCGiftVapSvgaManager._internal(); final SCPriorityQueue _tq = SCPriorityQueue( (a, b) => a.compareTo(b), // 调用 SCVapTask 的 compareTo 方法 ); VapController? _rgc; SVGAAnimationController? _rsc; bool _play = false; bool _dis = false; bool _pause = false; //是否关闭礼物特效声音 bool _mute = false; void setMute(bool muteMusic) { _mute = muteMusic; DataPersistence.setPlayGiftMusic(_mute); } bool getMute() { return _mute; } // 绑定控制器 void bindVapCtrl(VapController vapController) { _mute = DataPersistence.getPlayGiftMusic(); _dis = false; _rgc = vapController; _rgc?.setAnimListener( onVideoStart: () { }, onVideoComplete: () { _hcs(); }, onFailed: (code, type, msg) { _hcs(); }, ); } void bindSvgaCtrl(SVGAAnimationController svgaController) { _dis = false; _rsc = svgaController; _rsc?.addStatusListener((AnimationStatus status) { if (status.isCompleted) { _rsc?.reset(); _play = false; _pn(); } }); } // 播放任务 void play( String path, { int priority = 0, Map? customResources, int type = 0, }) { if (path.isEmpty) { return; } if (SCGlobalConfig.sdkInt > SCGlobalConfig.maxSdkNoAnim) { if (_dis) return; final task = SCVapTask( path: path, priority: priority, customResources: customResources, ); _tq.add(task); if (!_play) { _pn(); } } } // 播放下一个任务 Future _pn() async { if (_pause) { return; } if (_dis || _tq.isEmpty || _play) return; final task = _tq.removeFirst(); _play = true; try { final pathType = SCPathUtils.getPathType(task.path); if (pathType == PathType.asset) { await _pa(task); } else if (pathType == PathType.file) { await _pf(task); } else if (pathType == PathType.network) { await _pnw(task); } } catch (e, s) { print('VAP_SVGA播放失败: $e\n$s'); } finally { // 确保状态正确重置 // if (!_dis) { // _pn(); // } } } // 播放资源文件 Future _pa(SCVapTask task) async { if (_dis) return; if (SCPathUtils.getFileExtension(task.path).toLowerCase() == ".svga") { MovieEntity entity; if (videoItemCache.containsKey(task.path)) { entity = videoItemCache[task.path]!; } else { entity = await SVGAParser.shared.decodeFromAssets(task.path); videoItemCache[task.path] = entity; } _rsc?.videoItem = entity; _rsc?.reset(); _rsc?.forward(); } else { if (task.customResources != null) { task.customResources?.forEach((k, v) async { await _rgc?.setVapTagContent(k, v); }); } await _rgc?.playAsset(task.path); } } // 播放本地文件 Future _pf(SCVapTask task) async { if (_dis || _rgc == null) return; await _rgc?.setMute(_mute); if (task.customResources != null) { task.customResources?.forEach((k, v) async { await _rgc?.setVapTagContent(k, v); }); } await _rgc!.playFile(task.path); } // 播放网络资源 Future _pnw(SCVapTask task) async { if (_dis) return; if (SCPathUtils.getFileExtension(task.path).toLowerCase() == ".svga") { MovieEntity? entity; if (videoItemCache.containsKey(task.path)) { entity = videoItemCache[task.path]!; entity.autorelease = false; } else { try { entity = await SVGAParser.shared.decodeFromURL(task.path); entity.autorelease = false; videoItemCache[task.path] = entity; } catch (e) { _play = false; print('svga解析出错:$e'); } } if (entity != null) { _rsc?.videoItem = entity; _rsc?.reset(); _rsc?.forward(); } } else { final file = await FileCacheManager.getInstance().getFile(url: task.path); if (file != null && !_dis) { await _pf( SCVapTask( path: file.path, priority: task.priority, customResources: task.customResources, ), ); } } } // 处理控制器状态变化 void _hcs() { if (_rgc != null && !_dis) { _play = false; // 延迟一小段时间后播放下一个,避免状态冲突 Future.delayed(const Duration(milliseconds: 50), _pn); } } //暂停动画播放 void pauseAnim() { _pause = true; } //恢复动画播放 void resumeAnim() { _pause = false; _pn(); } // 释放资源 void dispose() { _dis = true; _play = false; _tq.clear(); _rgc?.stop(); _rgc?.dispose(); _rgc = null; _rsc?.stop(); _rsc?.dispose(); _rsc = null; } // 清除所有任务 void clearTasks() { _play = false; _tq.clear(); _pause = false; } } // 任务模型 // 1. 修改 SCVapTask 类,实现 Comparable class SCVapTask implements Comparable { final String path; final int type; final int priority; final Map? customResources; final int _seq; static int _nextSeq = 0; SCVapTask({ required this.path, this.priority = 0, this.customResources, this.type = 0, }) : _seq = _nextSeq++; @override int compareTo(SCVapTask other) { // 先按优先级降序排列 int priorityComparison = other.priority.compareTo(priority); if (priorityComparison != 0) { return priorityComparison; } // 相同优先级时,按序列号升序排列(先添加的先执行) return _seq.compareTo(other._seq); } @override String toString() { return 'SCVapTask{path: $path, priority: $priority, seq: $_seq}'; } } // 优先队列实现 class SCPriorityQueue { final List _els = []; final Comparator _cmp; SCPriorityQueue(this._cmp); void add(E element) { _els.add(element); _els.sort(_cmp); } E removeFirst() { if (isEmpty) throw StateError("No elements"); return _els.removeAt(0); } E? get first => isEmpty ? null : _els.first; bool get isEmpty => _els.isEmpty; bool get isNotEmpty => _els.isNotEmpty; int get length => _els.length; void clear() => _els.clear(); List get unorderedElements => List.from(_els); // 实现 Iterable 接口 Iterator get iterator => _els.iterator; }