From 522814b8ff3c7a88f067274e880a0e0c945cf7c0 Mon Sep 17 00:00:00 2001 From: Michael SCHAL Date: Thu, 11 Dec 2025 23:33:58 +0100 Subject: [PATCH] feat: Introduce `TVFocusable` widget for advanced TV navigation and focus management, alongside new `MobileSettingsTab` and `MobileScaffold` components. --- .../iptv/widgets/mobile_settings_tab.dart | 2 +- lib/mobile/widgets/mobile_scaffold.dart | 24 +++++++++---------- lib/mobile/widgets/tv_focusable.dart | 4 ++-- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/lib/mobile/features/iptv/widgets/mobile_settings_tab.dart b/lib/mobile/features/iptv/widgets/mobile_settings_tab.dart index 67c0f21..6c4c93f 100644 --- a/lib/mobile/features/iptv/widgets/mobile_settings_tab.dart +++ b/lib/mobile/features/iptv/widgets/mobile_settings_tab.dart @@ -96,7 +96,7 @@ class _MobileSettingsTabState extends ConsumerState { ), ), Text( - 'Version 1.2.5', + 'Version 1.2.6', style: GoogleFonts.inter( fontSize: 13, color: AppColors.textSecondary, diff --git a/lib/mobile/widgets/mobile_scaffold.dart b/lib/mobile/widgets/mobile_scaffold.dart index 063e203..b75a3a9 100644 --- a/lib/mobile/widgets/mobile_scaffold.dart +++ b/lib/mobile/widgets/mobile_scaffold.dart @@ -116,9 +116,9 @@ class _AppleTVNavItemState extends State<_AppleTVNavItem> { @override Widget build(BuildContext context) { - // Selected = white bg + black text, Focused = gray border + white text, Normal = white70 text - final Color textColor = widget.isSelected ? Colors.black : (_isFocused ? Colors.white : Colors.white70); - final Color iconColor = widget.isSelected ? Colors.black : (_isFocused ? Colors.white : Colors.white70); + // Selected OR Focused = black text (white bg), Normal = white70 text + final Color textColor = (widget.isSelected || _isFocused) ? Colors.black : Colors.white70; + final Color iconColor = (widget.isSelected || _isFocused) ? Colors.black : Colors.white70; return Focus( focusNode: _focusNode, @@ -141,20 +141,18 @@ class _AppleTVNavItemState extends State<_AppleTVNavItem> { padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), margin: const EdgeInsets.symmetric(horizontal: 2, vertical: 4), decoration: BoxDecoration( - // White pill background when selected, transparent otherwise - color: widget.isSelected ? Colors.white : Colors.transparent, + // White pill when selected OR focused + color: widget.isSelected + ? Colors.white + : (_isFocused ? Colors.white.withOpacity(0.9) : Colors.transparent), borderRadius: BorderRadius.circular(25), - // White border when focused - border: _isFocused - ? Border.all(color: Colors.white70, width: 2) - : null, - // Gray shadow when focused (for both selected and not selected) + // Strong glow when focused boxShadow: _isFocused ? [ BoxShadow( - color: Colors.white.withOpacity(0.4), - blurRadius: 12, - spreadRadius: 2, + color: Colors.white.withOpacity(0.5), + blurRadius: 16, + spreadRadius: 4, ), ] : null, diff --git a/lib/mobile/widgets/tv_focusable.dart b/lib/mobile/widgets/tv_focusable.dart index beb4932..76b2237 100644 --- a/lib/mobile/widgets/tv_focusable.dart +++ b/lib/mobile/widgets/tv_focusable.dart @@ -24,7 +24,7 @@ class TVFocusable extends StatefulWidget { this.onFocus, this.focusNode, this.autofocus = false, - this.scale = 1.05, + this.scale = 1.08, // More visible scale this.borderWidth = 3.0, this.focusColor = Colors.white, this.borderRadius, @@ -142,7 +142,7 @@ class _TVFocusableState extends State { onLongPress: widget.onLongPress, child: TweenAnimationBuilder( duration: const Duration(milliseconds: 200), - curve: Curves.easeOut, + curve: Curves.easeOutCubic, // Apple-like snappy curve tween: Tween( begin: 1.0, end: _isFocused ? widget.scale : 1.0,