216 lines
7.3 KiB
Dart
216 lines
7.3 KiB
Dart
import 'package:flutter/widgets.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
import 'package:shadcn_ui/shadcn_ui.dart';
|
|
|
|
import '../data/providers.dart';
|
|
import '../features/detail/report_detail_page.dart';
|
|
import '../features/feed/feed_page.dart';
|
|
import '../features/home/home_page.dart';
|
|
import '../features/institutions/institution_detail_page.dart';
|
|
import '../features/institutions/institutions_page.dart';
|
|
import '../features/listen/listen_page.dart';
|
|
import '../features/profile/profile_page.dart';
|
|
import '../features/reports/reports_page.dart';
|
|
import '../features/settings/settings_page.dart';
|
|
import '../features/shell_page.dart';
|
|
import 'app_routes.dart';
|
|
|
|
final routerProvider = Provider<GoRouter>((ref) {
|
|
final dataSource = ref.read(reportDataSourceProvider);
|
|
|
|
return GoRouter(
|
|
initialLocation: AppRoutes.home,
|
|
routes: [
|
|
ShellRoute(
|
|
builder: (context, state, child) =>
|
|
ShellPage(currentPath: state.matchedLocation, child: child),
|
|
routes: [
|
|
GoRoute(
|
|
path: AppRoutes.home,
|
|
builder: (context, state) => _TabSurface(
|
|
child: Consumer(
|
|
builder: (context, ref, _) {
|
|
final player = ref.watch(audioPlayerControllerProvider);
|
|
final controller = ref.read(
|
|
audioPlayerControllerProvider.notifier,
|
|
);
|
|
return FeedPage(
|
|
dataSource: dataSource,
|
|
onPlay: controller.startFromItem,
|
|
player: player,
|
|
onStartModuleAudio: controller.startModuleAudio,
|
|
onToggleAudio: controller.toggleAudio,
|
|
onSeekAudio: controller.seekAudio,
|
|
onSpeed: controller.cycleSpeed,
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
GoRoute(
|
|
path: AppRoutes.homeFeed,
|
|
builder: (context, state) => _TabSurface(
|
|
child: Consumer(
|
|
builder: (context, ref, _) {
|
|
final player = ref.watch(audioPlayerControllerProvider);
|
|
final controller = ref.read(
|
|
audioPlayerControllerProvider.notifier,
|
|
);
|
|
return HomePage(
|
|
dataSource: dataSource,
|
|
onPlay: controller.startFromItem,
|
|
player: player,
|
|
onStartModuleAudio: controller.startModuleAudio,
|
|
onToggleAudio: controller.toggleAudio,
|
|
onSeekAudio: controller.seekAudio,
|
|
onSpeed: controller.cycleSpeed,
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
GoRoute(
|
|
path: AppRoutes.reports,
|
|
builder: (context, state) => _TabSurface(
|
|
child: Consumer(
|
|
builder: (context, ref, _) {
|
|
final player = ref.watch(audioPlayerControllerProvider);
|
|
final controller = ref.read(
|
|
audioPlayerControllerProvider.notifier,
|
|
);
|
|
return ReportsPage(
|
|
dataSource: dataSource,
|
|
onPlay: controller.startFromItem,
|
|
player: player,
|
|
onStartModuleAudio: controller.startModuleAudio,
|
|
onToggleAudio: controller.toggleAudio,
|
|
onSeekAudio: controller.seekAudio,
|
|
onSpeed: controller.cycleSpeed,
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
GoRoute(
|
|
path: AppRoutes.institutions,
|
|
builder: (context, state) =>
|
|
_TabSurface(child: InstitutionsPage(dataSource: dataSource)),
|
|
),
|
|
GoRoute(
|
|
path: AppRoutes.listen,
|
|
builder: (context, state) => _TabSurface(
|
|
child: Consumer(
|
|
builder: (context, ref, _) {
|
|
final controller = ref.read(
|
|
audioPlayerControllerProvider.notifier,
|
|
);
|
|
return ListenPage(
|
|
dataSource: dataSource,
|
|
onPlay: controller.startFromItem,
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
GoRoute(
|
|
path: AppRoutes.profile,
|
|
builder: (context, state) =>
|
|
_TabSurface(child: ProfilePage(dataSource: dataSource)),
|
|
),
|
|
],
|
|
),
|
|
GoRoute(
|
|
path: AppRoutes.reportDetail,
|
|
pageBuilder: (context, state) {
|
|
final id = state.pathParameters['id'] ?? '';
|
|
final args = state.extra as ReportDetailRouteArgs?;
|
|
return _slidePage(
|
|
state: state,
|
|
child: Consumer(
|
|
builder: (context, ref, _) {
|
|
final player = ref.watch(audioPlayerControllerProvider);
|
|
final controller = ref.read(
|
|
audioPlayerControllerProvider.notifier,
|
|
);
|
|
return ReportDetailPage(
|
|
reportId: id,
|
|
dataSource: args?.dataSource ?? dataSource,
|
|
player: player,
|
|
onStartAudio:
|
|
args?.onStartAudio ?? controller.startModuleAudio,
|
|
onToggleAudio: args?.onToggleAudio ?? controller.toggleAudio,
|
|
onSeekAudio: args?.onSeekAudio ?? controller.seekAudio,
|
|
onSpeed: args?.onSpeed ?? controller.cycleSpeed,
|
|
);
|
|
},
|
|
),
|
|
);
|
|
},
|
|
),
|
|
GoRoute(
|
|
path: AppRoutes.institutionDetail,
|
|
pageBuilder: (context, state) {
|
|
final id = state.pathParameters['id'] ?? '';
|
|
final args = state.extra as InstitutionDetailRouteArgs?;
|
|
return _slidePage(
|
|
state: state,
|
|
child: InstitutionDetailPage(
|
|
institutionId: id,
|
|
dataSource: args?.dataSource ?? dataSource,
|
|
),
|
|
);
|
|
},
|
|
),
|
|
GoRoute(
|
|
path: AppRoutes.settings,
|
|
pageBuilder: (context, state) =>
|
|
_slidePage(state: state, child: const SettingsPage()),
|
|
),
|
|
],
|
|
);
|
|
});
|
|
|
|
CustomTransitionPage<void> _slidePage({
|
|
required GoRouterState state,
|
|
required Widget child,
|
|
}) {
|
|
return CustomTransitionPage<void>(
|
|
key: state.pageKey,
|
|
transitionDuration: const Duration(milliseconds: 260),
|
|
reverseTransitionDuration: const Duration(milliseconds: 220),
|
|
child: child,
|
|
transitionsBuilder: (context, animation, secondaryAnimation, child) {
|
|
final curved = CurvedAnimation(
|
|
parent: animation,
|
|
curve: Curves.easeOutCubic,
|
|
reverseCurve: Curves.easeInCubic,
|
|
);
|
|
return FadeTransition(
|
|
opacity: curved,
|
|
child: SlideTransition(
|
|
position: Tween<Offset>(
|
|
begin: const Offset(0.08, 0),
|
|
end: Offset.zero,
|
|
).animate(curved),
|
|
child: child,
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
class _TabSurface extends StatelessWidget {
|
|
const _TabSurface({required this.child});
|
|
|
|
final Widget child;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return ColoredBox(
|
|
color: ShadTheme.of(context).colorScheme.background,
|
|
child: child,
|
|
);
|
|
}
|
|
}
|