Files
sm-emby-share/lib/providers/version_priority_provider.dart
2026-07-14 11:11:36 +08:00

118 lines
3.3 KiB
Dart

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<VersionPriority> activePriorities;
const VersionPriorityState({this.activePriorities = const []});
}
class VersionPriorityNotifier extends AsyncNotifier<VersionPriorityState>
with SettingsPersistence {
static const _key = 'smplayer.version_priorities';
@override
Future<VersionPriorityState> 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<VersionPriority>()
.toList();
return VersionPriorityState(activePriorities: priorities);
}
Future<void> _save(List<VersionPriority> list) async {
state = AsyncValue.data(VersionPriorityState(activePriorities: list));
await persistField(_key, list.map((p) => p.name).toList());
}
Future<void> toggle(VersionPriority p) async {
final current = List<VersionPriority>.from(
state.value?.activePriorities ?? [],
);
current.contains(p) ? current.remove(p) : current.add(p);
await _save(current);
}
Future<void> setPriorities(List<VersionPriority> list) => _save(list);
}
final versionPriorityProvider =
AsyncNotifierProvider<VersionPriorityNotifier, VersionPriorityState>(
VersionPriorityNotifier.new,
);
List<EmbyRawMediaSource> sortMediaSources(
List<EmbyRawMediaSource> sources,
List<VersionPriority> priorities,
) {
if (priorities.isEmpty || sources.length <= 1) return sources;
final sorted = List<EmbyRawMediaSource>.from(sources);
sorted.sort((a, b) => compareMediaSourcesByPriority(a, b, priorities));
return sorted;
}
int compareMediaSourcesByPriority(
EmbyRawMediaSource a,
EmbyRawMediaSource b,
List<VersionPriority> 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;
}