refactor: share the toolbar scrim and dedupe playback and download paths

Extracts the repeated toolbar fade into a single ToolbarScrim widget, folds
duplicated request/retry handling in the media server HTTP client, and
collapses the parallel playback-source, download-manager and live TV helper
paths into shared implementations.
This commit is contained in:
edde746
2026-07-26 06:09:49 +02:00
parent 83f4e2a263
commit c68ffe9ed0
23 changed files with 699 additions and 840 deletions
+9 -33
View File
@@ -1,11 +1,7 @@
import '../database/app_database.dart';
import '../media/ids.dart';
import '../media/media_backend.dart';
import '../media/media_item.dart';
import '../media/media_server_client.dart';
import '../models/audio_quality_preset.dart';
import '../models/transcode_quality_preset.dart';
import '../mpv/mpv.dart';
import 'multi_server_manager.dart';
import 'playback_context.dart';
import 'playback_initialization_service.dart';
@@ -17,40 +13,20 @@ class PlaybackSourceResolver {
const PlaybackSourceResolver({required this.serverManager, required this.database});
/// [preferOffline] overrides the default downloaded-copy preference
/// (`offlineLibraryMode || qualityPreset.isOriginal`). Pass false for
/// flows that must stay on the server stream, e.g. a transcode restart.
///
/// [audioQualityPreset] is the music transcode preset, consulted by the
/// backends only for [MediaKind.track] items ([qualityPreset] is
/// video-shaped and ignored for tracks).
Future<PlaybackContext> resolve({
required MediaItem metadata,
required int selectedMediaIndex,
String? selectedMediaSourceId,
String? preferredVersionSignature,
/// (`offlineLibraryMode || options.qualityPreset.isOriginal`, so an omitted
/// preset keeps it on). Pass false for flows that must stay on the server
/// stream, e.g. a transcode restart.
Future<PlaybackContext> resolve(
PlaybackInitializationOptions options, {
required bool offlineLibraryMode,
required TranscodeQualityPreset qualityPreset,
AudioQualityPreset? audioQualityPreset,
int? selectedAudioStreamId,
SubtitleTrack? preferredSubtitleTrack,
String? sessionIdentifier,
String? transcodeSessionId,
bool? preferOffline,
}) async {
final metadata = options.metadata;
final reportingClient = _playbackClient(serverIdOrNull(metadata.serverId), offlineLibraryMode: offlineLibraryMode);
final service = PlaybackInitializationService(client: reportingClient, database: database);
final result = await service.getPlaybackData(
metadata: metadata,
selectedMediaIndex: selectedMediaIndex,
selectedMediaSourceId: selectedMediaSourceId,
preferredVersionSignature: preferredVersionSignature,
preferOffline: preferOffline ?? (offlineLibraryMode || qualityPreset.isOriginal),
qualityPreset: qualityPreset,
audioQualityPreset: audioQualityPreset,
selectedAudioStreamId: selectedAudioStreamId,
preferredSubtitleTrack: preferredSubtitleTrack,
sessionIdentifier: sessionIdentifier,
transcodeSessionId: transcodeSessionId,
options,
preferOffline: preferOffline ?? (offlineLibraryMode || options.qualityPreset.isOriginal),
);
final sourceKind = result.usesLocalMedia
@@ -75,7 +51,7 @@ class PlaybackSourceResolver {
streamHeaders: _streamHeaders(
client: reportingClient,
sourceKind: sourceKind,
sessionIdentifier: sessionIdentifier,
sessionIdentifier: options.sessionIdentifier,
),
);
}