From 9501831691ee334704a275331a994a3af3f4dedd Mon Sep 17 00:00:00 2001 From: edde746 <86283021+edde746@users.noreply.github.com> Date: Sun, 16 Nov 2025 23:57:32 +0100 Subject: [PATCH] refactor: format --- lib/services/storage_service.dart | 8 +- .../collection_playlist_play_helper.dart | 19 +- lib/utils/error_message_utils.dart | 5 +- lib/utils/grid_size_calculator.dart | 3 +- lib/utils/library_refresh_notifier.dart | 3 +- lib/widgets/content_state_builder.dart | 10 +- lib/widgets/empty_state_widget.dart | 7 +- lib/widgets/error_state_widget.dart | 10 +- lib/widgets/folder_tree_item.dart | 4 +- lib/widgets/folder_tree_view.dart | 29 +- lib/widgets/hub_section.dart | 19 +- lib/widgets/media_context_menu.dart | 302 ++++++++++-------- lib/widgets/sort_bottom_sheet.dart | 5 +- .../sheets/audio_sync_sheet.dart | 14 +- .../video_controls/sheets/chapter_sheet.dart | 30 +- .../sheets/playback_speed_sheet.dart | 5 +- .../sheets/subtitle_track_sheet.dart | 18 +- .../video_controls/sheets/version_sheet.dart | 4 +- .../sheets/video_settings_sheet.dart | 30 +- .../video_controls/video_controls.dart | 1 - 20 files changed, 244 insertions(+), 282 deletions(-) diff --git a/lib/services/storage_service.dart b/lib/services/storage_service.dart index d967425e..f17ced12 100644 --- a/lib/services/storage_service.dart +++ b/lib/services/storage_service.dart @@ -180,11 +180,13 @@ class StorageService { } Map getLibraryFilters({String? sectionId}) { - final scopedKey = - sectionId != null ? 'library_filters_$sectionId' : _keyLibraryFilters; + final scopedKey = sectionId != null + ? 'library_filters_$sectionId' + : _keyLibraryFilters; // Prefer per-library filters when available - final jsonString = _prefs.getString(scopedKey) ?? + final jsonString = + _prefs.getString(scopedKey) ?? // Legacy support: fall back to global filters if present _prefs.getString(_keyLibraryFilters); if (jsonString == null) return {}; diff --git a/lib/utils/collection_playlist_play_helper.dart b/lib/utils/collection_playlist_play_helper.dart index 701afa37..61a98cf4 100644 --- a/lib/utils/collection_playlist_play_helper.dart +++ b/lib/utils/collection_playlist_play_helper.dart @@ -62,13 +62,13 @@ Future playCollectionOrPlaylist({ // Set play queue in provider final playbackState = context.read(); playbackState.setClient(client); - await playbackState.setPlaybackFromPlayQueue( - fetchedQueue, - ratingKey, - ); + await playbackState.setPlaybackFromPlayQueue(fetchedQueue, ratingKey); // Navigate to first item - await navigateToVideoPlayer(context, metadata: fetchedQueue.items!.first); + await navigateToVideoPlayer( + context, + metadata: fetchedQueue.items!.first, + ); return; } } @@ -78,9 +78,7 @@ Future playCollectionOrPlaylist({ playQueue.items!.isEmpty) { if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(t.messages.failedToCreatePlayQueueNoItems), - ), + SnackBar(content: Text(t.messages.failedToCreatePlayQueueNoItems)), ); } return; @@ -91,10 +89,7 @@ Future playCollectionOrPlaylist({ // Set play queue in provider final playbackState = context.read(); playbackState.setClient(client); - await playbackState.setPlaybackFromPlayQueue( - playQueue, - ratingKey, - ); + await playbackState.setPlaybackFromPlayQueue(playQueue, ratingKey); // Navigate to first item await navigateToVideoPlayer(context, metadata: playQueue.items!.first); diff --git a/lib/utils/error_message_utils.dart b/lib/utils/error_message_utils.dart index 7290d374..567ef238 100644 --- a/lib/utils/error_message_utils.dart +++ b/lib/utils/error_message_utils.dart @@ -22,8 +22,5 @@ String mapDioErrorToMessage(DioException error, {required String context}) { /// Generic fallback for unexpected errors. String mapUnexpectedErrorToMessage(dynamic error, {required String context}) { appLogger.e('Unexpected error in $context', error: error); - return t.errors.failedToLoad( - context: context, - error: error.toString(), - ); + return t.errors.failedToLoad(context: context, error: error.toString()); } diff --git a/lib/utils/grid_size_calculator.dart b/lib/utils/grid_size_calculator.dart index c397dc49..35f403a2 100644 --- a/lib/utils/grid_size_calculator.dart +++ b/lib/utils/grid_size_calculator.dart @@ -17,7 +17,8 @@ class GridSizeCalculator { ) { final screenWidth = MediaQuery.of(context).size.width; final isDesktop = screenWidth > desktopBreakpoint; - final isTablet = screenWidth > tabletBreakpoint && screenWidth <= desktopBreakpoint; + final isTablet = + screenWidth > tabletBreakpoint && screenWidth <= desktopBreakpoint; switch (density) { case LibraryDensity.comfortable: diff --git a/lib/utils/library_refresh_notifier.dart b/lib/utils/library_refresh_notifier.dart index fb4d08f4..712348f0 100644 --- a/lib/utils/library_refresh_notifier.dart +++ b/lib/utils/library_refresh_notifier.dart @@ -3,7 +3,8 @@ import 'dart:async'; /// Notifier for triggering refreshes of library tabs /// Singleton pattern for global access class LibraryRefreshNotifier { - static final LibraryRefreshNotifier _instance = LibraryRefreshNotifier._internal(); + static final LibraryRefreshNotifier _instance = + LibraryRefreshNotifier._internal(); factory LibraryRefreshNotifier() => _instance; diff --git a/lib/widgets/content_state_builder.dart b/lib/widgets/content_state_builder.dart index 0cae5805..5ad59cee 100644 --- a/lib/widgets/content_state_builder.dart +++ b/lib/widgets/content_state_builder.dart @@ -57,10 +57,7 @@ class ContentStateBuilder extends StatelessWidget { style: const TextStyle(color: Colors.white70), ), const SizedBox(height: 16), - ElevatedButton( - onPressed: onRetry, - child: Text(t.common.retry), - ), + ElevatedButton(onPressed: onRetry, child: Text(t.common.retry)), ], ), ); @@ -74,10 +71,7 @@ class ContentStateBuilder extends StatelessWidget { children: [ Icon(emptyIcon, size: 64, color: Colors.grey), const SizedBox(height: 16), - Text( - emptyMessage, - style: const TextStyle(color: Colors.white70), - ), + Text(emptyMessage, style: const TextStyle(color: Colors.white70)), ], ), ); diff --git a/lib/widgets/empty_state_widget.dart b/lib/widgets/empty_state_widget.dart index 78e173ad..72535100 100644 --- a/lib/widgets/empty_state_widget.dart +++ b/lib/widgets/empty_state_widget.dart @@ -42,11 +42,8 @@ class EmptyStateWidget extends StatelessWidget { message, textAlign: TextAlign.center, style: Theme.of(context).textTheme.bodyLarge?.copyWith( - color: Theme.of(context) - .colorScheme - .onSurface - .withOpacity(0.6), - ), + color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6), + ), ), if (onAction != null && actionLabel != null) ...[ const SizedBox(height: 24), diff --git a/lib/widgets/error_state_widget.dart b/lib/widgets/error_state_widget.dart index be742f7f..31559bfe 100644 --- a/lib/widgets/error_state_widget.dart +++ b/lib/widgets/error_state_widget.dart @@ -31,19 +31,15 @@ class ErrorStateWidget extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ if (icon != null) ...[ - Icon( - icon, - size: 64, - color: Theme.of(context).colorScheme.error, - ), + Icon(icon, size: 64, color: Theme.of(context).colorScheme.error), const SizedBox(height: 16), ], Text( message, textAlign: TextAlign.center, style: Theme.of(context).textTheme.bodyLarge?.copyWith( - color: Theme.of(context).colorScheme.error, - ), + color: Theme.of(context).colorScheme.error, + ), ), if (onRetry != null) ...[ const SizedBox(height: 24), diff --git a/lib/widgets/folder_tree_item.dart b/lib/widgets/folder_tree_item.dart index 384cbdb8..4c765325 100644 --- a/lib/widgets/folder_tree_item.dart +++ b/lib/widgets/folder_tree_item.dart @@ -113,7 +113,9 @@ class FolderTreeItem extends StatelessWidget { item.year.toString(), style: TextStyle( fontSize: 12, - color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6), + color: Theme.of( + context, + ).colorScheme.onSurface.withOpacity(0.6), ), ), ], diff --git a/lib/widgets/folder_tree_view.dart b/lib/widgets/folder_tree_view.dart index b9854406..371a2e48 100644 --- a/lib/widgets/folder_tree_view.dart +++ b/lib/widgets/folder_tree_view.dart @@ -15,11 +15,7 @@ class FolderTreeView extends StatefulWidget { final String libraryKey; final void Function(String)? onRefresh; - const FolderTreeView({ - super.key, - required this.libraryKey, - this.onRefresh, - }); + const FolderTreeView({super.key, required this.libraryKey, this.onRefresh}); @override State createState() => _FolderTreeViewState(); @@ -109,7 +105,9 @@ class _FolderTreeViewState extends State { _loadingFolders.remove(folder.key); }); - appLogger.d('Loaded ${children.length} children for folder: ${folder.title}'); + appLogger.d( + 'Loaded ${children.length} children for folder: ${folder.title}', + ); } catch (e) { if (!mounted) return; @@ -148,10 +146,7 @@ class _FolderTreeViewState extends State { // For episodes, start playback directly if (itemType == 'episode') { - final result = await navigateToVideoPlayer( - context, - metadata: item, - ); + final result = await navigateToVideoPlayer(context, metadata: item); if (result == true) { widget.onRefresh?.call(item.ratingKey); } @@ -181,11 +176,15 @@ class _FolderTreeViewState extends State { // Folders typically don't have a specific type or might have special indicators // Check for common folder indicators return item.key.contains('/folder') || - item.type.isEmpty || - item.type.toLowerCase() == 'folder'; + item.type.isEmpty || + item.type.toLowerCase() == 'folder'; } - List _buildTreeItems(List items, int depth, [String parentPath = '']) { + List _buildTreeItems( + List items, + int depth, [ + String parentPath = '', + ]) { final List widgets = []; for (int i = 0; i < items.length; i++) { @@ -260,9 +259,7 @@ class _FolderTreeViewState extends State { return RefreshIndicator( onRefresh: _loadRootFolders, - child: ListView( - children: _buildTreeItems(_rootFolders, 0), - ), + child: ListView(children: _buildTreeItems(_rootFolders, 0)), ); } } diff --git a/lib/widgets/hub_section.dart b/lib/widgets/hub_section.dart index c2c4f1d1..ce7f7461 100644 --- a/lib/widgets/hub_section.dart +++ b/lib/widgets/hub_section.dart @@ -45,10 +45,7 @@ class HubSection extends StatelessWidget { : null, borderRadius: BorderRadius.circular(8), child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 4, - ), + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), child: Row( children: [ Icon(icon), @@ -76,10 +73,10 @@ class HubSection extends StatelessWidget { final cardWidth = screenWidth > 1600 ? 220.0 : screenWidth > 1200 - ? 200.0 - : screenWidth > 800 - ? 190.0 - : 160.0; + ? 200.0 + : screenWidth > 800 + ? 190.0 + : 160.0; // MediaCard has 8px padding on all sides (16px total horizontally) // So actual poster width is cardWidth - 16 @@ -125,9 +122,9 @@ class HubSection extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Text( t.messages.noItemsAvailable, - style: Theme.of(context).textTheme.bodySmall?.copyWith( - color: Colors.grey, - ), + style: Theme.of( + context, + ).textTheme.bodySmall?.copyWith(color: Colors.grey), ), ), ], diff --git a/lib/widgets/media_context_menu.dart b/lib/widgets/media_context_menu.dart index 67f0327f..87a2013a 100644 --- a/lib/widgets/media_context_menu.dart +++ b/lib/widgets/media_context_menu.dart @@ -31,7 +31,8 @@ class MediaContextMenu extends StatefulWidget { final VoidCallback? onTap; final Widget child; final bool isInContinueWatching; - final String? collectionId; // The collection ID if displaying within a collection + final String? + collectionId; // The collection ID if displaying within a collection const MediaContextMenu({ super.key, @@ -65,7 +66,8 @@ class _MediaContextMenuState extends State { final itemType = isPlaylist ? 'playlist' : (metadata!.type.toLowerCase()); final isCollection = itemType == 'collection'; - final isPartiallyWatched = !isPlaylist && + final isPartiallyWatched = + !isPlaylist && metadata!.viewedLeafCount != null && metadata.leafCount != null && metadata.viewedLeafCount! > 0 && @@ -110,108 +112,104 @@ class _MediaContextMenuState extends State { } else { // Regular menu items for other types - // Mark as Watched - if (!metadata!.isWatched || isPartiallyWatched) { - menuActions.add( - _MenuAction( - value: 'watch', - icon: Icons.check_circle_outline, - label: t.mediaMenu.markAsWatched, - ), - ); - } + // Mark as Watched + if (!metadata!.isWatched || isPartiallyWatched) { + menuActions.add( + _MenuAction( + value: 'watch', + icon: Icons.check_circle_outline, + label: t.mediaMenu.markAsWatched, + ), + ); + } - // Mark as Unwatched - if (metadata.isWatched || isPartiallyWatched) { - menuActions.add( - _MenuAction( - value: 'unwatch', - icon: Icons.remove_circle_outline, - label: t.mediaMenu.markAsUnwatched, - ), - ); - } + // Mark as Unwatched + if (metadata.isWatched || isPartiallyWatched) { + menuActions.add( + _MenuAction( + value: 'unwatch', + icon: Icons.remove_circle_outline, + label: t.mediaMenu.markAsUnwatched, + ), + ); + } - // Remove from Continue Watching (only in continue watching section) - if (widget.isInContinueWatching) { - menuActions.add( - _MenuAction( - value: 'remove_from_continue_watching', - icon: Icons.close, - label: t.mediaMenu.removeFromContinueWatching, - ), - ); - } + // Remove from Continue Watching (only in continue watching section) + if (widget.isInContinueWatching) { + menuActions.add( + _MenuAction( + value: 'remove_from_continue_watching', + icon: Icons.close, + label: t.mediaMenu.removeFromContinueWatching, + ), + ); + } - // Remove from Collection (only when viewing items within a collection) - if (widget.collectionId != null) { - menuActions.add( - _MenuAction( - value: 'remove_from_collection', - icon: Icons.delete_outline, - label: t.collections.removeFromCollection, - ), - ); - } + // Remove from Collection (only when viewing items within a collection) + if (widget.collectionId != null) { + menuActions.add( + _MenuAction( + value: 'remove_from_collection', + icon: Icons.delete_outline, + label: t.collections.removeFromCollection, + ), + ); + } - // Go to Series (for episodes and seasons) - if ((itemType == 'episode' || itemType == 'season') && - metadata.grandparentTitle != null) { - menuActions.add( - _MenuAction( - value: 'series', - icon: Icons.tv, - label: t.mediaMenu.goToSeries, - ), - ); - } + // Go to Series (for episodes and seasons) + if ((itemType == 'episode' || itemType == 'season') && + metadata.grandparentTitle != null) { + menuActions.add( + _MenuAction( + value: 'series', + icon: Icons.tv, + label: t.mediaMenu.goToSeries, + ), + ); + } - // Go to Season (for episodes) - if (itemType == 'episode' && metadata.parentTitle != null) { - menuActions.add( - _MenuAction( - value: 'season', - icon: Icons.playlist_play, - label: t.mediaMenu.goToSeason, - ), - ); - } + // Go to Season (for episodes) + if (itemType == 'episode' && metadata.parentTitle != null) { + menuActions.add( + _MenuAction( + value: 'season', + icon: Icons.playlist_play, + label: t.mediaMenu.goToSeason, + ), + ); + } - // Shuffle Play (for shows and seasons) - if (itemType == 'show' || itemType == 'season') { - menuActions.add( - _MenuAction( - value: 'shuffle_play', - icon: Icons.shuffle, - label: t.mediaMenu.shufflePlay, - ), - ); - } + // Shuffle Play (for shows and seasons) + if (itemType == 'show' || itemType == 'season') { + menuActions.add( + _MenuAction( + value: 'shuffle_play', + icon: Icons.shuffle, + label: t.mediaMenu.shufflePlay, + ), + ); + } - // File Info (for episodes and movies) - if (itemType == 'episode' || itemType == 'movie') { - menuActions.add( - _MenuAction( - value: 'fileinfo', - icon: Icons.info_outline, - label: t.mediaMenu.fileInfo, - ), - ); - } + // File Info (for episodes and movies) + if (itemType == 'episode' || itemType == 'movie') { + menuActions.add( + _MenuAction( + value: 'fileinfo', + icon: Icons.info_outline, + label: t.mediaMenu.fileInfo, + ), + ); + } - // Add to... (for episodes, movies, shows, and seasons) - if (itemType == 'episode' || - itemType == 'movie' || - itemType == 'show' || - itemType == 'season') { - menuActions.add( - _MenuAction( - value: 'add_to', - icon: Icons.add, - label: t.common.addTo, - ), - ); - } + // Add to... (for episodes, movies, shows, and seasons) + if (itemType == 'episode' || + itemType == 'movie' || + itemType == 'show' || + itemType == 'season') { + menuActions.add( + _MenuAction(value: 'add_to', icon: Icons.add, label: t.common.addTo), + ); + } } // End of regular menu items else block String? selected; @@ -478,10 +476,8 @@ class _MediaContextMenuState extends State { context: context, isScrollControlled: true, backgroundColor: Colors.transparent, - builder: (context) => FileInfoBottomSheet( - fileInfo: fileInfo, - title: metadata.title, - ), + builder: (context) => + FileInfoBottomSheet(fileInfo: fileInfo, title: metadata.title), ); } else if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( @@ -722,7 +718,9 @@ class _MediaContextMenuState extends State { // If still not found, try to extract from the key field if (sectionId == null) { - final keyMatch = RegExp(r'/library/sections/(\d+)').firstMatch(metadata.key); + final keyMatch = RegExp( + r'/library/sections/(\d+)', + ).firstMatch(metadata.key); if (keyMatch != null) { sectionId = int.tryParse(keyMatch.group(1)!); appLogger.d(' - Extracted from key: $sectionId'); @@ -732,8 +730,12 @@ class _MediaContextMenuState extends State { // Last resort: try to get it from the item's parent (for episodes/seasons) if (sectionId == null && metadata.grandparentRatingKey != null) { try { - appLogger.d(' - Trying to get from parent: ${metadata.grandparentRatingKey}'); - final parentMeta = await client.getMetadata(metadata.grandparentRatingKey!); + appLogger.d( + ' - Trying to get from parent: ${metadata.grandparentRatingKey}', + ); + final parentMeta = await client.getMetadata( + metadata.grandparentRatingKey!, + ); sectionId = parentMeta?.librarySectionID; appLogger.d(' - Parent sectionId: $sectionId'); } catch (e) { @@ -747,7 +749,9 @@ class _MediaContextMenuState extends State { if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( - content: Text('Unable to determine library section for this item'), + content: Text( + 'Unable to determine library section for this item', + ), ), ); } @@ -755,14 +759,17 @@ class _MediaContextMenuState extends State { } // Load collections for this library section - final collections = await client.getLibraryCollections(sectionId.toString()); + final collections = await client.getLibraryCollections( + sectionId.toString(), + ); if (!context.mounted) return; // Show dialog to select collection or create new final result = await showDialog( context: context, - builder: (context) => _CollectionSelectionDialog(collections: collections), + builder: (context) => + _CollectionSelectionDialog(collections: collections), ); if (result == null || !context.mounted) return; @@ -778,7 +785,9 @@ class _MediaContextMenuState extends State { builder: (context) => _CreateCollectionDialog(), ); - if (collectionName == null || collectionName.isEmpty || !context.mounted) { + if (collectionName == null || + collectionName.isEmpty || + !context.mounted) { return; } @@ -800,7 +809,9 @@ class _MediaContextMenuState extends State { break; } - appLogger.d('Creating collection "$collectionName" with type $collectionType'); + appLogger.d( + 'Creating collection "$collectionName" with type $collectionType', + ); final newCollectionId = await client.createCollection( sectionId: sectionId.toString(), title: collectionName, @@ -810,10 +821,14 @@ class _MediaContextMenuState extends State { if (context.mounted) { if (newCollectionId != null) { - appLogger.d('Successfully created collection with ID: $newCollectionId'); + appLogger.d( + 'Successfully created collection with ID: $newCollectionId', + ); // Now add the item to the newly created collection - appLogger.d('Adding item to new collection $newCollectionId with URI: $itemUri'); + appLogger.d( + 'Adding item to new collection $newCollectionId with URI: $itemUri', + ); final addSuccess = await client.addToCollection( collectionId: newCollectionId, uri: itemUri, @@ -828,15 +843,15 @@ class _MediaContextMenuState extends State { LibraryRefreshNotifier().notifyCollectionsChanged(); } else { appLogger.e('Failed to add item to new collection'); - ScaffoldMessenger.of( - context, - ).showSnackBar(SnackBar(content: Text(t.collections.errorAddingToCollection))); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(t.collections.errorAddingToCollection)), + ); } } else { appLogger.e('Failed to create collection - API returned null'); - ScaffoldMessenger.of( - context, - ).showSnackBar(SnackBar(content: Text(t.collections.errorAddingToCollection))); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(t.collections.errorAddingToCollection)), + ); } } } else { @@ -850,18 +865,18 @@ class _MediaContextMenuState extends State { if (context.mounted) { if (success) { appLogger.d('Successfully added item(s) to collection $result'); - ScaffoldMessenger.of( - context, - ).showSnackBar(SnackBar(content: Text(t.collections.addedToCollection))); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(t.collections.addedToCollection)), + ); // Trigger refresh of collections tab LibraryRefreshNotifier().notifyCollectionsChanged(); } else { appLogger.e( 'Failed to add item(s) to collection $result - API returned false', ); - ScaffoldMessenger.of( - context, - ).showSnackBar(SnackBar(content: Text(t.collections.errorAddingToCollection))); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(t.collections.errorAddingToCollection)), + ); } } } @@ -874,7 +889,9 @@ class _MediaContextMenuState extends State { if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text('${t.collections.errorAddingToCollection}: ${e.toString()}'), + content: Text( + '${t.collections.errorAddingToCollection}: ${e.toString()}', + ), duration: const Duration(seconds: 5), ), ); @@ -883,7 +900,10 @@ class _MediaContextMenuState extends State { } /// Handle remove from collection action - Future _handleRemoveFromCollection(BuildContext context, PlexMetadata metadata) async { + Future _handleRemoveFromCollection( + BuildContext context, + PlexMetadata metadata, + ) async { final client = context.client; if (client == null) return; @@ -928,9 +948,7 @@ class _MediaContextMenuState extends State { if (context.mounted) { if (success) { ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(t.collections.removedFromCollection), - ), + SnackBar(content: Text(t.collections.removedFromCollection)), ); // Trigger refresh of collections tab LibraryRefreshNotifier().notifyCollectionsChanged(); @@ -938,9 +956,7 @@ class _MediaContextMenuState extends State { widget.onListRefresh?.call(); } else { ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(t.collections.removeFromCollectionFailed), - ), + SnackBar(content: Text(t.collections.removeFromCollectionFailed)), ); } } @@ -959,7 +975,11 @@ class _MediaContextMenuState extends State { } /// Handle play action for collections and playlists - Future _handlePlay(BuildContext context, bool isCollection, bool isPlaylist) async { + Future _handlePlay( + BuildContext context, + bool isCollection, + bool isPlaylist, + ) async { final client = context.client; if (client == null) return; @@ -972,7 +992,11 @@ class _MediaContextMenuState extends State { } /// Handle shuffle action for collections and playlists - Future _handleShuffle(BuildContext context, bool isCollection, bool isPlaylist) async { + Future _handleShuffle( + BuildContext context, + bool isCollection, + bool isPlaylist, + ) async { final client = context.client; if (client == null) return; @@ -985,13 +1009,18 @@ class _MediaContextMenuState extends State { } /// Handle delete action for collections and playlists - Future _handleDelete(BuildContext context, bool isCollection, bool isPlaylist) async { + Future _handleDelete( + BuildContext context, + bool isCollection, + bool isPlaylist, + ) async { final client = context.client; if (client == null) return; final itemTitle = widget.item.title; - final itemTypeLabel = - isCollection ? t.collections.collection : t.playlists.playlist; + final itemTypeLabel = isCollection + ? t.collections.collection + : t.playlists.playlist; // Show confirmation dialog final confirmed = await showDialog( @@ -1241,7 +1270,8 @@ class _CollectionSelectionDialog extends StatelessWidget { /// Dialog to create a new collection class _CreateCollectionDialog extends StatefulWidget { @override - State<_CreateCollectionDialog> createState() => _CreateCollectionDialogState(); + State<_CreateCollectionDialog> createState() => + _CreateCollectionDialogState(); } class _CreateCollectionDialogState extends State<_CreateCollectionDialog> { diff --git a/lib/widgets/sort_bottom_sheet.dart b/lib/widgets/sort_bottom_sheet.dart index 0ff146d4..8c45770f 100644 --- a/lib/widgets/sort_bottom_sheet.dart +++ b/lib/widgets/sort_bottom_sheet.dart @@ -138,10 +138,7 @@ class _SortBottomSheetState extends State { : null, leading: Radio(value: sort, toggleable: false), onTap: () { - _handleSortChange( - sort, - sort.isDefaultDescending, - ); + _handleSortChange(sort, sort.isDefaultDescending); }, ); }, diff --git a/lib/widgets/video_controls/sheets/audio_sync_sheet.dart b/lib/widgets/video_controls/sheets/audio_sync_sheet.dart index 5d1af9a3..11ac2857 100644 --- a/lib/widgets/video_controls/sheets/audio_sync_sheet.dart +++ b/lib/widgets/video_controls/sheets/audio_sync_sheet.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:media_kit/media_kit.dart'; import 'package:plezy/services/settings_service.dart'; import '../../../i18n/strings.g.dart'; +import 'base_video_control_sheet.dart'; /// Bottom sheet for adjusting audio sync offset class AudioSyncSheet extends StatefulWidget { @@ -14,23 +15,12 @@ class AudioSyncSheet extends StatefulWidget { required this.initialOffset, }); - static BoxConstraints getBottomSheetConstraints(BuildContext context) { - final size = MediaQuery.of(context).size; - final isDesktop = size.width > 600; - - return BoxConstraints( - maxWidth: isDesktop ? 700 : double.infinity, - maxHeight: isDesktop ? 400 : size.height * 0.75, - minHeight: isDesktop ? 300 : size.height * 0.5, - ); - } - static void show(BuildContext context, Player player, int initialOffset) { showModalBottomSheet( context: context, backgroundColor: Colors.grey[900], isScrollControlled: true, - constraints: getBottomSheetConstraints(context), + constraints: BaseVideoControlSheet.getBottomSheetConstraints(context), builder: (context) => AudioSyncSheet(player: player, initialOffset: initialOffset), ); diff --git a/lib/widgets/video_controls/sheets/chapter_sheet.dart b/lib/widgets/video_controls/sheets/chapter_sheet.dart index 1fa83e61..5c615eb1 100644 --- a/lib/widgets/video_controls/sheets/chapter_sheet.dart +++ b/lib/widgets/video_controls/sheets/chapter_sheet.dart @@ -49,7 +49,8 @@ class ChapterSheet extends StatelessWidget { for (int i = 0; i < chapters.length; i++) { final chapter = chapters[i]; final startMs = chapter.startTimeOffset ?? 0; - final endMs = chapter.endTimeOffset ?? + final endMs = + chapter.endTimeOffset ?? (i < chapters.length - 1 ? chapters[i + 1].startTimeOffset ?? 0 : double.maxFinite.toInt()); @@ -94,22 +95,16 @@ class ChapterSheet extends StatelessWidget { ); } return Image.network( - client.getThumbnailUrl( - chapter.thumb, - ), + client.getThumbnailUrl(chapter.thumb), width: 60, height: 34, fit: BoxFit.cover, - errorBuilder: ( - context, - error, - stackTrace, - ) => + errorBuilder: (context, error, stackTrace) => const Icon( - Icons.image, - color: Colors.white54, - size: 34, - ), + Icons.image, + color: Colors.white54, + size: 34, + ), ); }, ), @@ -118,9 +113,7 @@ class ChapterSheet extends StatelessWidget { Positioned.fill( child: Container( decoration: BoxDecoration( - borderRadius: BorderRadius.circular( - 4, - ), + borderRadius: BorderRadius.circular(4), border: Border.all( color: Colors.blue, width: 2, @@ -150,10 +143,7 @@ class ChapterSheet extends StatelessWidget { ), ), trailing: isCurrentChapter - ? const Icon( - Icons.play_circle_filled, - color: Colors.blue, - ) + ? const Icon(Icons.play_circle_filled, color: Colors.blue) : null, onTap: () { player.seek(chapter.startTime); diff --git a/lib/widgets/video_controls/sheets/playback_speed_sheet.dart b/lib/widgets/video_controls/sheets/playback_speed_sheet.dart index ad11ea0a..ce727db3 100644 --- a/lib/widgets/video_controls/sheets/playback_speed_sheet.dart +++ b/lib/widgets/video_controls/sheets/playback_speed_sheet.dart @@ -36,8 +36,9 @@ class PlaybackSpeedSheet extends StatelessWidget { final isSelected = (currentRate - speed).abs() < 0.01; // Format speed label - final label = - speed == 1.0 ? 'Normal' : '${speed.toStringAsFixed(2)}x'; + final label = speed == 1.0 + ? 'Normal' + : '${speed.toStringAsFixed(2)}x'; return ListTile( title: Text( diff --git a/lib/widgets/video_controls/sheets/subtitle_track_sheet.dart b/lib/widgets/video_controls/sheets/subtitle_track_sheet.dart index faf01b97..90dd113f 100644 --- a/lib/widgets/video_controls/sheets/subtitle_track_sheet.dart +++ b/lib/widgets/video_controls/sheets/subtitle_track_sheet.dart @@ -67,15 +67,13 @@ class SubtitleTrackSheet extends StatelessWidget { title: Text( 'Off', style: TextStyle( - color: - isOffSelected ? Colors.blue : Colors.white, + color: isOffSelected + ? Colors.blue + : Colors.white, ), ), trailing: isOffSelected - ? const Icon( - Icons.check, - color: Colors.blue, - ) + ? const Icon(Icons.check, color: Colors.blue) : null, onTap: () { player.setSubtitleTrack(SubtitleTrack.no()); @@ -107,8 +105,7 @@ class SubtitleTrackSheet extends StatelessWidget { codecName = 'SRT'; } else if (codecName == 'DVD_SUBTITLE') { codecName = 'DVD'; - } else if (codecName == 'ASS' || - codecName == 'SSA') { + } else if (codecName == 'ASS' || codecName == 'SSA') { codecName = codecName; // Keep as-is } else if (codecName == 'WEBVTT') { codecName = 'VTT'; @@ -116,8 +113,9 @@ class SubtitleTrackSheet extends StatelessWidget { parts.add(codecName); } - final label = - parts.isEmpty ? 'Track $index' : parts.join(' · '); + final label = parts.isEmpty + ? 'Track $index' + : parts.join(' · '); return ListTile( title: Text( diff --git a/lib/widgets/video_controls/sheets/version_sheet.dart b/lib/widgets/video_controls/sheets/version_sheet.dart index 32540cce..70b45e9d 100644 --- a/lib/widgets/video_controls/sheets/version_sheet.dart +++ b/lib/widgets/video_controls/sheets/version_sheet.dart @@ -45,9 +45,7 @@ class VersionSheet extends StatelessWidget { return ListTile( title: Text( version.displayLabel, - style: TextStyle( - color: isSelected ? Colors.blue : Colors.white, - ), + style: TextStyle(color: isSelected ? Colors.blue : Colors.white), ), trailing: isSelected ? const Icon(Icons.check, color: Colors.blue) diff --git a/lib/widgets/video_controls/sheets/video_settings_sheet.dart b/lib/widgets/video_controls/sheets/video_settings_sheet.dart index 28ee1211..51ee84ed 100644 --- a/lib/widgets/video_controls/sheets/video_settings_sheet.dart +++ b/lib/widgets/video_controls/sheets/video_settings_sheet.dart @@ -6,6 +6,7 @@ import '../../../utils/platform_detector.dart'; import '../widgets/sync_offset_control.dart'; import '../widgets/sleep_timer_content.dart'; import '../../../i18n/strings.g.dart'; +import 'base_video_control_sheet.dart'; enum _SettingsView { menu, speed, sleep, audioSync, subtitleSync, audioDevice } @@ -39,21 +40,12 @@ class _SettingsMenuItem extends StatelessWidget { ); return ListTile( - leading: Icon( - icon, - color: isHighlighted ? Colors.amber : Colors.white70, - ), - title: Text( - title, - style: const TextStyle(color: Colors.white), - ), + leading: Icon(icon, color: isHighlighted ? Colors.amber : Colors.white70), + title: Text(title, style: const TextStyle(color: Colors.white)), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ - if (allowValueOverflow) - Flexible(child: valueWidget) - else - valueWidget, + if (allowValueOverflow) Flexible(child: valueWidget) else valueWidget, const SizedBox(width: 8), const Icon(Icons.chevron_right, color: Colors.white70), ], @@ -76,17 +68,6 @@ class VideoSettingsSheet extends StatefulWidget { required this.subtitleSyncOffset, }); - static BoxConstraints getBottomSheetConstraints(BuildContext context) { - final size = MediaQuery.of(context).size; - final isDesktop = size.width > 600; - - return BoxConstraints( - maxWidth: isDesktop ? 700 : double.infinity, - maxHeight: isDesktop ? 400 : size.height * 0.75, - minHeight: isDesktop ? 300 : size.height * 0.5, - ); - } - static Future show( BuildContext context, Player player, @@ -97,7 +78,7 @@ class VideoSettingsSheet extends StatefulWidget { context: context, backgroundColor: Colors.grey[900], isScrollControlled: true, - constraints: getBottomSheetConstraints(context), + constraints: BaseVideoControlSheet.getBottomSheetConstraints(context), builder: (context) => VideoSettingsSheet( player: player, audioSyncOffset: audioSyncOffset, @@ -194,7 +175,6 @@ class _VideoSettingsSheetState extends State { } } - Widget _buildHeader() { final sleepTimer = SleepTimerService(); final isIconActive = diff --git a/lib/widgets/video_controls/video_controls.dart b/lib/widgets/video_controls/video_controls.dart index 88029ca2..9b8ed853 100644 --- a/lib/widgets/video_controls/video_controls.dart +++ b/lib/widgets/video_controls/video_controls.dart @@ -1624,5 +1624,4 @@ class _PlexVideoControlsState extends State } } } - }