103 lines
3.0 KiB
Dart
103 lines
3.0 KiB
Dart
|
|
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),
|
||
|
|
];
|
||
|
|
}
|