perf(tv): exclude inactive hub rows from semantics

Their cards can't take focus until the row activates (locked-hub
model), and the per-frame semantics pass scales with node count.
This commit is contained in:
edde746
2026-07-02 11:41:25 +02:00
parent 320bde7f33
commit 48568fd412
2 changed files with 20 additions and 10 deletions
+19 -9
View File
@@ -1315,15 +1315,25 @@ class TvBrowseRailState extends State<TvBrowseRail> {
child: Stack(
clipBehavior: Clip.none,
children: [
_buildHubRailList(
hub: hub,
hubIndex: hubIndex,
episodePosterMode: episodePosterMode,
metrics: metrics,
scale: scale,
fullCardLayout: fullCardLayout,
scrollController: scrollController,
totalCount: totalCount,
// Inactive rows drop out of the semantics tree: their cards
// can't take focus until the hub is activated (locked-hub
// model), and the per-frame semantics pass on a11y-active TV
// boxes scales with node count — the active row's nodes are
// the only ones a screen reader can act on anyway.
ListenableSelector<bool>(
listenable: _focusModel,
selector: () => _focusModel.hubIndex == hubIndex,
builder: (context, isActive, child) => ExcludeSemantics(excluding: !isActive, child: child),
child: _buildHubRailList(
hub: hub,
hubIndex: hubIndex,
episodePosterMode: episodePosterMode,
metrics: metrics,
scale: scale,
fullCardLayout: fullCardLayout,
scrollController: scrollController,
totalCount: totalCount,
),
),
Positioned.fill(
left: -leftOverflow,
+1 -1
View File
@@ -102,7 +102,7 @@ class TvSpotlightBackground extends StatelessWidget {
// Expand instead of the default loose centered Stack so the
// info keeps filling the region and bottom-left aligning.
layoutBuilder: (currentChild, previousChildren) =>
Stack(fit: StackFit.expand, children: [...previousChildren, if (currentChild != null) currentChild]),
Stack(fit: StackFit.expand, children: [...previousChildren, ?currentChild]),
child: KeyedSubtree(
key: ValueKey(media.globalKey),
child: LayoutBuilder(