feat(ui): add themed shell navigation

This commit is contained in:
2026-04-23 21:57:24 +02:00
parent bf67e9c2ae
commit 8cf6e95474
14 changed files with 531 additions and 122 deletions

View File

@ -0,0 +1,68 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class AppShell extends StatelessWidget {
const AppShell({
required this.child,
required this.currentLocation,
super.key,
});
final Widget child;
final String currentLocation;
@override
Widget build(BuildContext context) {
final selectedIndex = currentLocation.startsWith('/settings') ? 1 : 0;
return Scaffold(
body: DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Theme.of(context).scaffoldBackgroundColor,
Theme.of(context).colorScheme.surface,
],
),
),
child: SafeArea(bottom: false, child: child),
),
bottomNavigationBar: SafeArea(
top: false,
child: Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: ClipRRect(
borderRadius: BorderRadius.circular(24),
child: NavigationBar(
selectedIndex: selectedIndex,
onDestinationSelected: (index) {
switch (index) {
case 0:
context.go('/devices');
break;
case 1:
context.go('/settings');
break;
}
},
destinations: const [
NavigationDestination(
icon: Icon(Icons.bluetooth_searching_outlined),
selectedIcon: Icon(Icons.bluetooth_searching),
label: 'Devices',
),
NavigationDestination(
icon: Icon(Icons.settings_outlined),
selectedIcon: Icon(Icons.settings),
label: 'Settings',
),
],
),
),
),
),
);
}
}

View File

@ -12,7 +12,7 @@ class HorizontalScanningAnimation extends StatefulWidget {
this.height = 50.0,
});
@override
_HorizontalScanningAnimationState createState() =>
State<HorizontalScanningAnimation> createState() =>
_HorizontalScanningAnimationState();
}
@ -117,8 +117,6 @@ class _HorizontalWavePainter extends CustomPainter {
double currentWidth =
width * easedProgress * 0.8; // Max 80% width expansion
double startX = (width / 2) - (currentWidth / 2);
double endX = (width / 2) + (currentWidth / 2);
// Calculate opacity based on progress (fade in and out)
double opacity;
if (waveProgress < 0.1) {
@ -130,8 +128,9 @@ class _HorizontalWavePainter extends CustomPainter {
}
opacity = max(0.0, opacity); // Clamp opacity
if (opacity <= 0.0 || currentWidth < 5)
continue; // Skip drawing if invisible or too small
if (opacity <= 0.0 || currentWidth < 5) {
continue;
}
// Create the wave path
final path = Path();

View File

@ -16,7 +16,7 @@ class ScanningWaveAnimation extends StatefulWidget {
});
@override
_ScanningWaveAnimationState createState() => _ScanningWaveAnimationState();
State<ScanningWaveAnimation> createState() => _ScanningWaveAnimationState();
}
class _ScanningWaveAnimationState extends State<ScanningWaveAnimation> {