veilidchat/lib/router/router_notifier.dart

132 lines
3.8 KiB
Dart
Raw Normal View History

2023-01-09 22:50:34 -05:00
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
2023-07-23 23:13:21 -04:00
import 'package:riverpod_annotation/riverpod_annotation.dart';
2023-01-09 22:50:34 -05:00
2023-08-08 02:03:26 -04:00
import '../pages/chat_only_page.dart';
2023-07-29 10:55:35 -04:00
import '../pages/home.dart';
import '../pages/index.dart';
import '../pages/new_account.dart';
2023-08-08 02:03:26 -04:00
import '../providers/chat.dart';
2023-07-23 23:13:21 -04:00
import '../providers/local_accounts.dart';
2023-08-08 02:03:26 -04:00
import '../tools/responsive.dart';
2023-01-09 22:50:34 -05:00
2023-07-23 23:13:21 -04:00
part 'router_notifier.g.dart';
@riverpod
class RouterNotifier extends _$RouterNotifier implements Listenable {
2023-07-22 23:29:10 -04:00
/// GoRouter listener
2023-01-09 22:50:34 -05:00
VoidCallback? routerListener;
2023-07-23 23:13:21 -04:00
/// Do we need to make or import an account immediately?
bool hasAnyAccount = false;
2023-08-08 02:03:26 -04:00
bool hasActiveChat = false;
2023-07-22 23:29:10 -04:00
/// AsyncNotifier build
2023-01-09 22:50:34 -05:00
@override
Future<void> build() async {
2023-07-23 23:13:21 -04:00
hasAnyAccount = await ref.watch(
localAccountsProvider.selectAsync((data) => data.isNotEmpty),
2023-01-09 22:50:34 -05:00
);
2023-08-08 02:03:26 -04:00
hasActiveChat = ref.watch(activeChatStateProvider).asData?.value != null;
2023-01-09 22:50:34 -05:00
2023-07-22 23:29:10 -04:00
// When this notifier's state changes, inform GoRouter
2023-01-09 22:50:34 -05:00
ref.listenSelf((_, __) {
2023-07-26 17:42:11 -04:00
if (state.isLoading) {
return;
}
2023-01-09 22:50:34 -05:00
routerListener?.call();
});
}
2023-07-22 23:29:10 -04:00
/// Redirects when our state changes
2023-01-09 22:50:34 -05:00
String? redirect(BuildContext context, GoRouterState state) {
2023-07-26 17:42:11 -04:00
if (this.state.isLoading || this.state.hasError) {
return null;
}
2023-01-09 22:50:34 -05:00
2023-07-26 22:38:09 -04:00
// No matter where we are, if there's not
2023-07-22 23:29:10 -04:00
switch (state.location) {
case IndexPage.path:
2023-07-23 23:13:21 -04:00
return hasAnyAccount ? HomePage.path : NewAccountPage.path;
2023-07-26 22:38:09 -04:00
case NewAccountPage.path:
return hasAnyAccount ? HomePage.path : null;
2023-08-08 02:03:26 -04:00
case HomePage.path:
if (!hasAnyAccount) {
return NewAccountPage.path;
}
if (responsiveVisibility(
context: context,
tablet: false,
tabletLandscape: false,
desktop: false)) {
if (hasActiveChat) {
return ChatOnlyPage.path;
}
}
return null;
case ChatOnlyPage.path:
if (!hasAnyAccount) {
return NewAccountPage.path;
}
if (responsiveVisibility(
context: context,
tablet: false,
tabletLandscape: false,
desktop: false)) {
if (!hasActiveChat) {
return HomePage.path;
}
} else {
return HomePage.path;
}
return null;
2023-07-22 23:29:10 -04:00
default:
2023-07-23 23:13:21 -04:00
return hasAnyAccount ? null : NewAccountPage.path;
2023-07-04 20:33:47 -04:00
}
2023-01-09 22:50:34 -05:00
}
2023-01-10 21:04:18 -05:00
/// Our application routes
2023-01-09 22:50:34 -05:00
List<GoRoute> get routes => [
GoRoute(
path: IndexPage.path,
builder: (context, state) => const IndexPage(),
),
GoRoute(
2023-01-10 21:04:18 -05:00
path: HomePage.path,
builder: (context, state) => const HomePage(),
2023-01-09 22:50:34 -05:00
),
2023-01-10 21:04:18 -05:00
GoRoute(
path: NewAccountPage.path,
builder: (context, state) => const NewAccountPage(),
),
2023-08-08 02:03:26 -04:00
GoRoute(
path: ChatOnlyPage.path,
builder: (context, state) => const ChatOnlyPage(),
),
2023-01-09 22:50:34 -05:00
];
2023-07-22 23:29:10 -04:00
///////////////////////////////////////////////////////////////////////////
/// Listenable
2023-01-09 22:50:34 -05:00
/// Adds [GoRouter]'s listener as specified by its [Listenable].
/// [GoRouteInformationProvider] uses this method on creation to handle its
/// internal [ChangeNotifier].
/// Check out the internal implementation of [GoRouter] and
/// [GoRouteInformationProvider] to see this in action.
@override
void addListener(VoidCallback listener) {
routerListener = listener;
}
/// Removes [GoRouter]'s listener as specified by its [Listenable].
/// [GoRouteInformationProvider] uses this method when disposing,
/// so that it removes its callback when destroyed.
/// Check out the internal implementation of [GoRouter] and
/// [GoRouteInformationProvider] to see this in action.
@override
void removeListener(VoidCallback listener) {
routerListener = null;
}
}