108 lines
3.9 KiB
Dart
108 lines
3.9 KiB
Dart
import 'package:bus_running_record/pages/home/page.dart' as home_v2;
|
|
import 'package:bus_running_record/pages/home_page.dart' as legacy_home;
|
|
import "package:bus_running_record/pages/operations_upload/page.dart";
|
|
import "package:bus_running_record/pages/invite/page.dart";
|
|
import "package:bus_running_record/pages/org_settings/page.dart";
|
|
import "package:bus_running_record/pages/auth/page.dart";
|
|
import "package:bus_running_record/pages/auth/verify_email_page.dart";
|
|
import "package:bus_running_record/pages/station_selection_page.dart";
|
|
import "package:bus_running_record/pages/trip_list_page.dart";
|
|
import "package:bus_running_record/provider/collaboration_state.dart";
|
|
import "package:bus_running_record/provider/supabase_state.dart";
|
|
import "package:bus_running_record/constants.dart";
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:hive_flutter/hive_flutter.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
|
|
|
void main() async {
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
await Hive.initFlutter();
|
|
await Supabase.initialize(
|
|
url: kSupabaseEndpoint,
|
|
anonKey: kSupabasePublishableKey,
|
|
);
|
|
final supabaseProvider = SupabaseProvider();
|
|
runApp(RoadboundApp(supabaseProvider: supabaseProvider));
|
|
}
|
|
|
|
class RoadboundApp extends StatefulWidget {
|
|
const RoadboundApp({required this.supabaseProvider, super.key});
|
|
|
|
final SupabaseProvider supabaseProvider;
|
|
|
|
@override
|
|
State<RoadboundApp> createState() => _RoadboundAppState();
|
|
}
|
|
|
|
class _RoadboundAppState extends State<RoadboundApp> {
|
|
late final GoRouter _routerConfig = GoRouter(
|
|
refreshListenable: widget.supabaseProvider,
|
|
routes: [
|
|
LoginPage.route,
|
|
VerifyEmailPage.route,
|
|
home_v2.HomePage.rootRoute,
|
|
home_v2.HomePage.channelRoute,
|
|
legacy_home.HomePage.route,
|
|
StationSelectionPage.route,
|
|
TripListPage.route,
|
|
OperationsUploadPage.route,
|
|
InvitePage.route,
|
|
OrganizationSettingsPage.route,
|
|
],
|
|
redirect: (context, state) {
|
|
final isLoggedIn = widget.supabaseProvider.isAuthenticated;
|
|
final isValidatingSession = widget.supabaseProvider.isValidatingSession;
|
|
final hasSession = widget.supabaseProvider.session != null;
|
|
final requestedPath = state.uri.path;
|
|
final onLogin = requestedPath == LoginPage.routePath;
|
|
final onVerify = requestedPath == VerifyEmailPage.routePath;
|
|
final onInvite = requestedPath.startsWith("/invite/");
|
|
final onLegacyFlow =
|
|
requestedPath == legacy_home.HomePage.routePath ||
|
|
requestedPath == StationSelectionPage.routePath ||
|
|
requestedPath == TripListPage.routePath;
|
|
if (onVerify) return null;
|
|
if (onInvite) return null;
|
|
if (onLegacyFlow) return null;
|
|
// Avoid login flash on cold start: keep current route until
|
|
// persisted session validation completes.
|
|
if (hasSession && isValidatingSession) return null;
|
|
if (!isLoggedIn && !onLogin) return LoginPage.routePath;
|
|
if (isLoggedIn && onLogin) {
|
|
final next = state.uri.queryParameters["next"];
|
|
return (next != null && next.isNotEmpty) ? next : "/";
|
|
}
|
|
return null;
|
|
},
|
|
);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
|
|
AdaptiveScaling? adaptiveScaling;
|
|
if (defaultTargetPlatform == TargetPlatform.iOS) {
|
|
adaptiveScaling = AdaptiveScaling(1.15);
|
|
}
|
|
|
|
return MultiProvider(
|
|
providers: [
|
|
ChangeNotifierProvider.value(value: widget.supabaseProvider),
|
|
ChangeNotifierProvider(
|
|
create: (context) =>
|
|
CollaborationProvider(context.read<SupabaseProvider>())
|
|
..initialize(),
|
|
),
|
|
],
|
|
child: ShadcnApp.router(
|
|
routerConfig: _routerConfig,
|
|
scaling: adaptiveScaling,
|
|
theme: ThemeData(
|
|
colorScheme: ColorSchemes.darkNeutral,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|