From 16e31303ae8e3724a625ea0cd480670aaf66cc4a Mon Sep 17 00:00:00 2001 From: edde746 <86283021+edde746@users.noreply.github.com> Date: Fri, 22 May 2026 17:06:51 +0200 Subject: [PATCH] fix(tv): keep spotlight background static --- lib/screens/discover_screen.dart | 32 +++++++++---------- .../tabs/library_recommended_tab.dart | 32 +++++++++---------- lib/screens/main_screen.dart | 10 ++++++ test/screens/discover_screen_test.dart | 21 ++++++------ 4 files changed, 52 insertions(+), 43 deletions(-) diff --git a/lib/screens/discover_screen.dart b/lib/screens/discover_screen.dart index e81865a7..623e3d21 100644 --- a/lib/screens/discover_screen.dart +++ b/lib/screens/discover_screen.dart @@ -1538,6 +1538,7 @@ class _DiscoverScreenState extends State ); final railSize = MainScreenFocusScope.foregroundSizeOf(context); final fullBleedWidth = MainScreenFocusScope.fullBleedWidthOf(context); + final foregroundLeft = MainScreenFocusScope.foregroundLeftOf(context); final railHeight = browseHubs.isEmpty ? 0.0 : TvBrowseRailLayout.estimateHeight( @@ -1562,23 +1563,20 @@ class _DiscoverScreenState extends State child: Stack( clipBehavior: Clip.none, children: [ - SideNavigationBleedBuilder( - targetBleed: sidebarBleed, - builder: (context, animatedBleed, _) => Positioned( - top: 0, - bottom: 0, - left: -animatedBleed, - width: fullBleedWidth, - child: TvSpotlightBackground( - item: spotlight, - client: _getMediaClientForItem(spotlight), - hideSpoilers: hideSpoilers, - contentTop: spotlightTop, - contentBottom: spotlightBottom, - contentLeft: spotlightLeft + animatedBleed, - compact: true, - showPrimaryAction: false, - ), + Positioned( + top: 0, + bottom: 0, + left: -foregroundLeft, + width: fullBleedWidth, + child: TvSpotlightBackground( + item: spotlight, + client: _getMediaClientForItem(spotlight), + hideSpoilers: hideSpoilers, + contentTop: spotlightTop, + contentBottom: spotlightBottom, + contentLeft: spotlightLeft + foregroundLeft, + compact: true, + showPrimaryAction: false, ), ), if (_isLoading || (_areHubsLoading && browseHubs.isEmpty)) const Center(child: CircularProgressIndicator()), diff --git a/lib/screens/libraries/tabs/library_recommended_tab.dart b/lib/screens/libraries/tabs/library_recommended_tab.dart index 63e0d3ec..7efb74e2 100644 --- a/lib/screens/libraries/tabs/library_recommended_tab.dart +++ b/lib/screens/libraries/tabs/library_recommended_tab.dart @@ -308,6 +308,7 @@ class _LibraryRecommendedTabState extends BaseLibraryTabState Positioned( - top: 0, - bottom: 0, - left: -animatedBleed, - width: fullBleedWidth, - child: TvSpotlightBackground( - item: spotlight, - client: client, - hideSpoilers: svc.read(SettingsService.hideSpoilers), - contentTop: spotlightTop, - contentBottom: spotlightBottom, - contentLeft: spotlightLeft + animatedBleed, - compact: true, - showPrimaryAction: false, - ), + Positioned( + top: 0, + bottom: 0, + left: -foregroundLeft, + width: fullBleedWidth, + child: TvSpotlightBackground( + item: spotlight, + client: client, + hideSpoilers: svc.read(SettingsService.hideSpoilers), + contentTop: spotlightTop, + contentBottom: spotlightBottom, + contentLeft: spotlightLeft + foregroundLeft, + compact: true, + showPrimaryAction: false, ), ), if (tvHubs.isNotEmpty) diff --git a/lib/screens/main_screen.dart b/lib/screens/main_screen.dart index b24cc879..2a146323 100644 --- a/lib/screens/main_screen.dart +++ b/lib/screens/main_screen.dart @@ -62,6 +62,7 @@ class MainScreenFocusScope extends InheritedWidget { final bool isSidebarFocused; final double sideNavigationWidth; final double? reservedSideNavigationWidth; + final double? foregroundLeft; final double? foregroundWidth; final double? viewportWidth; final void Function(String libraryGlobalKey)? selectLibrary; @@ -73,6 +74,7 @@ class MainScreenFocusScope extends InheritedWidget { required this.isSidebarFocused, required this.sideNavigationWidth, this.reservedSideNavigationWidth, + this.foregroundLeft, this.foregroundWidth, this.viewportWidth, this.selectLibrary, @@ -96,6 +98,12 @@ class MainScreenFocusScope extends InheritedWidget { return MediaQuery.sizeOf(context).width; } + static double foregroundLeftOf(BuildContext context) { + final left = of(context)?.foregroundLeft; + if (left != null) return left; + return 0.0; + } + static Size foregroundSizeOf(BuildContext context) { final size = MediaQuery.sizeOf(context); return Size(foregroundWidthOf(context), size.height); @@ -112,6 +120,7 @@ class MainScreenFocusScope extends InheritedWidget { return isSidebarFocused != oldWidget.isSidebarFocused || sideNavigationWidth != oldWidget.sideNavigationWidth || reservedSideNavigationWidth != oldWidget.reservedSideNavigationWidth || + foregroundLeft != oldWidget.foregroundLeft || foregroundWidth != oldWidget.foregroundWidth || viewportWidth != oldWidget.viewportWidth; } @@ -1334,6 +1343,7 @@ class _MainScreenState extends State isSidebarFocused: _isSidebarFocused, sideNavigationWidth: targetContentOffset, reservedSideNavigationWidth: reservedContentOffset, + foregroundLeft: contentLayout.left, foregroundWidth: contentLayout.width, viewportWidth: viewportWidth, selectLibrary: _selectLibrary, diff --git a/test/screens/discover_screen_test.dart b/test/screens/discover_screen_test.dart index fffb62e0..9432a9dc 100644 --- a/test/screens/discover_screen_test.dart +++ b/test/screens/discover_screen_test.dart @@ -101,7 +101,9 @@ void main() { storage: storage, ); final discoverKey = GlobalKey>(); - const sidebarOffset = SideNavigationRailState.expandedWidth; + const targetSidebarOffset = SideNavigationRailState.expandedWidth; + const currentForegroundLeft = 120.0; + const foregroundWidth = 1280 - SideNavigationRailState.tvCollapsedWidth; addTearDown(() async { activeProfileProvider.dispose(); @@ -131,14 +133,15 @@ void main() { focusSidebar: () {}, focusContent: () {}, isSidebarFocused: false, - sideNavigationWidth: sidebarOffset, - reservedSideNavigationWidth: sidebarOffset, - foregroundWidth: 1280 - sidebarOffset, + sideNavigationWidth: targetSidebarOffset, + reservedSideNavigationWidth: SideNavigationRailState.tvCollapsedWidth, + foregroundLeft: currentForegroundLeft, + foregroundWidth: foregroundWidth, viewportWidth: 1280, child: Align( alignment: Alignment.centerLeft, child: SizedBox( - width: 1280 - sidebarOffset, + width: foregroundWidth, height: 720, child: DiscoverScreen(key: discoverKey), ), @@ -155,10 +158,10 @@ void main() { final scale = TvLayoutConstants.scaleForSize(const Size(1280, 720)); final spotlightLeft = (24 * scale).clamp(18.0, 40.0).toDouble(); final spotlightBackground = tester.widget(find.byType(TvSpotlightBackground)); - expect(spotlightBackground.contentLeft, closeTo(spotlightLeft + sidebarOffset, 0.001)); + expect(spotlightBackground.contentLeft, closeTo(spotlightLeft + currentForegroundLeft, 0.001)); final railHeight = TvBrowseRailLayout.estimateHeight( - size: const Size(1280 - sidebarOffset, 720), + size: const Size(foregroundWidth, 720), hubs: [hub], density: LibraryDensity.max, episodePosterMode: settings.read(SettingsService.episodePosterMode), @@ -178,12 +181,12 @@ void main() { expect(spotlightBackground.contentBottom, closeTo(expectedSpotlightBottom, 0.001)); final browseRail = tester.widget(find.byType(TvBrowseRail)); - expect(browseRail.backgroundBleedLeft, sidebarOffset); + expect(browseRail.backgroundBleedLeft, targetSidebarOffset); final backgroundPosition = tester.widget( find.ancestor(of: find.byType(TvSpotlightBackground), matching: find.byType(Positioned)).first, ); - expect(backgroundPosition.left, -sidebarOffset); + expect(backgroundPosition.left, -currentForegroundLeft); expect(backgroundPosition.width, 1280); tester.state(find.byType(FocusableActionBar)).requestFocusOnFirst();