You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
210 lines
5.8 KiB
210 lines
5.8 KiB
import 'package:flutter/material.dart';
|
|
import '../../core/service_locator.dart';
|
|
import '../../data/session/session_service.dart';
|
|
import '../../data/local/local_storage_service.dart';
|
|
import '../../data/nostr/nostr_service.dart';
|
|
import '../../data/sync/sync_engine.dart';
|
|
import '../../data/firebase/firebase_service.dart';
|
|
import '../home/home_screen.dart';
|
|
import '../immich/immich_screen.dart';
|
|
import '../nostr_events/nostr_events_screen.dart';
|
|
import '../relay_management/relay_management_screen.dart';
|
|
import '../relay_management/relay_management_controller.dart';
|
|
import '../session/session_screen.dart';
|
|
import '../settings/settings_screen.dart';
|
|
|
|
/// Route names for the app navigation.
|
|
class AppRoutes {
|
|
static const String home = '/';
|
|
static const String immich = '/immich';
|
|
static const String nostrEvents = '/nostr-events';
|
|
static const String relayManagement = '/relay-management';
|
|
static const String session = '/session';
|
|
static const String settings = '/settings';
|
|
static const String login = '/login';
|
|
}
|
|
|
|
/// Route guard that requires authentication.
|
|
class AuthGuard {
|
|
final SessionService? sessionService;
|
|
|
|
AuthGuard(this.sessionService);
|
|
|
|
/// Checks if user is authenticated.
|
|
bool get isAuthenticated => sessionService?.isLoggedIn ?? false;
|
|
|
|
/// Redirects to login if not authenticated.
|
|
String? checkAuth(String route) {
|
|
if (_requiresAuth(route) && !isAuthenticated) {
|
|
return AppRoutes.login;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// Checks if a route requires authentication.
|
|
bool _requiresAuth(String route) {
|
|
// Routes that require authentication
|
|
const protectedRoutes = [
|
|
AppRoutes.immich,
|
|
AppRoutes.nostrEvents,
|
|
AppRoutes.session,
|
|
];
|
|
return protectedRoutes.contains(route);
|
|
}
|
|
}
|
|
|
|
/// App router for managing navigation and route guards.
|
|
class AppRouter {
|
|
final SessionService? sessionService;
|
|
final LocalStorageService? localStorageService;
|
|
final NostrService? nostrService;
|
|
final SyncEngine? syncEngine;
|
|
final FirebaseService? firebaseService;
|
|
|
|
late final AuthGuard _authGuard;
|
|
|
|
AppRouter({
|
|
this.sessionService,
|
|
this.localStorageService,
|
|
this.nostrService,
|
|
this.syncEngine,
|
|
this.firebaseService,
|
|
}) {
|
|
_authGuard = AuthGuard(sessionService);
|
|
}
|
|
|
|
/// Generates routes for the app.
|
|
Route<dynamic>? generateRoute(RouteSettings settings) {
|
|
// Check route guard
|
|
final redirect = _authGuard.checkAuth(settings.name ?? '');
|
|
if (redirect != null) {
|
|
return MaterialPageRoute(
|
|
builder: (_) => _buildLoginScreen(),
|
|
settings: settings,
|
|
);
|
|
}
|
|
|
|
switch (settings.name) {
|
|
case AppRoutes.home:
|
|
return MaterialPageRoute(
|
|
builder: (_) => const HomeScreen(),
|
|
settings: settings,
|
|
);
|
|
|
|
case AppRoutes.immich:
|
|
return MaterialPageRoute(
|
|
builder: (_) => const ImmichScreen(),
|
|
settings: settings,
|
|
);
|
|
|
|
case AppRoutes.nostrEvents:
|
|
return MaterialPageRoute(
|
|
builder: (_) => const NostrEventsScreen(),
|
|
settings: settings,
|
|
);
|
|
|
|
case AppRoutes.relayManagement:
|
|
final nostrService = ServiceLocator.instance.nostrService;
|
|
final syncEngine = ServiceLocator.instance.syncEngine;
|
|
if (nostrService == null || syncEngine == null) {
|
|
return MaterialPageRoute(
|
|
builder: (_) => _buildErrorScreen('Nostr service not available'),
|
|
settings: settings,
|
|
);
|
|
}
|
|
return MaterialPageRoute(
|
|
builder: (_) => RelayManagementScreen(
|
|
controller: RelayManagementController(
|
|
nostrService: nostrService,
|
|
syncEngine: syncEngine,
|
|
),
|
|
),
|
|
settings: settings,
|
|
);
|
|
|
|
case AppRoutes.session:
|
|
return MaterialPageRoute(
|
|
builder: (_) => const SessionScreen(),
|
|
settings: settings,
|
|
);
|
|
|
|
case AppRoutes.settings:
|
|
return MaterialPageRoute(
|
|
builder: (_) => const SettingsScreen(),
|
|
settings: settings,
|
|
);
|
|
|
|
case AppRoutes.login:
|
|
return MaterialPageRoute(
|
|
builder: (_) => _buildLoginScreen(),
|
|
settings: settings,
|
|
);
|
|
|
|
default:
|
|
return MaterialPageRoute(
|
|
builder: (_) => _buildErrorScreen('Route not found: ${settings.name}'),
|
|
settings: settings,
|
|
);
|
|
}
|
|
}
|
|
|
|
Widget _buildLoginScreen() {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text('Login Required'),
|
|
),
|
|
body: Center(
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
const Icon(
|
|
Icons.lock_outline,
|
|
size: 64,
|
|
color: Colors.grey,
|
|
),
|
|
const SizedBox(height: 16),
|
|
const Text(
|
|
'Please login to access this feature',
|
|
style: TextStyle(fontSize: 16),
|
|
),
|
|
const SizedBox(height: 24),
|
|
ElevatedButton(
|
|
onPressed: () {
|
|
// Navigation will be handled by the navigation scaffold
|
|
},
|
|
child: const Text('Go to Login'),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildErrorScreen(String message) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text('Error'),
|
|
),
|
|
body: Center(
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
const Icon(
|
|
Icons.error_outline,
|
|
size: 64,
|
|
color: Colors.red,
|
|
),
|
|
const SizedBox(height: 16),
|
|
Text(
|
|
message,
|
|
style: const TextStyle(fontSize: 16),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|