diff --git a/lib/utils/grid_size_calculator.dart b/lib/utils/grid_size_calculator.dart index eaf975fc..94bede84 100644 --- a/lib/utils/grid_size_calculator.dart +++ b/lib/utils/grid_size_calculator.dart @@ -76,31 +76,31 @@ class GridSizeCalculator { switch (density) { case LibraryDensity.comfortable: - divisor = 5.0; - maxItemWidth = 320; - case LibraryDensity.normal: - divisor = 6.0; + divisor = 5.5; maxItemWidth = 260; + case LibraryDensity.normal: + divisor = 6.5; + maxItemWidth = 230; case LibraryDensity.compact: - divisor = 7.5; - maxItemWidth = 200; + divisor = 9.0; + maxItemWidth = 160; } return (availableWidth / divisor).clamp(0, maxItemWidth); } else if (ScreenBreakpoints.isTablet(screenWidth)) { - // Medium screens (tablets): Fixed 3-4-5 items + // Medium screens (tablets): Fixed 3-4-6 items int targetItemCount = switch (density) { LibraryDensity.comfortable => 3, LibraryDensity.normal => 4, - LibraryDensity.compact => 5, + LibraryDensity.compact => 6, }; return availableWidth / targetItemCount; } else { - // Small screens (phones): Fixed 2-3-3 items + // Small screens (phones): Fixed 2-3-4 items int targetItemCount = switch (density) { LibraryDensity.comfortable => 2, LibraryDensity.normal => 3, - LibraryDensity.compact => 3, + LibraryDensity.compact => 4, }; return availableWidth / targetItemCount; } diff --git a/lib/utils/layout_constants.dart b/lib/utils/layout_constants.dart index 50e11519..545e7ba3 100644 --- a/lib/utils/layout_constants.dart +++ b/lib/utils/layout_constants.dart @@ -45,19 +45,19 @@ class ScreenBreakpoints { /// Grid layout constants class GridLayoutConstants { /// Maximum cross-axis extent for grid items in comfortable density mode - static const double comfortableDesktop = 280; - static const double comfortableTablet = 240; - static const double comfortableMobile = 200; + static const double comfortableDesktop = 250; + static const double comfortableTablet = 210; + static const double comfortableMobile = 180; /// Maximum cross-axis extent for grid items in compact density mode - static const double compactDesktop = 200; - static const double compactTablet = 170; - static const double compactMobile = 140; + static const double compactDesktop = 160; + static const double compactTablet = 140; + static const double compactMobile = 120; /// Maximum cross-axis extent for grid items in normal density mode - static const double normalDesktop = 240; - static const double normalTablet = 200; - static const double normalMobile = 170; + static const double normalDesktop = 220; + static const double normalTablet = 185; + static const double normalMobile = 155; /// Maximum cross-axis extent for grid items on TV (10ft viewing distance) static const double comfortableTV = 200; diff --git a/lib/widgets/hub_section.dart b/lib/widgets/hub_section.dart index 6ae87f18..6e448c1a 100644 --- a/lib/widgets/hub_section.dart +++ b/lib/widgets/hub_section.dart @@ -8,7 +8,7 @@ import 'package:provider/provider.dart'; import '../focus/dpad_navigator.dart'; import '../focus/key_event_utils.dart'; import '../providers/settings_provider.dart'; -import '../services/settings_service.dart' show EpisodePosterMode; +import '../services/settings_service.dart' show EpisodePosterMode, LibraryDensity; import '../theme/mono_tokens.dart'; import '../utils/layout_constants.dart'; import '../focus/locked_hub_controller.dart'; @@ -370,16 +370,22 @@ class HubSectionState extends State { builder: (context, constraints) { // Responsive base card width for posters (2:3 aspect ratio) final screenWidth = constraints.maxWidth; - final baseCardWidth = ScreenBreakpoints.isLargeDesktop(screenWidth) + final settings = context.watch(); + final densityScale = switch (settings.libraryDensity) { + LibraryDensity.compact => 0.8, + LibraryDensity.normal => 1.0, + LibraryDensity.comfortable => 1.15, + }; + final baseCardWidth = (ScreenBreakpoints.isLargeDesktop(screenWidth) ? 220.0 : ScreenBreakpoints.isDesktop(screenWidth) ? 200.0 : ScreenBreakpoints.isWideTablet(screenWidth) ? 190.0 - : 160.0; + : 160.0) * densityScale; // Get episode poster mode setting - final episodePosterMode = context.watch().episodePosterMode; + final episodePosterMode = settings.episodePosterMode; // Determine hub content type for layout decisions final hasEpisodes = widget.hub.items.any((item) => item.usesWideAspectRatio(episodePosterMode));