- Murattal: Spotify-style 5-button controls [Shuffle, Prev, Play, Next, Playlist] - Murattal: Animated 7-bar equalizer visualization in player circle - Murattal: Unsplash API background with frosted glass player overlay - Murattal: Transparent AppBar with backdrop blur - Murattal: Surah playlist bottom sheet with full 114 Surah list - Murattal: Auto-play disabled on screen open, enabled on navigation - Murattal: Shuffle mode for random Surah playback - Murattal: Photographer attribution per Unsplash guidelines - Dashboard: Auto-scroll prayer schedule to next active prayer - Fix: setState lifecycle errors on Reading & Murattal screens - Setup: flutter_dotenv, cached_network_image, url_launcher deps
176 lines
5.8 KiB
Dart
176 lines
5.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
|
|
import '../core/widgets/bottom_nav_bar.dart';
|
|
import '../features/dashboard/presentation/dashboard_screen.dart';
|
|
import '../features/imsakiyah/presentation/imsakiyah_screen.dart';
|
|
import '../features/checklist/presentation/checklist_screen.dart';
|
|
import '../features/laporan/presentation/laporan_screen.dart';
|
|
import '../features/tools/presentation/tools_screen.dart';
|
|
import '../features/dzikir/presentation/dzikir_screen.dart';
|
|
import '../features/qibla/presentation/qibla_screen.dart';
|
|
import '../features/quran/presentation/quran_screen.dart';
|
|
import '../features/quran/presentation/quran_reading_screen.dart';
|
|
import '../features/quran/presentation/quran_murattal_screen.dart';
|
|
import '../features/quran/presentation/quran_bookmarks_screen.dart';
|
|
import '../features/settings/presentation/settings_screen.dart';
|
|
|
|
/// Navigation key for the shell navigator (bottom-nav screens).
|
|
final _rootNavigatorKey = GlobalKey<NavigatorState>();
|
|
final _shellNavigatorKey = GlobalKey<NavigatorState>();
|
|
|
|
/// GoRouter configuration per PRD §5.2.
|
|
final GoRouter appRouter = GoRouter(
|
|
navigatorKey: _rootNavigatorKey,
|
|
initialLocation: '/',
|
|
routes: [
|
|
// ── Shell route (bottom nav persists) ──
|
|
ShellRoute(
|
|
navigatorKey: _shellNavigatorKey,
|
|
builder: (context, state, child) => _ScaffoldWithNav(child: child),
|
|
routes: [
|
|
GoRoute(
|
|
path: '/',
|
|
pageBuilder: (context, state) => const NoTransitionPage(
|
|
child: DashboardScreen(),
|
|
),
|
|
routes: [
|
|
GoRoute(
|
|
path: 'qibla',
|
|
parentNavigatorKey: _rootNavigatorKey,
|
|
builder: (context, state) => const QiblaScreen(),
|
|
),
|
|
],
|
|
),
|
|
GoRoute(
|
|
path: '/imsakiyah',
|
|
pageBuilder: (context, state) => const NoTransitionPage(
|
|
child: ImsakiyahScreen(),
|
|
),
|
|
),
|
|
GoRoute(
|
|
path: '/checklist',
|
|
pageBuilder: (context, state) => const NoTransitionPage(
|
|
child: ChecklistScreen(),
|
|
),
|
|
),
|
|
GoRoute(
|
|
path: '/laporan',
|
|
pageBuilder: (context, state) => const NoTransitionPage(
|
|
child: LaporanScreen(),
|
|
),
|
|
),
|
|
GoRoute(
|
|
path: '/tools',
|
|
pageBuilder: (context, state) => const NoTransitionPage(
|
|
child: ToolsScreen(),
|
|
),
|
|
routes: [
|
|
GoRoute(
|
|
path: 'dzikir',
|
|
parentNavigatorKey: _rootNavigatorKey,
|
|
builder: (context, state) => const DzikirScreen(),
|
|
),
|
|
GoRoute(
|
|
path: 'quran',
|
|
parentNavigatorKey: _rootNavigatorKey,
|
|
builder: (context, state) => const QuranScreen(),
|
|
routes: [
|
|
GoRoute(
|
|
path: 'bookmarks',
|
|
parentNavigatorKey: _rootNavigatorKey,
|
|
builder: (context, state) => const QuranBookmarksScreen(),
|
|
),
|
|
GoRoute(
|
|
path: ':surahId',
|
|
parentNavigatorKey: _rootNavigatorKey,
|
|
builder: (context, state) {
|
|
final surahId = state.pathParameters['surahId']!;
|
|
final startVerse = int.tryParse(state.uri.queryParameters['startVerse'] ?? '');
|
|
return QuranReadingScreen(surahId: surahId, initialVerse: startVerse);
|
|
},
|
|
routes: [
|
|
GoRoute(
|
|
path: 'murattal',
|
|
parentNavigatorKey: _rootNavigatorKey,
|
|
builder: (context, state) {
|
|
final surahId = state.pathParameters['surahId']!;
|
|
final qariId = state.uri.queryParameters['qariId'];
|
|
final autoplay = state.uri.queryParameters['autoplay'] == 'true';
|
|
return QuranMurattalScreen(
|
|
surahId: surahId,
|
|
initialQariId: qariId,
|
|
autoPlay: autoplay,
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
GoRoute(
|
|
path: 'qibla',
|
|
parentNavigatorKey: _rootNavigatorKey,
|
|
builder: (context, state) => const QiblaScreen(),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
// ── Settings (pushed, no bottom nav) ──
|
|
GoRoute(
|
|
path: '/settings',
|
|
parentNavigatorKey: _rootNavigatorKey,
|
|
builder: (context, state) => const SettingsScreen(),
|
|
),
|
|
],
|
|
);
|
|
|
|
/// Scaffold wrapper that provides the persistent bottom nav bar.
|
|
class _ScaffoldWithNav extends StatelessWidget {
|
|
const _ScaffoldWithNav({required this.child});
|
|
|
|
final Widget child;
|
|
|
|
/// Maps route locations to bottom nav indices.
|
|
int _currentIndex(BuildContext context) {
|
|
final location = GoRouterState.of(context).uri.toString();
|
|
if (location.startsWith('/imsakiyah')) return 1;
|
|
if (location.startsWith('/checklist')) return 2;
|
|
if (location.startsWith('/laporan')) return 3;
|
|
if (location.startsWith('/tools')) return 4;
|
|
return 0;
|
|
}
|
|
|
|
void _onTap(BuildContext context, int index) {
|
|
switch (index) {
|
|
case 0:
|
|
context.go('/');
|
|
break;
|
|
case 1:
|
|
context.go('/imsakiyah');
|
|
break;
|
|
case 2:
|
|
context.go('/checklist');
|
|
break;
|
|
case 3:
|
|
context.go('/laporan');
|
|
break;
|
|
case 4:
|
|
context.go('/tools');
|
|
break;
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
body: child,
|
|
bottomNavigationBar: AppBottomNavBar(
|
|
currentIndex: _currentIndex(context),
|
|
onTap: (i) => _onTap(context, i),
|
|
),
|
|
);
|
|
}
|
|
}
|