mirror of
https://github.com/lucavenir/go_router_riverpod.git
synced 2025-05-17 20:25:54 +08:00
Changed the main example with code gen tools
This commit is contained in:
@ -1,29 +1,8 @@
|
||||
# This file configures the analyzer, which statically analyzes Dart code to
|
||||
# check for errors, warnings, and lints.
|
||||
#
|
||||
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
||||
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
||||
# invoked from the command line by running `flutter analyze`.
|
||||
|
||||
# The following line activates a set of recommended lints for Flutter apps,
|
||||
# packages, and plugins designed to encourage good coding practices.
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
linter:
|
||||
# The lint rules applied to this project can be customized in the
|
||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||
# included above or to enable additional rules. A list of all available lints
|
||||
# and their documentation is published at
|
||||
# https://dart-lang.github.io/linter/lints/index.html.
|
||||
#
|
||||
# Instead of disabling a lint rule for the entire project in the
|
||||
# section below, it can also be suppressed for a single line of code
|
||||
# or a specific dart file by using the `// ignore: name_of_lint` and
|
||||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||
# producing the lint.
|
||||
rules:
|
||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||
analyzer:
|
||||
errors:
|
||||
invalid_annotation_target: ignore
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
linter:
|
||||
rules:
|
||||
|
@ -1,108 +1,111 @@
|
||||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class User {
|
||||
const User({
|
||||
required this.displayName,
|
||||
required this.email,
|
||||
required this.token,
|
||||
});
|
||||
import 'user.dart';
|
||||
|
||||
final String displayName;
|
||||
final String email;
|
||||
final String token;
|
||||
}
|
||||
part 'auth.g.dart';
|
||||
|
||||
// TODO in the next version: Use Freezed to generate states.
|
||||
typedef AsyncUser = AsyncValue<User?>;
|
||||
|
||||
final authProvider = AsyncNotifierProvider<AuthNotifier, User?>(() {
|
||||
return AuthNotifier();
|
||||
});
|
||||
|
||||
class AuthNotifier extends AsyncNotifier<User?> {
|
||||
AuthNotifier();
|
||||
static const _key = 'token';
|
||||
|
||||
@override
|
||||
FutureOr<User?> build() async {
|
||||
final sharedPreferences = await SharedPreferences.getInstance();
|
||||
|
||||
ref.listenSelf((_, next) {
|
||||
final val = next.valueOrNull;
|
||||
if (val == null) {
|
||||
sharedPreferences.remove(_key);
|
||||
return;
|
||||
}
|
||||
sharedPreferences.setString(_key, val.email);
|
||||
});
|
||||
|
||||
try {
|
||||
// This operation might fail for... reasons
|
||||
final savedToken = sharedPreferences.getString(_key);
|
||||
if (savedToken == null) return null;
|
||||
|
||||
// This request might also fail
|
||||
return await _loginWithToken(savedToken);
|
||||
} catch (error, stackTrace) {
|
||||
// If anything goes wrong, give a non-authenticated outcome
|
||||
await sharedPreferences.remove(_key);
|
||||
print(error);
|
||||
print(stackTrace);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<User?> _loginWithToken(String token) async {
|
||||
// here the token should be used to perform a login request
|
||||
final logInAttempt = await Future.delayed(
|
||||
const Duration(milliseconds: 750),
|
||||
() => Random().nextBool(), // mock
|
||||
);
|
||||
|
||||
// If the attempts succeeds, return the result out
|
||||
if (logInAttempt) {
|
||||
return const User(
|
||||
/// A mock of an Authenticated User
|
||||
const _dummyUser = User.signedIn(
|
||||
id: 0,
|
||||
displayName: "My Name",
|
||||
email: "My Email",
|
||||
token: "some-updated-secret-auth-token",
|
||||
);
|
||||
|
||||
@riverpod
|
||||
class AuthNotifier extends _$AuthNotifier {
|
||||
late SharedPreferences sharedPreferences;
|
||||
static const _sharedPrefsKey = 'token';
|
||||
|
||||
/// Mock of the duration of a network request
|
||||
final _networkRoundTripTime = Random().nextInt(750);
|
||||
|
||||
@override
|
||||
FutureOr<User> build() async {
|
||||
sharedPreferences = await SharedPreferences.getInstance();
|
||||
|
||||
_persistenceRefreshLogic();
|
||||
|
||||
return await _loginRecoveryAttempt();
|
||||
}
|
||||
|
||||
// If the attempt fails, or returns 401, or whatever, this should fail.
|
||||
throw const UnauthorizedException('401 Unauthorized or something');
|
||||
/// Tries to perform a login with the saved token on the persistant storage.
|
||||
/// If _anything_ goes wrong, deletes the internal token and returns a [User.signedOut].
|
||||
Future<User> _loginRecoveryAttempt() async {
|
||||
try {
|
||||
final savedToken = sharedPreferences.getString(_sharedPrefsKey);
|
||||
if (savedToken == null) {
|
||||
throw const UnauthorizedException(
|
||||
"Couldn't find the authentication token");
|
||||
}
|
||||
|
||||
return await _loginWithToken(savedToken);
|
||||
} catch (_, __) {
|
||||
await sharedPreferences.remove(_sharedPrefsKey);
|
||||
return const User.signedOut();
|
||||
}
|
||||
}
|
||||
|
||||
/// Mock of a request performed on logout (might be common, or not, whatevs).
|
||||
Future<void> logout() async {
|
||||
final sharedPreferences = await SharedPreferences.getInstance();
|
||||
|
||||
// Remove the token from persistence, first
|
||||
await sharedPreferences.remove(_key);
|
||||
// No request is mocked here but I guess we could: logout
|
||||
state = const AsyncUser.data(null);
|
||||
await Future.delayed(Duration(milliseconds: _networkRoundTripTime));
|
||||
state = const AsyncValue<User>.data(User.signedOut());
|
||||
}
|
||||
|
||||
/// Mock of a successful login attempt, which results come from the network.
|
||||
Future<void> login(String email, String password) async {
|
||||
// Simple mock of a successful login attempt
|
||||
state = await AsyncUser.guard(() async {
|
||||
state = await AsyncValue.guard<User>(() async {
|
||||
return Future.delayed(
|
||||
Duration(milliseconds: Random().nextInt(750)),
|
||||
() => const User(
|
||||
displayName: "My Name",
|
||||
email: "My Email",
|
||||
token: 'someToken',
|
||||
),
|
||||
Duration(milliseconds: _networkRoundTripTime),
|
||||
() => _dummyUser,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
bool get isAuthenticated => state.valueOrNull != null;
|
||||
bool get isLoading => state.isLoading;
|
||||
/// Mock of a login request performed with a saved token.
|
||||
/// If such request fails, this method will throw an [UnauthorizedException].
|
||||
Future<User> _loginWithToken(String token) async {
|
||||
final logInAttempt = await Future.delayed(
|
||||
Duration(milliseconds: _networkRoundTripTime),
|
||||
() => true,
|
||||
);
|
||||
|
||||
if (logInAttempt) return _dummyUser;
|
||||
|
||||
throw const UnauthorizedException('401 Unauthorized or something');
|
||||
}
|
||||
|
||||
/// Internal method used to listen authentication state changes.
|
||||
/// When the auth object is in a loading state, nothing happens.
|
||||
/// When the auth object is in a error state, we choose to remove the token
|
||||
/// Otherwise, we expect the current auth value to be reflected in our persitence API
|
||||
void _persistenceRefreshLogic() {
|
||||
ref.listenSelf((_, next) {
|
||||
if (next.isLoading) return;
|
||||
if (next.hasError) {
|
||||
sharedPreferences.remove(_sharedPrefsKey);
|
||||
return;
|
||||
}
|
||||
|
||||
final val = next.requireValue;
|
||||
|
||||
val.map<void>(
|
||||
signedIn: (signedIn) {
|
||||
sharedPreferences.setString(_sharedPrefsKey, signedIn.token);
|
||||
},
|
||||
signedOut: (signedOut) {
|
||||
sharedPreferences.remove(_sharedPrefsKey);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Simple mock of a 401 exception
|
||||
class UnauthorizedException implements Exception {
|
||||
final String message;
|
||||
const UnauthorizedException(this.message);
|
||||
|
47
complete_example/lib/auth.g.dart
Normal file
47
complete_example/lib/auth.g.dart
Normal file
@ -0,0 +1,47 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'auth.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// ignore_for_file: avoid_private_typedef_functions, non_constant_identifier_names, subtype_of_sealed_class, invalid_use_of_internal_member, unused_element, constant_identifier_names, unnecessary_raw_strings, library_private_types_in_public_api
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
_SystemHash._();
|
||||
|
||||
static int combine(int hash, int value) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + value);
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
||||
return hash ^ (hash >> 6);
|
||||
}
|
||||
|
||||
static int finish(int hash) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
||||
// ignore: parameter_assignments
|
||||
hash = hash ^ (hash >> 11);
|
||||
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||
}
|
||||
}
|
||||
|
||||
String $AuthNotifierHash() => r'587998753a879e6c3f8912f3913c0e2ea5eb1b14';
|
||||
|
||||
/// See also [AuthNotifier].
|
||||
final authNotifierProvider =
|
||||
AutoDisposeAsyncNotifierProvider<AuthNotifier, User>(
|
||||
AuthNotifier.new,
|
||||
name: r'authNotifierProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product') ? null : $AuthNotifierHash,
|
||||
);
|
||||
typedef AuthNotifierRef = AutoDisposeAsyncNotifierProviderRef<User>;
|
||||
|
||||
abstract class _$AuthNotifier extends AutoDisposeAsyncNotifier<User> {
|
||||
@override
|
||||
FutureOr<User> build();
|
||||
}
|
@ -16,35 +16,20 @@ class MyAwesomeApp extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final asyncRouter = ref.watch(routerProvider);
|
||||
final router = ref.watch(routerProvider);
|
||||
|
||||
if (asyncRouter.hasValue) {
|
||||
final router = asyncRouter.requireValue;
|
||||
return MaterialApp.router(
|
||||
routeInformationParser: router.routeInformationParser,
|
||||
routerDelegate: router.routerDelegate,
|
||||
routeInformationProvider: router.routeInformationProvider,
|
||||
routerConfig: router,
|
||||
title: 'flutter_riverpod + go_router Demo',
|
||||
theme: ThemeData(
|
||||
primarySwatch: Colors.blue,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return asyncRouter.maybeWhen(
|
||||
error: (error, stackTrace) {
|
||||
print(error);
|
||||
return const Text("Something went very, very wrong.");
|
||||
},
|
||||
orElse: () => const CircularProgressIndicator(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class HomePage extends ConsumerWidget {
|
||||
const HomePage({super.key});
|
||||
static String get routeName => 'home';
|
||||
static String get routeLocation => '/';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
@ -58,7 +43,7 @@ class HomePage extends ConsumerWidget {
|
||||
const Text("Home Page"),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
ref.read(authProvider.notifier).logout();
|
||||
ref.read(authNotifierProvider.notifier).logout();
|
||||
},
|
||||
child: const Text("Logout"),
|
||||
),
|
||||
@ -71,8 +56,6 @@ class HomePage extends ConsumerWidget {
|
||||
|
||||
class LoginPage extends ConsumerWidget {
|
||||
const LoginPage({super.key});
|
||||
static String get routeName => 'login';
|
||||
static String get routeLocation => '/$routeName';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
@ -86,7 +69,7 @@ class LoginPage extends ConsumerWidget {
|
||||
const Text("Login Page"),
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
ref.read(authProvider.notifier).login(
|
||||
ref.read(authNotifierProvider.notifier).login(
|
||||
"myEmail",
|
||||
"myPassword",
|
||||
);
|
||||
@ -102,8 +85,6 @@ class LoginPage extends ConsumerWidget {
|
||||
|
||||
class SplashPage extends StatelessWidget {
|
||||
const SplashPage({super.key});
|
||||
static String get routeName => 'splash';
|
||||
static String get routeLocation => '/$routeName';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -9,11 +9,12 @@ class RiverpodLogger extends ProviderObserver {
|
||||
Object? newValue,
|
||||
ProviderContainer container,
|
||||
) {
|
||||
// TODO use a proper logger
|
||||
print('''
|
||||
{
|
||||
provider: ${provider.name ?? provider.runtimeType},
|
||||
oldValue: ${previousValue ?? 'None'},
|
||||
newValue: ${newValue ?? 'None'}
|
||||
oldValue: $previousValue,
|
||||
newValue: $newValue
|
||||
}
|
||||
''');
|
||||
super.didUpdateProvider(provider, previousValue, newValue, container);
|
||||
|
@ -1,57 +1,25 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
import 'auth.dart';
|
||||
import 'main.dart';
|
||||
import 'router_notifier.dart';
|
||||
import 'routes.dart';
|
||||
|
||||
final _key = GlobalKey<NavigatorState>();
|
||||
part 'router.g.dart';
|
||||
|
||||
final routerProvider = FutureProvider<GoRouter>((ref) async {
|
||||
final isAuth = await ref.watch(
|
||||
authProvider.selectAsync((value) => value != null),
|
||||
);
|
||||
final _key = GlobalKey<NavigatorState>(debugLabel: 'routerKey');
|
||||
|
||||
@riverpod
|
||||
GoRouter router(RouterRef ref) {
|
||||
ref.watch(routerNotifierProvider);
|
||||
final notifier = ref.read(routerNotifierProvider.notifier);
|
||||
|
||||
return GoRouter(
|
||||
navigatorKey: _key,
|
||||
refreshListenable: notifier,
|
||||
debugLogDiagnostics: true,
|
||||
initialLocation: SplashPage.routeLocation,
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: SplashPage.routeLocation,
|
||||
name: SplashPage.routeName,
|
||||
builder: (context, state) {
|
||||
return const SplashPage();
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: HomePage.routeLocation,
|
||||
name: HomePage.routeName,
|
||||
builder: (context, state) {
|
||||
return const HomePage();
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: LoginPage.routeLocation,
|
||||
name: LoginPage.routeName,
|
||||
builder: (context, state) {
|
||||
return const LoginPage();
|
||||
},
|
||||
),
|
||||
],
|
||||
redirect: (context, state) {
|
||||
// If our async state is loading, don't perform redirects, yet
|
||||
if (isAuth == null) return null;
|
||||
|
||||
final isSplash = state.location == SplashPage.routeLocation;
|
||||
if (isSplash) {
|
||||
return isAuth ? HomePage.routeLocation : LoginPage.routeLocation;
|
||||
}
|
||||
|
||||
final isLoggingIn = state.location == LoginPage.routeLocation;
|
||||
if (isLoggingIn) return isAuth ? HomePage.routeLocation : null;
|
||||
|
||||
return isAuth ? null : SplashPage.routeLocation;
|
||||
},
|
||||
initialLocation: SplashRoute.path,
|
||||
routes: notifier.routes,
|
||||
redirect: notifier.redirect,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
41
complete_example/lib/router.g.dart
Normal file
41
complete_example/lib/router.g.dart
Normal file
@ -0,0 +1,41 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'router.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// ignore_for_file: avoid_private_typedef_functions, non_constant_identifier_names, subtype_of_sealed_class, invalid_use_of_internal_member, unused_element, constant_identifier_names, unnecessary_raw_strings, library_private_types_in_public_api
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
_SystemHash._();
|
||||
|
||||
static int combine(int hash, int value) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + value);
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
||||
return hash ^ (hash >> 6);
|
||||
}
|
||||
|
||||
static int finish(int hash) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
||||
// ignore: parameter_assignments
|
||||
hash = hash ^ (hash >> 11);
|
||||
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||
}
|
||||
}
|
||||
|
||||
String $routerHash() => r'f928f86033f77a05a3a9258abeb50e25d044c1a5';
|
||||
|
||||
/// See also [router].
|
||||
final routerProvider = AutoDisposeProvider<GoRouter>(
|
||||
router,
|
||||
name: r'routerProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product') ? null : $routerHash,
|
||||
);
|
||||
typedef RouterRef = AutoDisposeProviderRef<GoRouter>;
|
68
complete_example/lib/router_notifier.dart
Normal file
68
complete_example/lib/router_notifier.dart
Normal file
@ -0,0 +1,68 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
import 'auth.dart';
|
||||
import 'routes.dart';
|
||||
|
||||
part 'router_notifier.g.dart';
|
||||
|
||||
@riverpod
|
||||
class RouterNotifier extends _$RouterNotifier implements Listenable {
|
||||
VoidCallback? routerListener;
|
||||
bool? isAuth;
|
||||
|
||||
@override
|
||||
void build() {
|
||||
ref.listen(
|
||||
authNotifierProvider.select((value) => value),
|
||||
(previous, next) {
|
||||
if (next.isLoading) return;
|
||||
|
||||
isAuth = next.requireValue.map(
|
||||
signedIn: (_) => true,
|
||||
signedOut: (_) => false,
|
||||
);
|
||||
|
||||
routerListener?.call();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
String? redirect(BuildContext context, GoRouterState state) {
|
||||
if (isAuth == null) return null;
|
||||
final isSplash = state.location == SplashRoute.path;
|
||||
|
||||
if (isSplash) {
|
||||
return isAuth! ? HomeRoute.path : LoginRoute.path;
|
||||
}
|
||||
|
||||
final isLoggingIn = state.location == LoginRoute.path;
|
||||
if (isLoggingIn) return isAuth! ? HomeRoute.path : null;
|
||||
|
||||
return isAuth! ? null : SplashRoute.path;
|
||||
}
|
||||
|
||||
/// Our application routes. Obtained through code generation
|
||||
List<GoRoute> get routes => $appRoutes;
|
||||
|
||||
/// 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;
|
||||
}
|
||||
}
|
48
complete_example/lib/router_notifier.g.dart
Normal file
48
complete_example/lib/router_notifier.g.dart
Normal file
@ -0,0 +1,48 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'router_notifier.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// ignore_for_file: avoid_private_typedef_functions, non_constant_identifier_names, subtype_of_sealed_class, invalid_use_of_internal_member, unused_element, constant_identifier_names, unnecessary_raw_strings, library_private_types_in_public_api
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
_SystemHash._();
|
||||
|
||||
static int combine(int hash, int value) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + value);
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
||||
return hash ^ (hash >> 6);
|
||||
}
|
||||
|
||||
static int finish(int hash) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
||||
// ignore: parameter_assignments
|
||||
hash = hash ^ (hash >> 11);
|
||||
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||
}
|
||||
}
|
||||
|
||||
String $RouterNotifierHash() => r'97f2e52207151ab82f78803b85c3016d6c7a90e9';
|
||||
|
||||
/// See also [RouterNotifier].
|
||||
final routerNotifierProvider =
|
||||
AutoDisposeNotifierProvider<RouterNotifier, void>(
|
||||
RouterNotifier.new,
|
||||
name: r'routerNotifierProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: $RouterNotifierHash,
|
||||
);
|
||||
typedef RouterNotifierRef = AutoDisposeNotifierProviderRef<void>;
|
||||
|
||||
abstract class _$RouterNotifier extends AutoDisposeNotifier<void> {
|
||||
@override
|
||||
void build();
|
||||
}
|
39
complete_example/lib/routes.dart
Normal file
39
complete_example/lib/routes.dart
Normal file
@ -0,0 +1,39 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import 'main.dart';
|
||||
|
||||
part 'routes.g.dart';
|
||||
|
||||
@TypedGoRoute<SplashRoute>(path: SplashRoute.path)
|
||||
class SplashRoute extends GoRouteData {
|
||||
const SplashRoute();
|
||||
static const path = '/splash';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const SplashPage();
|
||||
}
|
||||
}
|
||||
|
||||
@TypedGoRoute<HomeRoute>(path: HomeRoute.path)
|
||||
class HomeRoute extends GoRouteData {
|
||||
const HomeRoute();
|
||||
static const path = '/home';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const HomePage();
|
||||
}
|
||||
}
|
||||
|
||||
@TypedGoRoute<LoginRoute>(path: LoginRoute.path)
|
||||
class LoginRoute extends GoRouteData {
|
||||
const LoginRoute();
|
||||
static const path = '/login';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const LoginPage();
|
||||
}
|
||||
}
|
64
complete_example/lib/routes.g.dart
Normal file
64
complete_example/lib/routes.g.dart
Normal file
@ -0,0 +1,64 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'routes.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// GoRouterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
List<GoRoute> get $appRoutes => [
|
||||
$splashRoute,
|
||||
$homeRoute,
|
||||
$loginRoute,
|
||||
];
|
||||
|
||||
GoRoute get $splashRoute => GoRouteData.$route(
|
||||
path: '/splash',
|
||||
factory: $SplashRouteExtension._fromState,
|
||||
);
|
||||
|
||||
extension $SplashRouteExtension on SplashRoute {
|
||||
static SplashRoute _fromState(GoRouterState state) => const SplashRoute();
|
||||
|
||||
String get location => GoRouteData.$location(
|
||||
'/splash',
|
||||
);
|
||||
|
||||
void go(BuildContext context) => context.go(location, extra: this);
|
||||
|
||||
void push(BuildContext context) => context.push(location, extra: this);
|
||||
}
|
||||
|
||||
GoRoute get $homeRoute => GoRouteData.$route(
|
||||
path: '/home',
|
||||
factory: $HomeRouteExtension._fromState,
|
||||
);
|
||||
|
||||
extension $HomeRouteExtension on HomeRoute {
|
||||
static HomeRoute _fromState(GoRouterState state) => const HomeRoute();
|
||||
|
||||
String get location => GoRouteData.$location(
|
||||
'/home',
|
||||
);
|
||||
|
||||
void go(BuildContext context) => context.go(location, extra: this);
|
||||
|
||||
void push(BuildContext context) => context.push(location, extra: this);
|
||||
}
|
||||
|
||||
GoRoute get $loginRoute => GoRouteData.$route(
|
||||
path: '/login',
|
||||
factory: $LoginRouteExtension._fromState,
|
||||
);
|
||||
|
||||
extension $LoginRouteExtension on LoginRoute {
|
||||
static LoginRoute _fromState(GoRouterState state) => const LoginRoute();
|
||||
|
||||
String get location => GoRouteData.$location(
|
||||
'/login',
|
||||
);
|
||||
|
||||
void go(BuildContext context) => context.go(location, extra: this);
|
||||
|
||||
void push(BuildContext context) => context.push(location, extra: this);
|
||||
}
|
15
complete_example/lib/user.dart
Normal file
15
complete_example/lib/user.dart
Normal file
@ -0,0 +1,15 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'user.freezed.dart';
|
||||
|
||||
@freezed
|
||||
class User with _$User {
|
||||
const factory User.signedIn({
|
||||
required int id,
|
||||
required String displayName,
|
||||
required String email,
|
||||
required String token,
|
||||
}) = SignedIn;
|
||||
|
||||
const factory User.signedOut() = SignedOut;
|
||||
}
|
356
complete_example/lib/user.freezed.dart
Normal file
356
complete_example/lib/user.freezed.dart
Normal file
@ -0,0 +1,356 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
|
||||
|
||||
part of 'user.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
||||
|
||||
/// @nodoc
|
||||
mixin _$User {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(
|
||||
int id, String displayName, String email, String token)
|
||||
signedIn,
|
||||
required TResult Function() signedOut,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function(int id, String displayName, String email, String token)?
|
||||
signedIn,
|
||||
TResult? Function()? signedOut,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(int id, String displayName, String email, String token)?
|
||||
signedIn,
|
||||
TResult Function()? signedOut,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(SignedIn value) signedIn,
|
||||
required TResult Function(SignedOut value) signedOut,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>({
|
||||
TResult? Function(SignedIn value)? signedIn,
|
||||
TResult? Function(SignedOut value)? signedOut,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(SignedIn value)? signedIn,
|
||||
TResult Function(SignedOut value)? signedOut,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $UserCopyWith<$Res> {
|
||||
factory $UserCopyWith(User value, $Res Function(User) then) =
|
||||
_$UserCopyWithImpl<$Res, User>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$UserCopyWithImpl<$Res, $Val extends User>
|
||||
implements $UserCopyWith<$Res> {
|
||||
_$UserCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$SignedInCopyWith<$Res> {
|
||||
factory _$$SignedInCopyWith(
|
||||
_$SignedIn value, $Res Function(_$SignedIn) then) =
|
||||
__$$SignedInCopyWithImpl<$Res>;
|
||||
@useResult
|
||||
$Res call({int id, String displayName, String email, String token});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$SignedInCopyWithImpl<$Res>
|
||||
extends _$UserCopyWithImpl<$Res, _$SignedIn>
|
||||
implements _$$SignedInCopyWith<$Res> {
|
||||
__$$SignedInCopyWithImpl(_$SignedIn _value, $Res Function(_$SignedIn) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? id = null,
|
||||
Object? displayName = null,
|
||||
Object? email = null,
|
||||
Object? token = null,
|
||||
}) {
|
||||
return _then(_$SignedIn(
|
||||
id: null == id
|
||||
? _value.id
|
||||
: id // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
displayName: null == displayName
|
||||
? _value.displayName
|
||||
: displayName // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
email: null == email
|
||||
? _value.email
|
||||
: email // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
token: null == token
|
||||
? _value.token
|
||||
: token // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$SignedIn implements SignedIn {
|
||||
const _$SignedIn(
|
||||
{required this.id,
|
||||
required this.displayName,
|
||||
required this.email,
|
||||
required this.token});
|
||||
|
||||
@override
|
||||
final int id;
|
||||
@override
|
||||
final String displayName;
|
||||
@override
|
||||
final String email;
|
||||
@override
|
||||
final String token;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'User.signedIn(id: $id, displayName: $displayName, email: $email, token: $token)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$SignedIn &&
|
||||
(identical(other.id, id) || other.id == id) &&
|
||||
(identical(other.displayName, displayName) ||
|
||||
other.displayName == displayName) &&
|
||||
(identical(other.email, email) || other.email == email) &&
|
||||
(identical(other.token, token) || other.token == token));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, id, displayName, email, token);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$SignedInCopyWith<_$SignedIn> get copyWith =>
|
||||
__$$SignedInCopyWithImpl<_$SignedIn>(this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(
|
||||
int id, String displayName, String email, String token)
|
||||
signedIn,
|
||||
required TResult Function() signedOut,
|
||||
}) {
|
||||
return signedIn(id, displayName, email, token);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function(int id, String displayName, String email, String token)?
|
||||
signedIn,
|
||||
TResult? Function()? signedOut,
|
||||
}) {
|
||||
return signedIn?.call(id, displayName, email, token);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(int id, String displayName, String email, String token)?
|
||||
signedIn,
|
||||
TResult Function()? signedOut,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (signedIn != null) {
|
||||
return signedIn(id, displayName, email, token);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(SignedIn value) signedIn,
|
||||
required TResult Function(SignedOut value) signedOut,
|
||||
}) {
|
||||
return signedIn(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>({
|
||||
TResult? Function(SignedIn value)? signedIn,
|
||||
TResult? Function(SignedOut value)? signedOut,
|
||||
}) {
|
||||
return signedIn?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(SignedIn value)? signedIn,
|
||||
TResult Function(SignedOut value)? signedOut,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (signedIn != null) {
|
||||
return signedIn(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class SignedIn implements User {
|
||||
const factory SignedIn(
|
||||
{required final int id,
|
||||
required final String displayName,
|
||||
required final String email,
|
||||
required final String token}) = _$SignedIn;
|
||||
|
||||
int get id;
|
||||
String get displayName;
|
||||
String get email;
|
||||
String get token;
|
||||
@JsonKey(ignore: true)
|
||||
_$$SignedInCopyWith<_$SignedIn> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$SignedOutCopyWith<$Res> {
|
||||
factory _$$SignedOutCopyWith(
|
||||
_$SignedOut value, $Res Function(_$SignedOut) then) =
|
||||
__$$SignedOutCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$SignedOutCopyWithImpl<$Res>
|
||||
extends _$UserCopyWithImpl<$Res, _$SignedOut>
|
||||
implements _$$SignedOutCopyWith<$Res> {
|
||||
__$$SignedOutCopyWithImpl(
|
||||
_$SignedOut _value, $Res Function(_$SignedOut) _then)
|
||||
: super(_value, _then);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$SignedOut implements SignedOut {
|
||||
const _$SignedOut();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'User.signedOut()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType && other is _$SignedOut);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(
|
||||
int id, String displayName, String email, String token)
|
||||
signedIn,
|
||||
required TResult Function() signedOut,
|
||||
}) {
|
||||
return signedOut();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function(int id, String displayName, String email, String token)?
|
||||
signedIn,
|
||||
TResult? Function()? signedOut,
|
||||
}) {
|
||||
return signedOut?.call();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(int id, String displayName, String email, String token)?
|
||||
signedIn,
|
||||
TResult Function()? signedOut,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (signedOut != null) {
|
||||
return signedOut();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(SignedIn value) signedIn,
|
||||
required TResult Function(SignedOut value) signedOut,
|
||||
}) {
|
||||
return signedOut(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>({
|
||||
TResult? Function(SignedIn value)? signedIn,
|
||||
TResult? Function(SignedOut value)? signedOut,
|
||||
}) {
|
||||
return signedOut?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(SignedIn value)? signedIn,
|
||||
TResult Function(SignedOut value)? signedOut,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (signedOut != null) {
|
||||
return signedOut(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class SignedOut implements User {
|
||||
const factory SignedOut() = _$SignedOut;
|
||||
}
|
@ -1,6 +1,27 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
_fe_analyzer_shared:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _fe_analyzer_shared
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "50.0.0"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.2.0"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -15,6 +36,62 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
build:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
build_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_config
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
build_daemon:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_daemon
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
build_resolvers:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_resolvers
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
build_runner:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: build_runner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
build_runner_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_runner_core
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "7.2.7"
|
||||
built_collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_collection
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
built_value:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_value
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "8.4.2"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -22,6 +99,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
checked_yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: checked_yaml
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -29,6 +113,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
code_builder:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: code_builder
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.3.0"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -36,6 +127,27 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.16.0"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: convert
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
dart_style:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dart_style
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.4"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -57,6 +169,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fixnum
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@ -86,13 +205,76 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
freezed:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: freezed
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
freezed_annotation:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: freezed_annotation
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: frontend_server_client
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
go_router:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: go_router
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.0.5"
|
||||
version: "5.1.9"
|
||||
go_router_builder:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: go_router_builder
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.15"
|
||||
graphs:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: graphs
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_multi_server
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.0.2"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: io
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -100,6 +282,20 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.4"
|
||||
json_annotation:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: json_annotation
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.7.0"
|
||||
json_serializable:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: json_serializable
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.5.4"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -135,6 +331,20 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mime
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_config
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -163,6 +373,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
path_to_regexp:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_to_regexp
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -177,6 +394,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
pool:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pool
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.5.1"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -184,6 +408,20 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.2.4"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pub_semver
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
pubspec_parse:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pubspec_parse
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
riverpod:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -191,6 +429,20 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
riverpod_annotation:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: riverpod_annotation
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.6"
|
||||
riverpod_generator:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: riverpod_generator
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.6"
|
||||
shared_preferences:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -247,11 +499,39 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
shelf_web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_web_socket
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
source_gen:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_gen
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.6"
|
||||
source_helper:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_helper
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.3"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -280,6 +560,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
stream_transform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_transform
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -301,6 +588,20 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.12"
|
||||
timing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: timing
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -308,6 +609,20 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: watcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -322,6 +637,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.0+2"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
sdks:
|
||||
dart: ">=2.18.0 <3.0.0"
|
||||
flutter: ">=3.3.0"
|
||||
|
@ -11,14 +11,22 @@ environment:
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
go_router: ^5.0.5
|
||||
go_router: ^5.1.9
|
||||
flutter_riverpod: ^2.1.1
|
||||
riverpod_annotation: ^1.0.6
|
||||
shared_preferences: ^2.0.15
|
||||
freezed_annotation: ^2.2.0
|
||||
json_annotation: ^4.7.0
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.3.2
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^2.0.1
|
||||
go_router_builder: ^1.0.15
|
||||
riverpod_generator: ^1.0.6
|
||||
freezed: ^2.2.1
|
||||
json_serializable: ^6.5.4
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
Reference in New Issue
Block a user