import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../core/contracts/library.dart'; import '../core/media/media_range_detector.dart'; import 'shared/settings_persistence.dart'; enum VersionPriority { dolbyVision('杜比视界优先'), hdr('HDR 优先'), sdr('SDR 优先'), highBitrate('高码率优先'), lowBitrate('低码率优先'), highFramerate('高帧率优先'), largeFile('大文件优先'); final String label; const VersionPriority(this.label); } class VersionPriorityState { final List activePriorities; const VersionPriorityState({this.activePriorities = const []}); } class VersionPriorityNotifier extends AsyncNotifier with SettingsPersistence { static const _key = 'smplayer.version_priorities'; @override Future build() async { final prefs = await getPrefs(); final raw = prefs.getStringList(_key); if (raw == null) return const VersionPriorityState(); final priorities = raw .map((name) { try { return VersionPriority.values.byName(name); } catch (_) { return null; } }) .whereType() .toList(); return VersionPriorityState(activePriorities: priorities); } Future _save(List list) async { state = AsyncValue.data(VersionPriorityState(activePriorities: list)); await persistField(_key, list.map((p) => p.name).toList()); } Future toggle(VersionPriority p) async { final current = List.from( state.value?.activePriorities ?? [], ); current.contains(p) ? current.remove(p) : current.add(p); await _save(current); } Future setPriorities(List list) => _save(list); } final versionPriorityProvider = AsyncNotifierProvider( VersionPriorityNotifier.new, ); List sortMediaSources( List sources, List priorities, ) { if (priorities.isEmpty || sources.length <= 1) return sources; final sorted = List.from(sources); sorted.sort((a, b) => compareMediaSourcesByPriority(a, b, priorities)); return sorted; } int compareMediaSourcesByPriority( EmbyRawMediaSource a, EmbyRawMediaSource b, List priorities, ) { for (final p in priorities) { final cmp = _compareByRule(a, b, p); if (cmp != 0) return cmp; } return 0; } int _compareByRule( EmbyRawMediaSource a, EmbyRawMediaSource b, VersionPriority rule, ) { switch (rule) { case VersionPriority.dolbyVision: return _boolDesc(isDolbyVision(a), isDolbyVision(b)); case VersionPriority.hdr: return _boolDesc(isHdr(a), isHdr(b)); case VersionPriority.sdr: return _boolDesc(!isHdr(a), !isHdr(b)); case VersionPriority.highBitrate: return (b.Bitrate ?? 0).compareTo(a.Bitrate ?? 0); case VersionPriority.lowBitrate: return (a.Bitrate ?? 0).compareTo(b.Bitrate ?? 0); case VersionPriority.highFramerate: return getFrameRate(b).compareTo(getFrameRate(a)); case VersionPriority.largeFile: return (b.Size ?? 0).compareTo(a.Size ?? 0); } } int _boolDesc(bool a, bool b) { if (a == b) return 0; return a ? -1 : 1; }