break everything

This commit is contained in:
Christien Rioux 2023-12-26 20:26:54 -05:00
parent e898074387
commit 29210c89d2
121 changed files with 2892 additions and 2608 deletions

View file

@ -0,0 +1,152 @@
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:flutter/widgets.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:go_router/go_router.dart';
import '../../init.dart';
import '../../local_account_manager/account_repository/account_repository.dart';
import '../../old_to_refactor/pages/chat_only.dart';
import '../../old_to_refactor/pages/developer.dart';
import '../../old_to_refactor/pages/home.dart';
import '../../old_to_refactor/pages/index.dart';
import '../../old_to_refactor/pages/new_account.dart';
import '../../old_to_refactor/pages/settings.dart';
import '../../tools/tools.dart';
part 'router_cubit.freezed.dart';
part 'router_cubit.g.dart';
part 'router_state.dart';
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;
emit(state.copyWith(isInitialized: true));
});
// Subscribe to repository streams
_accountRepositorySubscription =
accountRepository.changes().listen((event) {
switch (event) {
case AccountRepositoryChange.localAccounts:
emit(state.copyWith(
hasAnyAccount: accountRepository.getLocalAccounts().isNotEmpty));
break;
case AccountRepositoryChange.userLogins:
case AccountRepositoryChange.activeUserLogin:
break;
}
});
_chatListRepositorySubscription = ...
}
@override
Future<void> close() async {
await _accountRepositorySubscription.cancel();
await super.close();
}
/// Our application routes
List<GoRoute> get routes => [
GoRoute(
path: '/',
builder: (context, state) => const IndexPage(),
),
GoRoute(
path: '/home',
builder: (context, state) => const HomePage(),
routes: [
GoRoute(
path: 'settings',
builder: (context, state) => const SettingsPage(),
),
GoRoute(
path: 'chat',
builder: (context, state) => const ChatOnlyPage(),
),
],
),
GoRoute(
path: '/new_account',
builder: (context, state) => const NewAccountPage(),
routes: [
GoRoute(
path: 'settings',
builder: (context, state) => const SettingsPage(),
),
],
),
GoRoute(
path: '/developer',
builder: (context, state) => const DeveloperPage(),
)
];
/// Redirects when our state changes
String? redirect(BuildContext context, GoRouterState goRouterState) {
// if (state.isLoading || state.hasError) {
// return null;
// }
// No matter where we are, if there's not
switch (goRouterState.matchedLocation) {
case '/':
// Wait for veilid to be initialized
if (!eventualVeilid.isCompleted) {
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;
case '/home/settings':
case '/new_account/settings':
return null;
case '/developer':
return null;
default:
return state.hasAnyAccount ? null : '/new_account';
}
}
late final StreamSubscription<AccountRepositoryChange>
_accountRepositorySubscription;
}

View file

@ -0,0 +1,193 @@
// 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, unnecessary_question_mark
part of 'router_cubit.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');
RouterState _$RouterStateFromJson(Map<String, dynamic> json) {
return _RouterState.fromJson(json);
}
/// @nodoc
mixin _$RouterState {
bool get isInitialized => throw _privateConstructorUsedError;
bool get hasAnyAccount => throw _privateConstructorUsedError;
bool get hasActiveChat => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$RouterStateCopyWith<RouterState> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $RouterStateCopyWith<$Res> {
factory $RouterStateCopyWith(
RouterState value, $Res Function(RouterState) then) =
_$RouterStateCopyWithImpl<$Res, RouterState>;
@useResult
$Res call({bool isInitialized, bool hasAnyAccount, bool hasActiveChat});
}
/// @nodoc
class _$RouterStateCopyWithImpl<$Res, $Val extends RouterState>
implements $RouterStateCopyWith<$Res> {
_$RouterStateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? isInitialized = null,
Object? hasAnyAccount = null,
Object? hasActiveChat = null,
}) {
return _then(_value.copyWith(
isInitialized: null == isInitialized
? _value.isInitialized
: isInitialized // ignore: cast_nullable_to_non_nullable
as bool,
hasAnyAccount: null == hasAnyAccount
? _value.hasAnyAccount
: hasAnyAccount // ignore: cast_nullable_to_non_nullable
as bool,
hasActiveChat: null == hasActiveChat
? _value.hasActiveChat
: hasActiveChat // ignore: cast_nullable_to_non_nullable
as bool,
) as $Val);
}
}
/// @nodoc
abstract class _$$RouterStateImplCopyWith<$Res>
implements $RouterStateCopyWith<$Res> {
factory _$$RouterStateImplCopyWith(
_$RouterStateImpl value, $Res Function(_$RouterStateImpl) then) =
__$$RouterStateImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({bool isInitialized, bool hasAnyAccount, bool hasActiveChat});
}
/// @nodoc
class __$$RouterStateImplCopyWithImpl<$Res>
extends _$RouterStateCopyWithImpl<$Res, _$RouterStateImpl>
implements _$$RouterStateImplCopyWith<$Res> {
__$$RouterStateImplCopyWithImpl(
_$RouterStateImpl _value, $Res Function(_$RouterStateImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? isInitialized = null,
Object? hasAnyAccount = null,
Object? hasActiveChat = null,
}) {
return _then(_$RouterStateImpl(
isInitialized: null == isInitialized
? _value.isInitialized
: isInitialized // ignore: cast_nullable_to_non_nullable
as bool,
hasAnyAccount: null == hasAnyAccount
? _value.hasAnyAccount
: hasAnyAccount // ignore: cast_nullable_to_non_nullable
as bool,
hasActiveChat: null == hasActiveChat
? _value.hasActiveChat
: hasActiveChat // ignore: cast_nullable_to_non_nullable
as bool,
));
}
}
/// @nodoc
@JsonSerializable()
class _$RouterStateImpl implements _RouterState {
const _$RouterStateImpl(
{required this.isInitialized,
required this.hasAnyAccount,
required this.hasActiveChat});
factory _$RouterStateImpl.fromJson(Map<String, dynamic> json) =>
_$$RouterStateImplFromJson(json);
@override
final bool isInitialized;
@override
final bool hasAnyAccount;
@override
final bool hasActiveChat;
@override
String toString() {
return 'RouterState(isInitialized: $isInitialized, hasAnyAccount: $hasAnyAccount, hasActiveChat: $hasActiveChat)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$RouterStateImpl &&
(identical(other.isInitialized, isInitialized) ||
other.isInitialized == isInitialized) &&
(identical(other.hasAnyAccount, hasAnyAccount) ||
other.hasAnyAccount == hasAnyAccount) &&
(identical(other.hasActiveChat, hasActiveChat) ||
other.hasActiveChat == hasActiveChat));
}
@JsonKey(ignore: true)
@override
int get hashCode =>
Object.hash(runtimeType, isInitialized, hasAnyAccount, hasActiveChat);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$RouterStateImplCopyWith<_$RouterStateImpl> get copyWith =>
__$$RouterStateImplCopyWithImpl<_$RouterStateImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$RouterStateImplToJson(
this,
);
}
}
abstract class _RouterState implements RouterState {
const factory _RouterState(
{required final bool isInitialized,
required final bool hasAnyAccount,
required final bool hasActiveChat}) = _$RouterStateImpl;
factory _RouterState.fromJson(Map<String, dynamic> json) =
_$RouterStateImpl.fromJson;
@override
bool get isInitialized;
@override
bool get hasAnyAccount;
@override
bool get hasActiveChat;
@override
@JsonKey(ignore: true)
_$$RouterStateImplCopyWith<_$RouterStateImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View file

@ -0,0 +1,21 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'router_cubit.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$RouterStateImpl _$$RouterStateImplFromJson(Map<String, dynamic> json) =>
_$RouterStateImpl(
isInitialized: json['is_initialized'] as bool,
hasAnyAccount: json['has_any_account'] as bool,
hasActiveChat: json['has_active_chat'] as bool,
);
Map<String, dynamic> _$$RouterStateImplToJson(_$RouterStateImpl instance) =>
<String, dynamic>{
'is_initialized': instance.isInitialized,
'has_any_account': instance.hasAnyAccount,
'has_active_chat': instance.hasActiveChat,
};

View file

@ -0,0 +1,12 @@
part of 'router_cubit.dart';
@freezed
class RouterState with _$RouterState {
const factory RouterState(
{required bool isInitialized,
required bool hasAnyAccount,
required bool hasActiveChat}) = _RouterState;
factory RouterState.fromJson(dynamic json) =>
_$RouterStateFromJson(json as Map<String, dynamic>);
}

View file

@ -0,0 +1,20 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:stream_transform/stream_transform.dart';
import '../tools/stream_listenable.dart';
import 'cubit/router_cubit.dart';
final _key = GlobalKey<NavigatorState>(debugLabel: 'routerKey');
/// This simple provider caches our GoRouter.
GoRouter router({required RouterCubit routerCubit}) => GoRouter(
navigatorKey: _key,
refreshListenable: StreamListenable(
routerCubit.stream.startWith(routerCubit.state).distinct()),
debugLogDiagnostics: kDebugMode,
initialLocation: '/',
routes: routerCubit.routes,
redirect: routerCubit.redirect,
);

View file

@ -1,23 +1,2 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'router_notifier.dart';
part 'router.g.dart';
final _key = GlobalKey<NavigatorState>(debugLabel: 'routerKey');
/// This simple provider caches our GoRouter.
@riverpod
GoRouter router(RouterRef ref) {
final notifier = ref.watch(routerNotifierProvider.notifier);
return GoRouter(
navigatorKey: _key,
refreshListenable: notifier,
debugLogDiagnostics: true,
initialLocation: '/',
routes: notifier.routes,
redirect: notifier.redirect,
);
}
export 'cubit/router_cubit.dart';
export 'make_router.dart';

View file

@ -1,26 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'router.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
String _$routerHash() => r'86eecb1955be62ef8e6f6efcec0fa615289cb823';
/// This simple provider caches our GoRouter.
///
/// Copied from [router].
@ProviderFor(router)
final routerProvider = AutoDisposeProvider<GoRouter>.internal(
router,
name: r'routerProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product') ? null : _$routerHash,
dependencies: null,
allTransitiveDependencies: null,
);
typedef RouterRef = AutoDisposeProviderRef<GoRouter>;
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View file

@ -1,160 +0,0 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../pages/chat_only.dart';
import '../pages/developer.dart';
import '../pages/home.dart';
import '../pages/index.dart';
import '../pages/new_account.dart';
import '../pages/settings.dart';
import '../providers/chat.dart';
import '../providers/local_accounts.dart';
import '../tools/responsive.dart';
import '../veilid_init.dart';
part 'router_notifier.g.dart';
@riverpod
class RouterNotifier extends _$RouterNotifier implements Listenable {
/// GoRouter listener
VoidCallback? routerListener;
/// Do we need to make or import an account immediately?
bool hasAnyAccount = false;
bool hasActiveChat = false;
/// AsyncNotifier build
@override
Future<void> build() async {
hasAnyAccount = await ref.watch(
localAccountsProvider.selectAsync((data) => data.isNotEmpty),
);
hasActiveChat = ref.watch(activeChatStateProvider) != null;
// When this notifier's state changes, inform GoRouter
ref.listenSelf((_, __) {
if (state.isLoading) {
return;
}
routerListener?.call();
});
}
/// Redirects when our state changes
String? redirect(BuildContext context, GoRouterState state) {
if (this.state.isLoading || this.state.hasError) {
return null;
}
// No matter where we are, if there's not
switch (state.matchedLocation) {
case '/':
// Wait for veilid to be initialized
if (!eventualVeilid.isCompleted) {
return null;
}
return hasAnyAccount ? '/home' : '/new_account';
case '/new_account':
return hasAnyAccount ? '/home' : null;
case '/home':
if (!hasAnyAccount) {
return '/new_account';
}
if (responsiveVisibility(
context: context,
tablet: false,
tabletLandscape: false,
desktop: false)) {
if (hasActiveChat) {
return '/home/chat';
}
}
return null;
case '/home/chat':
if (!hasAnyAccount) {
return '/new_account';
}
if (responsiveVisibility(
context: context,
tablet: false,
tabletLandscape: false,
desktop: false)) {
if (!hasActiveChat) {
return '/home';
}
} else {
return '/home';
}
return null;
case '/home/settings':
case '/new_account/settings':
return null;
case '/developer':
return null;
default:
return hasAnyAccount ? null : '/new_account';
}
}
/// Our application routes
List<GoRoute> get routes => [
GoRoute(
path: '/',
builder: (context, state) => const IndexPage(),
),
GoRoute(
path: '/home',
builder: (context, state) => const HomePage(),
routes: [
GoRoute(
path: 'settings',
builder: (context, state) => const SettingsPage(),
),
GoRoute(
path: 'chat',
builder: (context, state) => const ChatOnlyPage(),
),
],
),
GoRoute(
path: '/new_account',
builder: (context, state) => const NewAccountPage(),
routes: [
GoRoute(
path: 'settings',
builder: (context, state) => const SettingsPage(),
),
],
),
GoRoute(
path: '/developer',
builder: (context, state) => const DeveloperPage(),
)
];
///////////////////////////////////////////////////////////////////////////
/// Listenable
/// 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;
}
}

View file

@ -1,26 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'router_notifier.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
String _$routerNotifierHash() => r'6f52ed95f090f2d198d358e7526a91511c0a61e5';
/// See also [RouterNotifier].
@ProviderFor(RouterNotifier)
final routerNotifierProvider =
AutoDisposeAsyncNotifierProvider<RouterNotifier, void>.internal(
RouterNotifier.new,
name: r'routerNotifierProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
? null
: _$routerNotifierHash,
dependencies: null,
allTransitiveDependencies: null,
);
typedef _$RouterNotifier = AutoDisposeAsyncNotifier<void>;
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member