From 58776737551fc730412f6979ff972eb15401aa3f Mon Sep 17 00:00:00 2001 From: edde746 <86283021+edde746@users.noreply.github.com> Date: Wed, 4 Mar 2026 18:28:49 +0100 Subject: [PATCH] fix: reduce UI padding between media items close #629 --- lib/screens/discover_screen.dart | 2 +- lib/screens/libraries/adaptive_media_grid.dart | 2 +- .../tabs/library_recommended_tab.dart | 2 +- lib/utils/layout_constants.dart | 2 +- lib/widgets/hub_section.dart | 18 +++++++++++------- lib/widgets/media_card.dart | 6 +++--- 6 files changed, 18 insertions(+), 14 deletions(-) diff --git a/lib/screens/discover_screen.dart b/lib/screens/discover_screen.dart index 169b2f17..bd667729 100644 --- a/lib/screens/discover_screen.dart +++ b/lib/screens/discover_screen.dart @@ -1168,7 +1168,7 @@ class _DiscoverScreenState extends State Positioned( left: 0, right: 0, - bottom: -32, // Extend 32px past the hero section bounds + bottom: -2, // Minimal overflow to avoid gap without covering hub header height: 80, // Tall enough to cover any gap child: IgnorePointer( child: Builder( diff --git a/lib/screens/libraries/adaptive_media_grid.dart b/lib/screens/libraries/adaptive_media_grid.dart index 8cad8618..de582d8b 100644 --- a/lib/screens/libraries/adaptive_media_grid.dart +++ b/lib/screens/libraries/adaptive_media_grid.dart @@ -73,7 +73,7 @@ class AdaptiveMediaGrid extends StatelessWidget { } // Extra top padding for focus decoration (scale + border extends beyond item bounds) - static const double _focusDecorationPadding = 8.0; + static const double _focusDecorationPadding = 3.0; /// Navigate focus to the sidebar void _navigateToSidebar(BuildContext context) { diff --git a/lib/screens/libraries/tabs/library_recommended_tab.dart b/lib/screens/libraries/tabs/library_recommended_tab.dart index eedc5acb..9957b64a 100644 --- a/lib/screens/libraries/tabs/library_recommended_tab.dart +++ b/lib/screens/libraries/tabs/library_recommended_tab.dart @@ -131,7 +131,7 @@ class _LibraryRecommendedTabState extends BaseLibraryTabState const EdgeInsets.only(left: 8, right: 8, bottom: 8); + static EdgeInsets get gridPadding => const EdgeInsets.only(left: 2, right: 2, bottom: 2); } diff --git a/lib/widgets/hub_section.dart b/lib/widgets/hub_section.dart index 751c2325..dd7ad95b 100644 --- a/lib/widgets/hub_section.dart +++ b/lib/widgets/hub_section.dart @@ -6,6 +6,7 @@ import 'package:plezy/widgets/app_icon.dart'; import 'package:material_symbols_icons/symbols.dart'; import 'package:provider/provider.dart'; import '../focus/dpad_navigator.dart'; +import '../focus/focus_theme.dart'; import '../focus/input_mode_tracker.dart'; import '../focus/key_event_utils.dart'; import '../providers/settings_provider.dart'; @@ -325,13 +326,13 @@ class HubSectionState extends State { children: [ // Hub header (NOT focusable - titles should not be focusable) Padding( - padding: const EdgeInsets.fromLTRB(16, 24, 16, 8), + padding: const EdgeInsets.fromLTRB(8, 12, 8, 4), child: ExcludeFocus( child: InkWell( onTap: widget.hub.more ? () => _navigateToHubDetail(context) : null, borderRadius: BorderRadius.circular(tokens(context).radiusSm), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 6), child: Row( mainAxisSize: MainAxisSize.min, children: [ @@ -420,23 +421,26 @@ class HubSectionState extends State { // Card dimensions based on hub type const wideCardMultiplier = 1.5; final cardWidth = useWideLayout ? baseCardWidth * wideCardMultiplier : baseCardWidth; - final posterWidth = cardWidth - 16; // 8px padding on each side + final posterWidth = cardWidth - 6; // 3px padding on each side final posterHeight = useWideLayout ? posterWidth * (9 / 16) // 16:9 for wide layout : posterWidth * 1.5; // 2:3 for poster layout - final containerHeight = posterHeight + 66; - _itemExtent = cardWidth + 4; + final containerHeight = posterHeight + 48; + final focusBorderWidth = FocusTheme.focusBorderWidth; + final focusExtra = focusBorderWidth * 2; // border on both sides + _itemExtent = cardWidth + focusExtra + 4; return SizedBox( - height: containerHeight, + height: containerHeight + focusExtra + 4, // extra for scale + border top/bottom child: HorizontalScrollWithArrows( controller: _scrollController, builder: (scrollController) => ListView.builder( controller: scrollController, scrollDirection: Axis.horizontal, - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 5), + clipBehavior: Clip.none, + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), itemCount: isKeyboardMode ? _totalItemCount : widget.hub.items.length, itemBuilder: (context, index) { final isItemFocused = hasFocus && index == _focusedIndex; diff --git a/lib/widgets/media_card.dart b/lib/widgets/media_card.dart index 9280c52a..e7a92fe8 100644 --- a/lib/widgets/media_card.dart +++ b/lib/widgets/media_card.dart @@ -218,7 +218,7 @@ class MediaCardState extends State { Widget _buildGridCard(BuildContext context, String semanticLabel, String? localPosterPath) { final item = widget.item; // Compute actual poster dimensions from card dimensions - final posterWidth = widget.width != null ? widget.width! - 16 : null; // 8px padding each side + final posterWidth = widget.width != null ? widget.width! - 6 : null; // 3px padding each side final posterHeight = widget.height; return SizedBox( @@ -232,7 +232,7 @@ class MediaCardState extends State { onSecondaryTap: _showContextMenu, borderRadius: BorderRadius.circular(tokens(context).radiusSm), child: Padding( - padding: const EdgeInsets.all(8), + padding: const EdgeInsets.all(3), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -278,7 +278,7 @@ class MediaCardState extends State { ], ), ), - const SizedBox(height: 4), + const SizedBox(height: 2), // Title (flattened — no inner Column) Text( item is PlexPlaylist ? item.title : (item as PlexMetadata).displayTitle,