fix(tv): keep spotlight background static

This commit is contained in:
edde746
2026-05-22 17:06:51 +02:00
parent e301fec38c
commit 16e31303ae
4 changed files with 52 additions and 43 deletions
+15 -17
View File
@@ -1538,6 +1538,7 @@ class _DiscoverScreenState extends State<DiscoverScreen>
);
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<DiscoverScreen>
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()),
@@ -308,6 +308,7 @@ class _LibraryRecommendedTabState extends BaseLibraryTabState<MediaHub, LibraryR
);
final railSize = MainScreenFocusScope.foregroundSizeOf(context);
final fullBleedWidth = MainScreenFocusScope.fullBleedWidthOf(context);
final foregroundLeft = MainScreenFocusScope.foregroundLeftOf(context);
final railHeight = tvHubs.isEmpty
? 0.0
: TvBrowseRailLayout.estimateHeight(
@@ -334,23 +335,20 @@ class _LibraryRecommendedTabState extends BaseLibraryTabState<MediaHub, LibraryR
fit: StackFit.expand,
clipBehavior: Clip.none,
children: [
SideNavigationBleedBuilder(
targetBleed: sidebarBleed,
builder: (context, animatedBleed, _) => 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)
+10
View File
@@ -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<MainScreen>
isSidebarFocused: _isSidebarFocused,
sideNavigationWidth: targetContentOffset,
reservedSideNavigationWidth: reservedContentOffset,
foregroundLeft: contentLayout.left,
foregroundWidth: contentLayout.width,
viewportWidth: viewportWidth,
selectLibrary: _selectLibrary,
+12 -9
View File
@@ -101,7 +101,9 @@ void main() {
storage: storage,
);
final discoverKey = GlobalKey<State<DiscoverScreen>>();
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<TvSpotlightBackground>(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<TvBrowseRail>(find.byType(TvBrowseRail));
expect(browseRail.backgroundBleedLeft, sidebarOffset);
expect(browseRail.backgroundBleedLeft, targetSidebarOffset);
final backgroundPosition = tester.widget<Positioned>(
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<FocusableActionBarState>(find.byType(FocusableActionBar)).requestFocusOnFirst();