veilidchat/lib/router/cubit/router_cubit.dart

174 lines
4.9 KiB
Dart
Raw Normal View History

2023-12-26 20:26:54 -05:00
import 'dart:async';
import 'package:bloc/bloc.dart';
2024-02-11 23:18:20 -05:00
import 'package:flutter/foundation.dart';
2023-12-26 20:26:54 -05:00
import 'package:flutter/widgets.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:go_router/go_router.dart';
2024-02-11 23:18:20 -05:00
import 'package:stream_transform/stream_transform.dart';
2023-12-26 20:26:54 -05:00
2024-01-04 22:29:43 -05:00
import '../../../account_manager/account_manager.dart';
2023-12-26 20:26:54 -05:00
import '../../init.dart';
2024-01-08 21:37:08 -05:00
import '../../layout/layout.dart';
2024-02-11 23:18:20 -05:00
import '../../settings/settings.dart';
2023-12-26 20:26:54 -05:00
import '../../tools/tools.dart';
2024-01-04 22:29:43 -05:00
import '../../veilid_processor/views/developer.dart';
2023-12-26 20:26:54 -05:00
part 'router_cubit.freezed.dart';
part 'router_cubit.g.dart';
part 'router_state.dart';
2024-02-11 23:18:20 -05:00
final _rootNavKey = GlobalKey<NavigatorState>(debugLabel: 'rootNavKey');
final _homeNavKey = GlobalKey<NavigatorState>(debugLabel: 'homeNavKey');
2023-12-26 20:26:54 -05:00
class RouterCubit extends Cubit<RouterState> {
RouterCubit(AccountRepository accountRepository)
: super(const RouterState(
isInitialized: false,
hasAnyAccount: false,
hasActiveChat: false,
)) {
// Watch for changes that the router will care about
Future.delayed(Duration.zero, () async {
await eventualInitialized.future;
2024-02-14 21:33:15 -05:00
emit(state.copyWith(
isInitialized: true,
hasAnyAccount: accountRepository.getLocalAccounts().isNotEmpty));
2023-12-26 20:26:54 -05:00
});
2024-02-11 23:18:20 -05:00
2023-12-26 20:26:54 -05:00
// Subscribe to repository streams
2024-02-11 23:18:20 -05:00
_accountRepositorySubscription = accountRepository.stream.listen((event) {
2023-12-26 20:26:54 -05:00
switch (event) {
case AccountRepositoryChange.localAccounts:
emit(state.copyWith(
hasAnyAccount: accountRepository.getLocalAccounts().isNotEmpty));
break;
case AccountRepositoryChange.userLogins:
2024-02-13 22:03:26 -05:00
case AccountRepositoryChange.activeLocalAccount:
2023-12-26 20:26:54 -05:00
break;
}
});
}
2024-02-13 22:03:26 -05:00
void setHasActiveChat(bool active) {
emit(state.copyWith(hasActiveChat: active));
}
2023-12-26 20:26:54 -05:00
@override
Future<void> close() async {
await _accountRepositorySubscription.cancel();
await super.close();
}
/// Our application routes
2024-02-11 23:18:20 -05:00
List<RouteBase> get routes => [
2023-12-26 20:26:54 -05:00
GoRoute(
path: '/',
builder: (context, state) => const IndexPage(),
),
2024-02-11 23:18:20 -05:00
ShellRoute(
2024-02-13 22:03:26 -05:00
navigatorKey: _homeNavKey,
builder: (context, state, child) =>
HomeShell(child: HomeAccountReadyShell(child: child)),
routes: [
GoRoute(
path: '/home',
builder: (context, state) => const HomeAccountReadyMain(),
),
GoRoute(
path: '/home/chat',
builder: (context, state) => const HomeAccountReadyChat(),
),
],
),
2023-12-26 20:26:54 -05:00
GoRoute(
path: '/new_account',
builder: (context, state) => const NewAccountPage(),
2024-02-11 23:18:20 -05:00
),
GoRoute(
path: '/settings',
builder: (context, state) => const SettingsPage(),
2023-12-26 20:26:54 -05:00
),
GoRoute(
path: '/developer',
builder: (context, state) => const DeveloperPage(),
)
];
/// Redirects when our state changes
String? redirect(BuildContext context, GoRouterState goRouterState) {
// No matter where we are, if there's not
2024-02-11 23:18:20 -05:00
2023-12-26 20:26:54 -05:00
switch (goRouterState.matchedLocation) {
case '/':
2024-01-08 21:37:08 -05:00
// Wait for initialization to complete
if (!eventualInitialized.isCompleted) {
2023-12-26 20:26:54 -05:00
return null;
}
return state.hasAnyAccount ? '/home' : '/new_account';
case '/new_account':
return state.hasAnyAccount ? '/home' : null;
case '/home':
if (!state.hasAnyAccount) {
return '/new_account';
}
if (responsiveVisibility(
context: context,
tablet: false,
tabletLandscape: false,
desktop: false)) {
if (state.hasActiveChat) {
return '/home/chat';
}
}
return null;
case '/home/chat':
if (!state.hasAnyAccount) {
return '/new_account';
}
if (responsiveVisibility(
context: context,
tablet: false,
tabletLandscape: false,
desktop: false)) {
if (!state.hasActiveChat) {
return '/home';
}
} else {
return '/home';
}
return null;
2024-02-11 23:18:20 -05:00
case '/settings':
2023-12-26 20:26:54 -05:00
return null;
case '/developer':
return null;
default:
return state.hasAnyAccount ? null : '/new_account';
}
}
2024-02-11 23:18:20 -05:00
/// Make a GoRouter instance that uses this cubit
2024-02-12 22:30:09 -05:00
GoRouter router() {
final r = _router;
if (r != null) {
return r;
}
return _router = GoRouter(
navigatorKey: _rootNavKey,
refreshListenable: StreamListenable(stream.startWith(state).distinct()),
debugLogDiagnostics: kDebugMode,
initialLocation: '/',
routes: routes,
redirect: redirect,
);
}
2024-02-11 23:18:20 -05:00
////////////////
2023-12-26 20:26:54 -05:00
late final StreamSubscription<AccountRepositoryChange>
_accountRepositorySubscription;
2024-02-12 22:30:09 -05:00
GoRouter? _router;
2023-12-26 20:26:54 -05:00
}