165 lines
4.3 KiB
Dart
165 lines
4.3 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:forui/forui.dart';
|
|
|
|
import '../../../core/contracts/library.dart';
|
|
import '../../../shared/utils/format_utils.dart';
|
|
import 'hero_action_buttons.dart';
|
|
|
|
|
|
List<FItem> buildSubtitleMenuButtons({
|
|
required List<EmbyRawMediaStream> subtitles,
|
|
required int? selectedSubtitleIdx,
|
|
required ValueChanged<int?> onSelectSubtitle,
|
|
}) {
|
|
return [
|
|
FItem(
|
|
prefix: selectedSubtitleIdx == null
|
|
? const Icon(Icons.check, size: 14)
|
|
: const SizedBox(width: 14),
|
|
title: const Text('关闭字幕'),
|
|
selected: selectedSubtitleIdx == null,
|
|
onPress: () => onSelectSubtitle(null),
|
|
),
|
|
...subtitles.asMap().entries.map(
|
|
(e) => FItem(
|
|
prefix: selectedSubtitleIdx == e.key
|
|
? const Icon(Icons.check, size: 14)
|
|
: const SizedBox(width: 14),
|
|
title: Text(
|
|
e.value.DisplayTitle ?? e.value.Language ?? '字幕 ${e.key + 1}',
|
|
),
|
|
selected: selectedSubtitleIdx == e.key,
|
|
onPress: () => onSelectSubtitle(e.key),
|
|
),
|
|
),
|
|
];
|
|
}
|
|
|
|
|
|
List<FItem> buildAudioMenuButtons({
|
|
required List<EmbyRawMediaStream> audios,
|
|
required int selectedAudioIdx,
|
|
required ValueChanged<int> onSelectAudio,
|
|
}) {
|
|
return audios
|
|
.asMap()
|
|
.entries
|
|
.map(
|
|
(e) => FItem(
|
|
prefix: selectedAudioIdx == e.key
|
|
? const Icon(Icons.check, size: 14)
|
|
: const SizedBox(width: 14),
|
|
title: Text(
|
|
e.value.DisplayTitle ?? e.value.Language ?? '音轨 ${e.key + 1}',
|
|
),
|
|
selected: selectedAudioIdx == e.key,
|
|
onPress: () => onSelectAudio(e.key),
|
|
),
|
|
)
|
|
.toList();
|
|
}
|
|
|
|
|
|
List<FItem> buildVersionMenuButtons({
|
|
required List<EmbyRawMediaSource> sources,
|
|
required int selectedSourceIdx,
|
|
required ValueChanged<int> onSelectSource,
|
|
}) {
|
|
return sources.asMap().entries.map((e) {
|
|
final src = e.value;
|
|
final name = src.Name ?? '版本 ${e.key + 1}';
|
|
final size = src.Size;
|
|
final sizeStr = size != null && size > 0 ? formatFileSize(size) : null;
|
|
return FItem(
|
|
prefix: selectedSourceIdx == e.key
|
|
? const Icon(Icons.check, size: 14)
|
|
: const SizedBox(width: 14),
|
|
title: Text(sizeStr != null ? '$name $sizeStr' : name),
|
|
selected: selectedSourceIdx == e.key,
|
|
onPress: () => onSelectSource(e.key),
|
|
);
|
|
}).toList();
|
|
}
|
|
|
|
|
|
String subtitleSummaryLabel(
|
|
List<EmbyRawMediaStream> subtitles,
|
|
int? selectedSubtitleIdx,
|
|
) => _streamSummaryLabel(
|
|
subtitles,
|
|
selectedSubtitleIdx,
|
|
empty: '关闭',
|
|
prefix: '字幕',
|
|
);
|
|
|
|
|
|
String audioSummaryLabel(
|
|
List<EmbyRawMediaStream> audios,
|
|
int selectedAudioIdx,
|
|
) => _streamSummaryLabel(audios, selectedAudioIdx, empty: '默认', prefix: '音轨');
|
|
|
|
String _streamSummaryLabel(
|
|
List<EmbyRawMediaStream> streams,
|
|
int? idx, {
|
|
required String empty,
|
|
required String prefix,
|
|
}) {
|
|
if (idx == null || idx < 0 || idx >= streams.length) return empty;
|
|
final s = streams[idx];
|
|
return s.Language ?? s.DisplayTitle ?? '$prefix ${idx + 1}';
|
|
}
|
|
|
|
|
|
String versionSummaryLabel(
|
|
List<EmbyRawMediaSource> sources,
|
|
int selectedSourceIdx,
|
|
) {
|
|
if (selectedSourceIdx < 0 || selectedSourceIdx >= sources.length) {
|
|
return '版本';
|
|
}
|
|
return sources[selectedSourceIdx].Name ?? '版本 ${selectedSourceIdx + 1}';
|
|
}
|
|
|
|
|
|
List<Widget> buildStreamSelectorPills({
|
|
required List<EmbyRawMediaStream> subtitles,
|
|
required List<EmbyRawMediaStream> audios,
|
|
required int? selectedSubtitleIdx,
|
|
required int selectedAudioIdx,
|
|
required ValueChanged<int?> onSelectSubtitle,
|
|
required ValueChanged<int> onSelectAudio,
|
|
required double height,
|
|
}) {
|
|
final actions = <Widget>[];
|
|
|
|
if (subtitles.length > 1) {
|
|
actions.add(
|
|
HeroPillDropdownButton(
|
|
height: height,
|
|
icon: Icons.subtitles_outlined,
|
|
menuChildren: buildSubtitleMenuButtons(
|
|
subtitles: subtitles,
|
|
selectedSubtitleIdx: selectedSubtitleIdx,
|
|
onSelectSubtitle: onSelectSubtitle,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
if (audios.length > 1) {
|
|
actions.add(
|
|
HeroPillDropdownButton(
|
|
height: height,
|
|
icon: Icons.audiotrack_outlined,
|
|
menuChildren: buildAudioMenuButtons(
|
|
audios: audios,
|
|
selectedAudioIdx: selectedAudioIdx,
|
|
onSelectAudio: onSelectAudio,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
return actions;
|
|
}
|