From 967c25b11d8dc9c5ef9c8619ffc81adc3c598794 Mon Sep 17 00:00:00 2001 From: edde746 <86283021+edde746@users.noreply.github.com> Date: Sun, 12 Jul 2026 03:00:56 +0200 Subject: [PATCH] refactor(player): share queue item labels --- lib/media/media_item_labels.dart | 14 +++++++ .../video_controls/sheets/queue_sheet.dart | 17 +-------- .../video_controls/widgets/content_strip.dart | 15 +------- test/media/media_item_labels_test.dart | 37 +++++++++++++++++++ 4 files changed, 55 insertions(+), 28 deletions(-) create mode 100644 lib/media/media_item_labels.dart create mode 100644 test/media/media_item_labels_test.dart diff --git a/lib/media/media_item_labels.dart b/lib/media/media_item_labels.dart new file mode 100644 index 00000000..989d357a --- /dev/null +++ b/lib/media/media_item_labels.dart @@ -0,0 +1,14 @@ +import 'media_item.dart'; + +String formatQueueItemSubtitle(MediaItem item) { + final grandparentTitle = item.grandparentTitle; + if (grandparentTitle != null && item.parentIndex != null && item.index != null) { + return '$grandparentTitle \u00b7 S${item.parentIndex}E${item.index}'; + } + if (grandparentTitle != null) return grandparentTitle; + if (item.year != null) { + final edition = item.editionTitle; + return edition != null ? '${item.year} \u00b7 $edition' : '${item.year}'; + } + return item.kind.name; +} diff --git a/lib/widgets/video_controls/sheets/queue_sheet.dart b/lib/widgets/video_controls/sheets/queue_sheet.dart index d59ccabc..2b69f943 100644 --- a/lib/widgets/video_controls/sheets/queue_sheet.dart +++ b/lib/widgets/video_controls/sheets/queue_sheet.dart @@ -6,6 +6,7 @@ import 'package:provider/provider.dart'; import '../../../i18n/strings.g.dart'; import '../../../media/media_item.dart'; +import '../../../media/media_item_labels.dart'; import '../../../media/media_item_types.dart'; import '../../../providers/playback_state_provider.dart'; import '../../../services/settings_service.dart'; @@ -80,7 +81,7 @@ class _QueueSheetState extends State { overflow: .ellipsis, ), subtitle: Text( - _buildSubtitle(item), + formatQueueItemSubtitle(item), style: TextStyle( color: isCurrent ? primaryColor.withValues(alpha: 0.7) : tokens(context).textMuted, fontSize: 12, @@ -127,18 +128,4 @@ class _QueueSheetState extends State { blurThumbnail: hideSpoilers && item.shouldHideSpoiler, ); } - - String _buildSubtitle(MediaItem item) { - if (item.grandparentTitle != null && item.parentIndex != null && item.index != null) { - return '${item.grandparentTitle} \u00b7 S${item.parentIndex}E${item.index}'; - } - if (item.grandparentTitle != null) { - return item.grandparentTitle!; - } - if (item.year != null) { - final edition = item.editionTitle; - return edition != null ? '${item.year} · $edition' : '${item.year}'; - } - return item.kind.name; - } } diff --git a/lib/widgets/video_controls/widgets/content_strip.dart b/lib/widgets/video_controls/widgets/content_strip.dart index cb50ae5f..cecfbe2a 100644 --- a/lib/widgets/video_controls/widgets/content_strip.dart +++ b/lib/widgets/video_controls/widgets/content_strip.dart @@ -10,6 +10,7 @@ import '../../../focus/dpad_navigator.dart'; import '../../../focus/focusable_wrapper.dart'; import '../../../i18n/strings.g.dart'; import '../../../media/media_item.dart'; +import '../../../media/media_item_labels.dart'; import '../../../media/media_item_types.dart'; import '../../../media/media_server_client.dart'; import '../../../mpv/mpv.dart'; @@ -542,7 +543,7 @@ class ContentStripState extends State { : null, blurThumbnail: hideSpoilers && item.shouldHideSpoiler, title: item.title ?? '', - subtitle: _buildQueueSubtitle(item), + subtitle: formatQueueItemSubtitle(item), onTap: onTap, ); @@ -572,18 +573,6 @@ class ContentStripState extends State { ); } - String _buildQueueSubtitle(MediaItem item) { - if (item.grandparentTitle != null && item.parentIndex != null && item.index != null) { - return '${item.grandparentTitle} \u00b7 S${item.parentIndex}E${item.index}'; - } - if (item.grandparentTitle != null) return item.grandparentTitle!; - if (item.year != null) { - final edition = item.editionTitle; - return edition != null ? '${item.year} · $edition' : '${item.year}'; - } - return item.kind.name; - } - Widget _buildStripItem({ Key? key, required bool isCurrent, diff --git a/test/media/media_item_labels_test.dart b/test/media/media_item_labels_test.dart new file mode 100644 index 00000000..89990059 --- /dev/null +++ b/test/media/media_item_labels_test.dart @@ -0,0 +1,37 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:plezy/media/media_item.dart'; +import 'package:plezy/media/media_item_labels.dart'; +import 'package:plezy/media/media_kind.dart'; + +void main() { + MediaItem item({ + MediaKind kind = MediaKind.movie, + String? grandparentTitle, + int? parentIndex, + int? index, + int? year, + String? editionTitle, + }) => MediaItem.plex( + id: 'item', + kind: kind, + grandparentTitle: grandparentTitle, + parentIndex: parentIndex, + index: index, + year: year, + editionTitle: editionTitle, + ); + + test('formats episodes with show and season/episode numbers', () { + expect( + formatQueueItemSubtitle(item(kind: MediaKind.episode, grandparentTitle: 'Show', parentIndex: 2, index: 3)), + 'Show \u00b7 S2E3', + ); + }); + + test('falls back through show, year and edition, then media kind', () { + expect(formatQueueItemSubtitle(item(grandparentTitle: 'Show')), 'Show'); + expect(formatQueueItemSubtitle(item(year: 2026, editionTitle: 'Director Cut')), '2026 \u00b7 Director Cut'); + expect(formatQueueItemSubtitle(item(year: 2026)), '2026'); + expect(formatQueueItemSubtitle(item()), 'movie'); + }); +}