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
@@ -65,13 +65,15 @@ void main() {
await PlexApiCache.instance.put(ServerId('srv-1'), '/library/metadata/movie-1', _plexMetadataEnvelope());
final result = await PlaybackInitializationService(database: db).getPlaybackData(
metadata: testMediaItem(
id: 'movie-1',
backend: MediaBackend.plex,
kind: MediaKind.movie,
serverId: ServerId('srv-1'),
PlaybackInitializationOptions(
metadata: testMediaItem(
id: 'movie-1',
backend: MediaBackend.plex,
kind: MediaKind.movie,
serverId: ServerId('srv-1'),
),
selectedMediaIndex: 0,
),
selectedMediaIndex: 0,
preferOffline: true,
);
@@ -94,13 +96,15 @@ void main() {
final client = _FailingPlaybackClient(serverId: ServerId('srv-1'));
final result = await PlaybackInitializationService(client: client, database: db).getPlaybackData(
metadata: testMediaItem(
id: 'track-1',
backend: MediaBackend.plex,
kind: MediaKind.track,
serverId: ServerId('srv-1'),
PlaybackInitializationOptions(
metadata: testMediaItem(
id: 'track-1',
backend: MediaBackend.plex,
kind: MediaKind.track,
serverId: ServerId('srv-1'),
),
selectedMediaIndex: 0,
),
selectedMediaIndex: 0,
preferOffline: true,
);
@@ -121,13 +125,15 @@ void main() {
final client = _FailingPlaybackClient(serverId: ServerId('srv-1'));
final result = await PlaybackInitializationService(client: client, database: db).getPlaybackData(
metadata: testMediaItem(
id: 'movie-1',
backend: MediaBackend.plex,
kind: MediaKind.movie,
serverId: ServerId('srv-1'),
PlaybackInitializationOptions(
metadata: testMediaItem(
id: 'movie-1',
backend: MediaBackend.plex,
kind: MediaKind.movie,
serverId: ServerId('srv-1'),
),
selectedMediaIndex: 0,
),
selectedMediaIndex: 0,
preferOffline: true,
);
@@ -153,13 +159,15 @@ void main() {
);
final result = await PlaybackInitializationService(database: db).getPlaybackData(
metadata: testMediaItem(
id: 'movie-1',
backend: MediaBackend.plex,
kind: MediaKind.movie,
serverId: ServerId('srv-1'),
PlaybackInitializationOptions(
metadata: testMediaItem(
id: 'movie-1',
backend: MediaBackend.plex,
kind: MediaKind.movie,
serverId: ServerId('srv-1'),
),
selectedMediaIndex: 1,
),
selectedMediaIndex: 1,
preferOffline: true,
);
@@ -186,13 +194,15 @@ void main() {
);
final result = await PlaybackInitializationService(database: db).getPlaybackData(
metadata: testMediaItem(
id: 'movie-1',
backend: MediaBackend.plex,
kind: MediaKind.movie,
serverId: ServerId('srv-1'),
PlaybackInitializationOptions(
metadata: testMediaItem(
id: 'movie-1',
backend: MediaBackend.plex,
kind: MediaKind.movie,
serverId: ServerId('srv-1'),
),
selectedMediaIndex: 0,
),
selectedMediaIndex: 0,
);
expect(result.isOffline, isTrue);
@@ -213,14 +223,16 @@ void main() {
);
final result = await PlaybackInitializationService(database: db).getPlaybackData(
metadata: testMediaItem(
id: 'movie-1',
backend: MediaBackend.plex,
kind: MediaKind.movie,
serverId: ServerId('srv-1'),
PlaybackInitializationOptions(
metadata: testMediaItem(
id: 'movie-1',
backend: MediaBackend.plex,
kind: MediaKind.movie,
serverId: ServerId('srv-1'),
),
selectedMediaIndex: 0,
selectedMediaSourceId: 'source-a',
),
selectedMediaIndex: 0,
selectedMediaSourceId: 'source-a',
);
expect(result.isOffline, isTrue);
@@ -243,14 +255,16 @@ void main() {
final client = _StreamingPlaybackClient(serverId: ServerId('srv-1'));
final result = await PlaybackInitializationService(client: client, database: db).getPlaybackData(
metadata: testMediaItem(
id: 'movie-1',
backend: MediaBackend.plex,
kind: MediaKind.movie,
serverId: ServerId('srv-1'),
PlaybackInitializationOptions(
metadata: testMediaItem(
id: 'movie-1',
backend: MediaBackend.plex,
kind: MediaKind.movie,
serverId: ServerId('srv-1'),
),
selectedMediaIndex: 0,
selectedMediaSourceId: 'source-a',
),
selectedMediaIndex: 0,
selectedMediaSourceId: 'source-a',
preferOffline: true,
);
@@ -297,13 +311,15 @@ void main() {
);
final result = await PlaybackInitializationService(database: db).getPlaybackData(
metadata: testMediaItem(
id: 'item-1',
backend: MediaBackend.jellyfin,
kind: MediaKind.movie,
serverId: ServerId('jf-machine'),
PlaybackInitializationOptions(
metadata: testMediaItem(
id: 'item-1',
backend: MediaBackend.jellyfin,
kind: MediaKind.movie,
serverId: ServerId('jf-machine'),
),
selectedMediaIndex: 0,
),
selectedMediaIndex: 0,
preferOffline: true,
);
@@ -325,13 +341,15 @@ void main() {
await subtitleFile.writeAsString('1\n00:00:00,000 --> 00:00:01,000\nHello');
final result = await PlaybackInitializationService(database: db).getPlaybackData(
metadata: testMediaItem(
id: 'movie-1',
backend: MediaBackend.plex,
kind: MediaKind.movie,
serverId: ServerId('srv-1'),
PlaybackInitializationOptions(
metadata: testMediaItem(
id: 'movie-1',
backend: MediaBackend.plex,
kind: MediaKind.movie,
serverId: ServerId('srv-1'),
),
selectedMediaIndex: 0,
),
selectedMediaIndex: 0,
preferOffline: true,
);
@@ -57,10 +57,12 @@ void main() {
manager.debugRegisterClientForTesting(client, online: false);
final context = await PlaybackSourceResolver(serverManager: manager, database: db).resolve(
metadata: testMediaItem(id: 'item-1', backend: MediaBackend.plex, kind: MediaKind.movie, serverId: 'srv'),
selectedMediaIndex: 0,
PlaybackInitializationOptions(
metadata: testMediaItem(id: 'item-1', backend: MediaBackend.plex, kind: MediaKind.movie, serverId: 'srv'),
selectedMediaIndex: 0,
qualityPreset: TranscodeQualityPreset.original,
),
offlineLibraryMode: false,
qualityPreset: TranscodeQualityPreset.original,
);
expect(context.result.videoUrl, 'https://example.com/video.mp4');
@@ -80,11 +82,13 @@ void main() {
manager.debugRegisterClientForTesting(client, online: true);
final context = await PlaybackSourceResolver(serverManager: manager, database: db).resolve(
metadata: testMediaItem(id: 'item-1', backend: MediaBackend.plex, kind: MediaKind.movie, serverId: 'srv'),
selectedMediaIndex: 0,
PlaybackInitializationOptions(
metadata: testMediaItem(id: 'item-1', backend: MediaBackend.plex, kind: MediaKind.movie, serverId: 'srv'),
selectedMediaIndex: 0,
qualityPreset: TranscodeQualityPreset.original,
sessionIdentifier: 'playback-session-id',
),
offlineLibraryMode: false,
qualityPreset: TranscodeQualityPreset.original,
sessionIdentifier: 'playback-session-id',
);
expect(context.sourceKind, PlaybackSourceKind.remoteDirect);
@@ -104,11 +108,13 @@ void main() {
manager.debugRegisterClientForTesting(client, online: true);
final context = await PlaybackSourceResolver(serverManager: manager, database: db).resolve(
metadata: testMediaItem(id: 'item-1', backend: MediaBackend.jellyfin, kind: MediaKind.movie, serverId: 'srv'),
selectedMediaIndex: 0,
PlaybackInitializationOptions(
metadata: testMediaItem(id: 'item-1', backend: MediaBackend.jellyfin, kind: MediaKind.movie, serverId: 'srv'),
selectedMediaIndex: 0,
qualityPreset: TranscodeQualityPreset.original,
sessionIdentifier: 'playback-session-id',
),
offlineLibraryMode: false,
qualityPreset: TranscodeQualityPreset.original,
sessionIdentifier: 'playback-session-id',
);
expect(context.sourceKind, PlaybackSourceKind.remoteDirect);