feat: Introduce TVFocusable widget for advanced TV navigation and focus management, alongside new MobileSettingsTab and MobileScaffold components.

This commit is contained in:
Michael committed 2025-12-11 23:33:58 +01:00
1 parent c791631b09
commit 522814b8ff
3 files changed
+14 -16

No files matched your search

@@ -96,7 +96,7 @@ class _MobileSettingsTabState extends ConsumerState<MobileSettingsTab> {
), ),
), ),
Text( Text(
'Version 1.2.5', 'Version 1.2.6',
style: GoogleFonts.inter( style: GoogleFonts.inter(
fontSize: 13, fontSize: 13,
color: AppColors.textSecondary, color: AppColors.textSecondary,
+11 -13
View File
@@ -116,9 +116,9 @@ class _AppleTVNavItemState extends State<_AppleTVNavItem> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// Selected = white bg + black text, Focused = gray border + white text, Normal = white70 text // Selected OR Focused = black text (white bg), Normal = white70 text
final Color textColor = widget.isSelected ? Colors.black : (_isFocused ? Colors.white : Colors.white70); final Color textColor = (widget.isSelected || _isFocused) ? Colors.black : Colors.white70;
final Color iconColor = widget.isSelected ? Colors.black : (_isFocused ? Colors.white : Colors.white70); final Color iconColor = (widget.isSelected || _isFocused) ? Colors.black : Colors.white70;
return Focus( return Focus(
focusNode: _focusNode, focusNode: _focusNode,
@@ -141,20 +141,18 @@ class _AppleTVNavItemState extends State<_AppleTVNavItem> {
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
margin: const EdgeInsets.symmetric(horizontal: 2, vertical: 4), margin: const EdgeInsets.symmetric(horizontal: 2, vertical: 4),
decoration: BoxDecoration( decoration: BoxDecoration(
// White pill background when selected, transparent otherwise // White pill when selected OR focused
color: widget.isSelected ? Colors.white : Colors.transparent, color: widget.isSelected
? Colors.white
: (_isFocused ? Colors.white.withOpacity(0.9) : Colors.transparent),
borderRadius: BorderRadius.circular(25), borderRadius: BorderRadius.circular(25),
// White border when focused // Strong glow when focused
border: _isFocused
? Border.all(color: Colors.white70, width: 2)
: null,
// Gray shadow when focused (for both selected and not selected)
boxShadow: _isFocused boxShadow: _isFocused
? [ ? [
BoxShadow( BoxShadow(
color: Colors.white.withOpacity(0.4), color: Colors.white.withOpacity(0.5),
blurRadius: 12, blurRadius: 16,
spreadRadius: 2, spreadRadius: 4,
), ),
] ]
: null, : null,
+2 -2
View File
@@ -24,7 +24,7 @@ class TVFocusable extends StatefulWidget {
this.onFocus, this.onFocus,
this.focusNode, this.focusNode,
this.autofocus = false, this.autofocus = false,
this.scale = 1.05, this.scale = 1.08, // More visible scale
this.borderWidth = 3.0, this.borderWidth = 3.0,
this.focusColor = Colors.white, this.focusColor = Colors.white,
this.borderRadius, this.borderRadius,
@@ -142,7 +142,7 @@ class _TVFocusableState extends State<TVFocusable> {
onLongPress: widget.onLongPress, onLongPress: widget.onLongPress,
child: TweenAnimationBuilder<double>( child: TweenAnimationBuilder<double>(
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),
curve: Curves.easeOut, curve: Curves.easeOutCubic, // Apple-like snappy curve
tween: Tween<double>( tween: Tween<double>(
begin: 1.0, begin: 1.0,
end: _isFocused ? widget.scale : 1.0, end: _isFocused ? widget.scale : 1.0,