feat: Android TV support (#503)

Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
PartyDonut 2025-09-28 21:07:49 +02:00 committed by GitHub
parent 7ab8c015b9
commit c299492d6d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
168 changed files with 12019 additions and 3073 deletions

View file

@ -64,25 +64,28 @@ class _NavigationBodyState extends ConsumerState<NavigationBody> {
child: widget.child,
);
return switch (AdaptiveLayout.layoutOf(context)) {
ViewSize.phone => paddedChild(),
ViewSize.tablet => hasOverlay
? SideNavigationBar(
currentIndex: widget.currentIndex,
destinations: widget.destinations,
currentLocation: widget.currentLocation,
child: paddedChild(),
scaffoldKey: widget.drawerKey,
)
: paddedChild(),
ViewSize.desktop => SideNavigationBar(
currentIndex: widget.currentIndex,
destinations: widget.destinations,
currentLocation: widget.currentLocation,
child: paddedChild(),
scaffoldKey: widget.drawerKey,
)
};
return FocusTraversalGroup(
policy: GlobalFallbackTraversalPolicy(fallbackNode: navBarNode),
child: switch (AdaptiveLayout.layoutOf(context)) {
ViewSize.phone => paddedChild(),
ViewSize.tablet => hasOverlay
? SideNavigationBar(
currentIndex: widget.currentIndex,
destinations: widget.destinations,
currentLocation: widget.currentLocation,
child: paddedChild(),
scaffoldKey: widget.drawerKey,
)
: paddedChild(),
ViewSize.desktop || ViewSize.television => SideNavigationBar(
currentIndex: widget.currentIndex,
destinations: widget.destinations,
currentLocation: widget.currentLocation,
child: paddedChild(),
scaffoldKey: widget.drawerKey,
)
},
);
}
MediaQueryData semiNestedPadding(BuildContext context, bool hasOverlay) {
@ -92,3 +95,28 @@ class _NavigationBodyState extends ConsumerState<NavigationBody> {
);
}
}
FocusNode? lastMainFocus;
class GlobalFallbackTraversalPolicy extends ReadingOrderTraversalPolicy {
final FocusNode fallbackNode;
GlobalFallbackTraversalPolicy({required this.fallbackNode}) : super();
@override
bool inDirection(FocusNode currentNode, TraversalDirection direction) {
lastMainFocus = null;
final handled = super.inDirection(currentNode, direction);
if (!handled && direction == TraversalDirection.left) {
lastMainFocus = currentNode;
if (fallbackNode.canRequestFocus && fallbackNode.context?.mounted == true) {
final cb = FocusTraversalPolicy.defaultTraversalRequestFocusCallback;
cb(fallbackNode);
return true;
}
}
return handled;
}
}