Files
sm-emby-share/lib/shared/widgets/version_grouping.dart
T

103 lines
3.0 KiB
Dart
Raw Normal View History

2026-07-14 11:11:36 +08:00
import 'version_source_card.dart';
class VersionSourceGroup {
final List<VersionSourceCardData> members;
VersionSourceGroup(List<VersionSourceCardData> members)
: assert(members.isNotEmpty),
members = List.unmodifiable(members);
VersionSourceCardData get representative => members.first;
VersionSourceCardData? get activeMember {
for (final member in members) {
if (member.isCurrent || member.selected) return member;
}
return null;
}
bool get hasActiveMember => activeMember != null;
bool get hasCurrentMember => members.any((member) => member.isCurrent);
List<String> get serverNames =>
List.unmodifiable([for (final member in members) member.serverName]);
VersionSourceCardData get displayData {
final visibleMember = activeMember ?? representative;
final names = serverNames;
final hasCurrent = hasCurrentMember;
final hasSelected = !hasCurrent && members.any((member) => member.selected);
final serverList = names.join('');
return VersionSourceCardData(
topLabel: visibleMember.topLabel,
sizeBytes: visibleMember.sizeBytes,
bitrate: visibleMember.bitrate,
serverName: visibleMember.serverName,
serverKey: visibleMember.serverKey,
isCurrent: hasCurrent,
selected: hasSelected,
onTap: visibleMember.onTap,
tooltip: names.length > 1 ? '可用服务器:$serverList' : visibleMember.tooltip,
resolutionLabel: visibleMember.resolutionLabel,
sourceKey: visibleMember.sourceKey,
mergedServerNames: names,
);
}
}
String? versionGroupKeyOf({
required int? sizeBytes,
required String resolutionLabel,
}) {
if (sizeBytes == null || sizeBytes <= 0) return null;
return '$sizeBytes|${resolutionLabel.trim().toUpperCase()}';
}
List<VersionSourceGroup> groupVersionEntries(
List<VersionSourceCardData> entries,
) {
final groupedMembers = <String, List<List<VersionSourceCardData>>>{};
final orderedMemberLists = <List<VersionSourceCardData>>[];
for (final entry in entries) {
final groupKey = versionGroupKeyOf(
sizeBytes: entry.sizeBytes,
resolutionLabel: entry.resolutionLabel,
);
if (groupKey == null) {
orderedMemberLists.add([entry]);
continue;
}
final candidateGroups = groupedMembers[groupKey] ?? const [];
List<VersionSourceCardData>? matchingGroup;
for (final candidateGroup in candidateGroups) {
final alreadyContainsServer = candidateGroup.any(
(member) => member.serverKey == entry.serverKey,
);
if (!alreadyContainsServer) {
matchingGroup = candidateGroup;
break;
}
}
if (matchingGroup != null && entry.serverKey.isNotEmpty) {
matchingGroup.add(entry);
continue;
}
final newMembers = <VersionSourceCardData>[entry];
groupedMembers.putIfAbsent(groupKey, () => []).add(newMembers);
orderedMemberLists.add(newMembers);
}
return [
for (final members in orderedMemberLists) VersionSourceGroup(members),
];
}