[Feature] Replace go_router with auto_route

This commit is contained in:
PartyDonut 2024-10-05 16:29:51 +02:00
parent b31cc86ae8
commit 144c8faf70
42 changed files with 1181 additions and 980 deletions

View file

@ -1,121 +0,0 @@
import 'package:fladder/providers/shared_provider.dart';
import 'package:fladder/providers/user_provider.dart';
import 'package:fladder/routes/build_routes/home_routes.dart';
import 'package:fladder/routes/build_routes/route_builder.dart';
import 'package:fladder/routes/build_routes/settings_routes.dart';
import 'package:fladder/screens/home.dart';
import 'package:fladder/screens/settings/settings_screen.dart';
import 'package:fladder/util/adaptive_layout.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
class AppRoutes {
static final parentKey = GlobalKey<NavigatorState>();
static final homeShellKey = GlobalKey<NavigatorState>();
static final settingsKey = GlobalKey<NavigatorState>();
static final loginRoute = LoginRoute();
static final splashRoute = SplashRoute();
static final scrollController = ScrollController();
static GoRouter routes({required WidgetRef ref, required ScreenLayout screenLayout}) {
return GoRouter(
navigatorKey: parentKey,
initialLocation: splashRoute.route,
//Only useful for web if the user is not in an active session yet
redirect: kIsWeb
? (context, state) async {
if (state.uri.toString() == loginRoute.route || state.uri.toString() == splashRoute.route) return null;
await Future.microtask(() {
final lastUsedAccount = ref.read(sharedUtilityProvider).getActiveAccount();
if (lastUsedAccount == null) return loginRoute.route;
if (ref.read(userProvider) == null) ref.read(userProvider.notifier).loginUser(lastUsedAccount);
});
if (ref.read(userProvider) == null) {
return loginRoute.route;
} else {
return state.uri.toString();
}
}
: null,
routes: AppRoutes().getRoutes(screenLayout),
);
}
List<RouteBase> getRoutes(ScreenLayout screenLayout) {
switch (screenLayout) {
case ScreenLayout.single:
return linearRoutes;
case ScreenLayout.dual:
return nestedRoutes;
}
}
static List<RouteBase> linearRoutes = [
loginRoute.go,
splashRoute.go,
LockScreenRoute().go,
ShellRoute(
navigatorKey: homeShellKey,
pageBuilder: (context, state, child) {
return NoTransitionPage(
child: Home(
key: state.pageKey,
location: state.uri.toString(),
nestedChild: child,
),
);
},
routes: [
DashboardRoute().go,
FavouritesRoute().go,
SyncRoute().go,
],
),
DetailsRoute(navKey: parentKey).go,
LibrarySearchRoute(navKey: parentKey).go,
// Settings routes
SettingsRoute(navKey: parentKey).go,
ClientSettingsRoute(navKey: parentKey).go,
SecuritySettingsRoute(navKey: parentKey).go,
PlayerSettingsRoute(navKey: parentKey).go,
];
static List<RouteBase> nestedRoutes = [
loginRoute.go,
splashRoute.go,
LockScreenRoute().go,
ShellRoute(
navigatorKey: homeShellKey,
pageBuilder: (context, state, child) => NoTransitionPage(
child: Home(
key: state.pageKey,
location: state.uri.toString(),
nestedChild: child,
),
),
routes: [
ShellRoute(
navigatorKey: settingsKey,
pageBuilder: (context, state, child) => NoTransitionPage(
key: state.pageKey,
child: SettingsScreen(location: state.uri.toString(), child: child),
),
routes: [
ClientSettingsRoute(navKey: settingsKey).go,
SecuritySettingsRoute(navKey: settingsKey).go,
PlayerSettingsRoute(navKey: settingsKey).go,
],
),
DashboardRoute().go,
FavouritesRoute().go,
SyncRoute().go,
DetailsRoute(navKey: homeShellKey).go,
LibrarySearchRoute(navKey: homeShellKey).go,
],
),
];
}

135
lib/routes/auto_router.dart Normal file
View file

@ -0,0 +1,135 @@
import 'package:flutter/foundation.dart';
import 'package:auto_route/auto_route.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fladder/providers/user_provider.dart';
import 'package:fladder/routes/auto_router.gr.dart';
import 'package:fladder/screens/login/lock_screen.dart';
import 'package:fladder/util/adaptive_layout.dart';
@AutoRouterConfig(replaceInRouteName: 'Screen|Page,Route')
class AutoRouter extends RootStackRouter {
AutoRouter({required this.layout, required this.ref});
final WidgetRef ref;
final ScreenLayout layout;
@override
List<AutoRouteGuard> get guards => [...super.guards, AuthGuard(ref: ref)];
@override
RouteType get defaultRouteType => kIsWeb ? const RouteType.material() : const RouteType.adaptive();
@override
List<AutoRoute> get routes => [
..._defaultRoutes,
...(layout == ScreenLayout.dual ? desktopRoutes : mobileRoutes),
];
final List<AutoRoute> mobileRoutes = [
_homeRoute.copyWith(
children: [
_dashboardRoute,
_favouritesRoute,
_syncedRoute,
],
),
AutoRoute(page: DetailsRoute.page, path: '/details'),
AutoRoute(page: LibrarySearchRoute.page, path: '/library'),
AutoRoute(page: SettingsRoute.page, path: '/settings'),
..._settingsChildren.map(
(e) => e.copyWith(path: "/$e", initial: false),
),
AutoRoute(page: LockRoute.page, path: '/locked'),
];
final List<AutoRoute> desktopRoutes = [
_homeRoute.copyWith(
children: [
_dashboardRoute,
_favouritesRoute,
_syncedRoute,
AutoRoute(page: DetailsRoute.page, path: 'details'),
AutoRoute(page: LibrarySearchRoute.page, path: 'library'),
AutoRoute(
page: SettingsRoute.page,
path: 'settings',
children: _settingsChildren,
)
],
),
AutoRoute(page: LockRoute.page, path: '/locked'),
];
}
final List<AutoRoute> _defaultRoutes = [
AutoRoute(page: SplashRoute.page, path: '/splash'),
AutoRoute(page: LoginRoute.page, path: '/login'),
];
final AutoRoute _homeRoute = AutoRoute(page: HomeRoute.page, path: '/');
final AutoRoute _dashboardRoute = CustomRoute(
page: DashboardRoute.page,
transitionsBuilder: TransitionsBuilders.fadeIn,
initial: true,
path: 'dashboard',
maintainState: false,
);
final AutoRoute _favouritesRoute = CustomRoute(
page: FavouritesRoute.page,
transitionsBuilder: TransitionsBuilders.fadeIn,
path: 'favourites',
maintainState: false,
);
final AutoRoute _syncedRoute = CustomRoute(
page: SyncedRoute.page,
transitionsBuilder: TransitionsBuilders.fadeIn,
path: 'synced',
maintainState: false,
);
final List<AutoRoute> _settingsChildren = [
CustomRoute(
page: ClientSettingsRoute.page, initial: true, transitionsBuilder: TransitionsBuilders.fadeIn, path: 'client'),
CustomRoute(page: SecuritySettingsRoute.page, transitionsBuilder: TransitionsBuilders.fadeIn, path: 'security'),
CustomRoute(page: PlayerSettingsRoute.page, transitionsBuilder: TransitionsBuilders.fadeIn, path: 'player'),
];
class LockScreenGuard extends AutoRouteGuard {
final WidgetRef ref;
const LockScreenGuard({required this.ref});
@override
Future<void> onNavigation(NavigationResolver resolver, StackRouter router) async {
if (ref.read(lockScreenActiveProvider) && resolver.routeName != const LockRoute().routeName) {
router.replace(const LockRoute());
return;
} else {
return resolver.next(true);
}
}
}
class AuthGuard extends AutoRouteGuard {
final WidgetRef ref;
const AuthGuard({required this.ref});
@override
Future<void> onNavigation(NavigationResolver resolver, StackRouter router) async {
if (ref.read(userProvider) != null ||
resolver.routeName == const LoginRoute().routeName ||
resolver.routeName == SplashRoute().routeName) {
return resolver.next(true);
}
resolver.redirect<bool>(SplashRoute(loggedIn: (value) {
if (value) {
resolver.next(true);
} else {
router.navigate(const LoginRoute());
}
}));
}
}

View file

@ -0,0 +1,445 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// **************************************************************************
// AutoRouterGenerator
// **************************************************************************
// ignore_for_file: type=lint
// coverage:ignore-file
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:auto_route/auto_route.dart' as _i14;
import 'package:fladder/models/item_base_model.dart' as _i15;
import 'package:fladder/models/items/photos_model.dart' as _i18;
import 'package:fladder/models/library_search/library_search_options.dart'
as _i17;
import 'package:fladder/routes/nested_details_screen.dart' as _i3;
import 'package:fladder/screens/dashboard/dashboard_screen.dart' as _i2;
import 'package:fladder/screens/favourites/favourites_screen.dart' as _i4;
import 'package:fladder/screens/home_screen.dart' as _i5;
import 'package:fladder/screens/library_search/library_search_screen.dart'
as _i6;
import 'package:fladder/screens/login/lock_screen.dart' as _i7;
import 'package:fladder/screens/login/login_screen.dart' as _i8;
import 'package:fladder/screens/settings/client_settings_page.dart' as _i1;
import 'package:fladder/screens/settings/player_settings_page.dart' as _i9;
import 'package:fladder/screens/settings/security_settings_page.dart' as _i10;
import 'package:fladder/screens/settings/settings_screen.dart' as _i11;
import 'package:fladder/screens/splash_screen.dart' as _i12;
import 'package:fladder/screens/syncing/synced_screen.dart' as _i13;
import 'package:flutter/material.dart' as _i16;
/// generated route for
/// [_i1.ClientSettingsPage]
class ClientSettingsRoute extends _i14.PageRouteInfo<void> {
const ClientSettingsRoute({List<_i14.PageRouteInfo>? children})
: super(
ClientSettingsRoute.name,
initialChildren: children,
);
static const String name = 'ClientSettingsRoute';
static _i14.PageInfo page = _i14.PageInfo(
name,
builder: (data) {
return const _i1.ClientSettingsPage();
},
);
}
/// generated route for
/// [_i2.DashboardScreen]
class DashboardRoute extends _i14.PageRouteInfo<void> {
const DashboardRoute({List<_i14.PageRouteInfo>? children})
: super(
DashboardRoute.name,
initialChildren: children,
);
static const String name = 'DashboardRoute';
static _i14.PageInfo page = _i14.PageInfo(
name,
builder: (data) {
return const _i2.DashboardScreen();
},
);
}
/// generated route for
/// [_i3.DetailsScreen]
class DetailsRoute extends _i14.PageRouteInfo<DetailsRouteArgs> {
DetailsRoute({
String id = '',
_i15.ItemBaseModel? item,
_i16.Key? key,
List<_i14.PageRouteInfo>? children,
}) : super(
DetailsRoute.name,
args: DetailsRouteArgs(
id: id,
item: item,
key: key,
),
rawQueryParams: {'id': id},
initialChildren: children,
);
static const String name = 'DetailsRoute';
static _i14.PageInfo page = _i14.PageInfo(
name,
builder: (data) {
final queryParams = data.queryParams;
final args = data.argsAs<DetailsRouteArgs>(
orElse: () => DetailsRouteArgs(
id: queryParams.getString(
'id',
'',
)));
return _i3.DetailsScreen(
id: args.id,
item: args.item,
key: args.key,
);
},
);
}
class DetailsRouteArgs {
const DetailsRouteArgs({
this.id = '',
this.item,
this.key,
});
final String id;
final _i15.ItemBaseModel? item;
final _i16.Key? key;
@override
String toString() {
return 'DetailsRouteArgs{id: $id, item: $item, key: $key}';
}
}
/// generated route for
/// [_i4.FavouritesScreen]
class FavouritesRoute extends _i14.PageRouteInfo<void> {
const FavouritesRoute({List<_i14.PageRouteInfo>? children})
: super(
FavouritesRoute.name,
initialChildren: children,
);
static const String name = 'FavouritesRoute';
static _i14.PageInfo page = _i14.PageInfo(
name,
builder: (data) {
return const _i4.FavouritesScreen();
},
);
}
/// generated route for
/// [_i5.HomeScreen]
class HomeRoute extends _i14.PageRouteInfo<void> {
const HomeRoute({List<_i14.PageRouteInfo>? children})
: super(
HomeRoute.name,
initialChildren: children,
);
static const String name = 'HomeRoute';
static _i14.PageInfo page = _i14.PageInfo(
name,
builder: (data) {
return const _i5.HomeScreen();
},
);
}
/// generated route for
/// [_i6.LibrarySearchScreen]
class LibrarySearchRoute extends _i14.PageRouteInfo<LibrarySearchRouteArgs> {
LibrarySearchRoute({
String? viewModelId,
List<String>? folderId,
bool? favourites,
_i17.SortingOrder? sortOrder,
_i17.SortingOptions? sortingOptions,
_i18.PhotoModel? photoToView,
_i16.Key? key,
List<_i14.PageRouteInfo>? children,
}) : super(
LibrarySearchRoute.name,
args: LibrarySearchRouteArgs(
viewModelId: viewModelId,
folderId: folderId,
favourites: favourites,
sortOrder: sortOrder,
sortingOptions: sortingOptions,
photoToView: photoToView,
key: key,
),
rawQueryParams: {
'parentId': viewModelId,
'folderId': folderId,
'favourites': favourites,
'sortOrder': sortOrder,
'sortOptions': sortingOptions,
},
initialChildren: children,
);
static const String name = 'LibrarySearchRoute';
static _i14.PageInfo page = _i14.PageInfo(
name,
builder: (data) {
final queryParams = data.queryParams;
final args = data.argsAs<LibrarySearchRouteArgs>(
orElse: () => LibrarySearchRouteArgs(
viewModelId: queryParams.optString('parentId'),
folderId: queryParams.optList('folderId'),
favourites: queryParams.optBool('favourites'),
sortOrder: queryParams.get('sortOrder'),
sortingOptions: queryParams.get('sortOptions'),
));
return _i6.LibrarySearchScreen(
viewModelId: args.viewModelId,
folderId: args.folderId,
favourites: args.favourites,
sortOrder: args.sortOrder,
sortingOptions: args.sortingOptions,
photoToView: args.photoToView,
key: args.key,
);
},
);
}
class LibrarySearchRouteArgs {
const LibrarySearchRouteArgs({
this.viewModelId,
this.folderId,
this.favourites,
this.sortOrder,
this.sortingOptions,
this.photoToView,
this.key,
});
final String? viewModelId;
final List<String>? folderId;
final bool? favourites;
final _i17.SortingOrder? sortOrder;
final _i17.SortingOptions? sortingOptions;
final _i18.PhotoModel? photoToView;
final _i16.Key? key;
@override
String toString() {
return 'LibrarySearchRouteArgs{viewModelId: $viewModelId, folderId: $folderId, favourites: $favourites, sortOrder: $sortOrder, sortingOptions: $sortingOptions, photoToView: $photoToView, key: $key}';
}
}
/// generated route for
/// [_i7.LockScreen]
class LockRoute extends _i14.PageRouteInfo<void> {
const LockRoute({List<_i14.PageRouteInfo>? children})
: super(
LockRoute.name,
initialChildren: children,
);
static const String name = 'LockRoute';
static _i14.PageInfo page = _i14.PageInfo(
name,
builder: (data) {
return const _i7.LockScreen();
},
);
}
/// generated route for
/// [_i8.LoginScreen]
class LoginRoute extends _i14.PageRouteInfo<void> {
const LoginRoute({List<_i14.PageRouteInfo>? children})
: super(
LoginRoute.name,
initialChildren: children,
);
static const String name = 'LoginRoute';
static _i14.PageInfo page = _i14.PageInfo(
name,
builder: (data) {
return const _i8.LoginScreen();
},
);
}
/// generated route for
/// [_i9.PlayerSettingsPage]
class PlayerSettingsRoute extends _i14.PageRouteInfo<void> {
const PlayerSettingsRoute({List<_i14.PageRouteInfo>? children})
: super(
PlayerSettingsRoute.name,
initialChildren: children,
);
static const String name = 'PlayerSettingsRoute';
static _i14.PageInfo page = _i14.PageInfo(
name,
builder: (data) {
return const _i9.PlayerSettingsPage();
},
);
}
/// generated route for
/// [_i10.SecuritySettingsPage]
class SecuritySettingsRoute extends _i14.PageRouteInfo<void> {
const SecuritySettingsRoute({List<_i14.PageRouteInfo>? children})
: super(
SecuritySettingsRoute.name,
initialChildren: children,
);
static const String name = 'SecuritySettingsRoute';
static _i14.PageInfo page = _i14.PageInfo(
name,
builder: (data) {
return const _i10.SecuritySettingsPage();
},
);
}
/// generated route for
/// [_i11.SettingsScreen]
class SettingsRoute extends _i14.PageRouteInfo<void> {
const SettingsRoute({List<_i14.PageRouteInfo>? children})
: super(
SettingsRoute.name,
initialChildren: children,
);
static const String name = 'SettingsRoute';
static _i14.PageInfo page = _i14.PageInfo(
name,
builder: (data) {
return const _i11.SettingsScreen();
},
);
}
/// generated route for
/// [_i12.SplashScreen]
class SplashRoute extends _i14.PageRouteInfo<SplashRouteArgs> {
SplashRoute({
dynamic Function(bool)? loggedIn,
_i16.Key? key,
List<_i14.PageRouteInfo>? children,
}) : super(
SplashRoute.name,
args: SplashRouteArgs(
loggedIn: loggedIn,
key: key,
),
initialChildren: children,
);
static const String name = 'SplashRoute';
static _i14.PageInfo page = _i14.PageInfo(
name,
builder: (data) {
final args =
data.argsAs<SplashRouteArgs>(orElse: () => const SplashRouteArgs());
return _i12.SplashScreen(
loggedIn: args.loggedIn,
key: args.key,
);
},
);
}
class SplashRouteArgs {
const SplashRouteArgs({
this.loggedIn,
this.key,
});
final dynamic Function(bool)? loggedIn;
final _i16.Key? key;
@override
String toString() {
return 'SplashRouteArgs{loggedIn: $loggedIn, key: $key}';
}
}
/// generated route for
/// [_i13.SyncedScreen]
class SyncedRoute extends _i14.PageRouteInfo<SyncedRouteArgs> {
SyncedRoute({
_i16.ScrollController? navigationScrollController,
_i16.Key? key,
List<_i14.PageRouteInfo>? children,
}) : super(
SyncedRoute.name,
args: SyncedRouteArgs(
navigationScrollController: navigationScrollController,
key: key,
),
initialChildren: children,
);
static const String name = 'SyncedRoute';
static _i14.PageInfo page = _i14.PageInfo(
name,
builder: (data) {
final args =
data.argsAs<SyncedRouteArgs>(orElse: () => const SyncedRouteArgs());
return _i13.SyncedScreen(
navigationScrollController: args.navigationScrollController,
key: args.key,
);
},
);
}
class SyncedRouteArgs {
const SyncedRouteArgs({
this.navigationScrollController,
this.key,
});
final _i16.ScrollController? navigationScrollController;
final _i16.Key? key;
@override
String toString() {
return 'SyncedRouteArgs{navigationScrollController: $navigationScrollController, key: $key}';
}
}

View file

@ -1,182 +0,0 @@
import 'package:animations/animations.dart';
import 'package:collection/collection.dart';
import 'package:fladder/jellyfin/jellyfin_open_api.enums.swagger.dart';
import 'package:fladder/models/item_base_model.dart';
import 'package:fladder/models/library_search/library_search_options.dart';
import 'package:fladder/routes/app_routes.dart';
import 'package:fladder/routes/build_routes/route_builder.dart';
import 'package:fladder/screens/dashboard/dashboard_screen.dart';
import 'package:fladder/screens/syncing/synced_screen.dart';
import 'package:fladder/screens/favourites/favourites_screen.dart';
import 'package:fladder/screens/library_search/library_search_screen.dart';
import 'package:fladder/screens/shared/detail_scaffold.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class DashboardRoute extends CustomRoute {
DashboardRoute() : super(name: 'Dashboard', basePath: '/dashboard');
@override
GoRoute get go => GoRoute(
path: basePath,
parentNavigatorKey: AppRoutes.homeShellKey,
pageBuilder: (context, state) {
return CustomTransitionPage(
key: state.pageKey,
child: DashboardScreen(
key: Key(basePath),
navigationScrollController: AppRoutes.scrollController,
),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return FadeTransition(
opacity: CurveTween(curve: Curves.easeInOutCirc).animate(animation),
child: child,
);
});
},
);
}
class FavouritesRoute extends CustomRoute {
FavouritesRoute() : super(name: 'Favorites', basePath: '/favorites');
@override
GoRoute get go => GoRoute(
path: basePath,
parentNavigatorKey: AppRoutes.homeShellKey,
pageBuilder: (context, state) {
return CustomTransitionPage(
key: state.pageKey,
child: FavouritesScreen(
key: Key(basePath),
navigationScrollController: AppRoutes.scrollController,
),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return FadeTransition(
opacity: CurveTween(curve: Curves.easeInOutCirc).animate(animation),
child: child,
);
});
},
);
}
class SyncRoute extends CustomRoute {
SyncRoute() : super(name: 'Sync', basePath: '/sync');
@override
GoRoute get go => GoRoute(
path: basePath,
parentNavigatorKey: AppRoutes.homeShellKey,
pageBuilder: (context, state) {
return CustomTransitionPage(
key: state.pageKey,
child: SyncedScreen(
key: Key(basePath),
navigationScrollController: AppRoutes.scrollController,
),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return FadeTransition(
opacity: CurveTween(curve: Curves.easeInOutCirc).animate(animation),
child: child,
);
});
},
);
}
class DetailsRoute extends CustomRoute {
final String? id;
final GlobalKey<NavigatorState>? navKey;
DetailsRoute({this.id, this.navKey}) : super(name: 'Details', basePath: '/details', arguments: ':itemId');
@override
String get route => "$basePath/$id";
@override
GoRoute get go => GoRoute(
path: path,
parentNavigatorKey: navKey,
pageBuilder: (context, state) {
final String id = state.pathParameters['itemId'] ?? "nothing";
ItemBaseModel? item = state.extra as ItemBaseModel?;
return CustomTransitionPage(
key: state.pageKey,
child: DetailScreen(
key: Key(id),
id: id,
item: item,
),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return FadeThroughTransition(
animation: animation,
secondaryAnimation: secondaryAnimation,
child: child,
);
},
);
},
);
}
const _libraryKey = "libraryId";
const _sortOptionsKey = "sortOptions";
const _sortOrderKey = "sortOrder";
const _favoriteKey = "favorite";
const _folderKey = "folder";
class LibrarySearchRoute extends CustomRoute {
final String? id;
final bool? favorites;
final SortingOptions? sortOptions;
final SortOrder? sortOrder;
final String? folderId;
final GlobalKey<NavigatorState>? navKey;
LibrarySearchRoute({this.id, this.favorites, this.sortOptions, this.sortOrder, this.folderId, this.navKey})
: super(
name: 'LibrarySearch',
basePath: '/library',
queryParameters: {
_libraryKey: id,
_sortOptionsKey: sortOptions?.name,
_sortOrderKey: sortOrder?.name,
_favoriteKey: favorites,
_folderKey: folderId,
},
);
@override
String get route => "$basePath${parseUrlParameters(queryParameters)}";
@override
GoRoute get go => GoRoute(
path: basePath,
parentNavigatorKey: navKey,
pageBuilder: (context, state) {
final String? id = state.uri.queryParameters[_libraryKey];
final bool? favourites = bool.tryParse(state.uri.queryParameters[_favoriteKey] ?? "");
final String? folderId = state.uri.queryParameters[_folderKey];
final SortingOptions? sortingOptions = SortingOptions.values
.firstWhereOrNull((element) => element.name == state.uri.queryParameters[_sortOptionsKey]);
final SortingOrder? sortOrder = SortingOrder.values
.firstWhereOrNull((element) => element.name == state.uri.queryParameters[_sortOrderKey]);
return CustomTransitionPage(
key: state.pageKey,
child: LibrarySearchScreen(
key: Key(id ?? "librarySearch"),
viewModelId: id,
folderId: folderId?.split(','),
sortingOptions: sortingOptions,
sortOrder: sortOrder,
favourites: favourites,
),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return FadeTransition(
opacity: CurveTween(curve: Curves.easeInOutCirc).animate(animation),
child: child,
);
},
);
},
);
}

View file

@ -1,124 +0,0 @@
import 'package:fladder/screens/login/login_screen.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:fladder/routes/app_routes.dart';
import 'package:fladder/screens/login/lock_screen.dart';
import 'package:fladder/screens/splash_screen.dart';
import 'package:fladder/util/adaptive_layout.dart';
extension RouteContextBuilder on BuildContext {
/// Push a location onto the page stack.
Future<T?> routePush<T>(CustomRoute route, {Object? extra}) async {
return push(route.route, extra: extra);
}
/// Replaces the top-most page of the page stack with the given URL location
void routeReplace(CustomRoute route, {Object? extra}) {
replace(route.route, extra: extra);
}
/// Navigate to a location.
void routeGo(CustomRoute route, {Object? extra}) {
go(route.route, extra: extra);
}
/// [Pushed] if nested(single) else [Go]
void routePushOrGo(CustomRoute route, {Object? extra}) {
switch (AdaptiveLayout.of(this).size) {
case ScreenLayout.single:
routePush(route, extra: extra);
break;
case ScreenLayout.dual:
routeGo(route, extra: extra);
break;
}
}
/// [Push] if nested(single) else [Replace]
void routeReplaceOrPush(CustomRoute route, {Object? extra}) {
switch (AdaptiveLayout.of(this).size) {
case ScreenLayout.single:
routePush(route, extra: extra);
break;
case ScreenLayout.dual:
routeReplace(route, extra: extra);
break;
}
}
}
abstract class CustomRoute {
final String name;
final String basePath;
final String? arguments;
final Map<String, dynamic>? queryParameters;
CustomRoute({required this.name, required this.basePath, this.arguments, this.queryParameters})
: assert(basePath.isNotEmpty, 'GoRoute path cannot be empty');
String get route => basePath;
String get path => "$basePath/${arguments ?? queryParameters}";
void navigate() {
AppRoutes.parentKey.currentContext?.routeGo(this);
}
void replaceRoot() {
AppRoutes.parentKey.currentContext?.routeReplace(this);
}
RouteBase get go;
}
class LoginRoute extends CustomRoute {
LoginRoute() : super(name: 'Login', basePath: '/login');
@override
GoRoute get go => GoRoute(
path: basePath,
builder: (context, state) {
return const LoginScreen();
},
);
}
class SplashRoute extends CustomRoute {
SplashRoute() : super(name: 'Splash', basePath: '/splash');
@override
GoRoute get go => GoRoute(
path: basePath,
builder: (context, state) {
return const SplashScreen();
},
);
}
class LockScreenRoute extends CustomRoute {
final bool selfLock;
LockScreenRoute({this.selfLock = false}) : super(name: 'Lock', basePath: '/lock');
@override
GoRoute get go => GoRoute(
parentNavigatorKey: AppRoutes.parentKey,
path: basePath,
builder: (context, state) {
return LockScreen(
selfLock: selfLock,
);
},
);
}
String parseUrlParameters(Map<String, dynamic>? parameters) {
if (parameters == null) return '';
String parameterString = '?';
for (String key in parameters.keys) {
if (parameters[key] != null) parameterString += '$key=${parameters[key]}&';
}
return parameterString.substring(0, parameterString.length - 1);
}

View file

@ -1,103 +0,0 @@
import 'package:fladder/routes/build_routes/route_builder.dart';
import 'package:fladder/screens/settings/client_settings_page.dart';
import 'package:fladder/screens/settings/player_settings_page.dart';
import 'package:fladder/screens/settings/settings_screen.dart';
import 'package:fladder/screens/settings/security_settings_page.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class SettingsRoute extends CustomRoute {
final String? id;
final GlobalKey<NavigatorState>? navKey;
SettingsRoute({this.id, this.navKey}) : super(name: 'Settings', basePath: '/settings');
@override
GoRoute get go => GoRoute(
path: basePath,
parentNavigatorKey: navKey,
pageBuilder: (context, state) {
return CustomTransitionPage(
key: state.pageKey,
child: const SettingsScreen(),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return FadeTransition(
opacity: CurveTween(curve: Curves.easeInOutCirc).animate(animation),
child: child,
);
},
);
},
);
}
class ClientSettingsRoute extends CustomRoute {
final String? id;
final GlobalKey<NavigatorState>? navKey;
ClientSettingsRoute({this.id, this.navKey}) : super(name: 'ClientSettings', basePath: '/settings/client');
@override
GoRoute get go => GoRoute(
path: basePath,
parentNavigatorKey: navKey,
pageBuilder: (context, state) {
return CustomTransitionPage(
key: state.pageKey,
child: const ClientSettingsPage(),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return FadeTransition(
opacity: CurveTween(curve: Curves.easeInOutCirc).animate(animation),
child: child,
);
},
);
},
);
}
class SecuritySettingsRoute extends CustomRoute {
final String? id;
final GlobalKey<NavigatorState>? navKey;
SecuritySettingsRoute({this.id, this.navKey}) : super(name: 'SecuritySettings', basePath: '/settings/security');
@override
GoRoute get go => GoRoute(
path: basePath,
parentNavigatorKey: navKey,
pageBuilder: (context, state) {
return CustomTransitionPage(
key: state.pageKey,
child: const SecuritySettingsPage(),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return FadeTransition(
opacity: CurveTween(curve: Curves.easeInOutCirc).animate(animation),
child: child,
);
},
);
},
);
}
class PlayerSettingsRoute extends CustomRoute {
final String? id;
final GlobalKey<NavigatorState>? navKey;
PlayerSettingsRoute({this.id, this.navKey}) : super(name: 'PlayerSettings', basePath: '/settings/player');
@override
GoRoute get go => GoRoute(
path: basePath,
parentNavigatorKey: navKey,
pageBuilder: (context, state) {
return CustomTransitionPage(
key: state.pageKey,
child: const PlayerSettingsPage(),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return FadeTransition(
opacity: CurveTween(curve: Curves.easeInOutCirc).animate(animation),
child: child,
);
},
);
},
);
}

View file

@ -0,0 +1,70 @@
import 'package:auto_route/auto_route.dart';
import 'package:fladder/models/item_base_model.dart';
import 'package:fladder/providers/items/item_details_provider.dart';
import 'package:fladder/routes/auto_router.gr.dart';
import 'package:fladder/util/fladder_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
@RoutePage()
class DetailsScreen extends ConsumerStatefulWidget {
final String id;
final ItemBaseModel? item;
const DetailsScreen({@QueryParam() this.id = '', this.item, super.key});
@override
ConsumerState<ConsumerStatefulWidget> createState() => _DetailsScreenState();
}
class _DetailsScreenState extends ConsumerState<DetailsScreen> {
late Widget currentWidget = const Center(
key: Key("progress-indicator"),
child: CircularProgressIndicator.adaptive(strokeCap: StrokeCap.round),
);
@override
void initState() {
super.initState();
Future.microtask(() async {
if (widget.item != null) {
setState(() {
currentWidget = widget.item!.detailScreenWidget;
});
} else {
final response = await ref.read(itemDetailsProvider.notifier).fetchDetails(widget.id);
if (context.mounted) {
if (response != null) {
setState(() {
currentWidget = response.detailScreenWidget;
});
} else {
const DashboardRoute().navigate(context);
}
}
}
});
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
Hero(
tag: widget.id,
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface.withOpacity(1.0),
),
//Small offset to match detailscaffold
child: Transform.translate(
offset: const Offset(0, -5), child: FladderImage(image: widget.item?.getPosters?.primary)),
),
),
AnimatedSwitcher(
duration: const Duration(seconds: 1),
child: currentWidget,
)
],
);
}
}