diff --git a/app/lib/core/routing/routes.dart b/app/lib/core/routing/routes.dart index 45049c06..d6f70063 100644 --- a/app/lib/core/routing/routes.dart +++ b/app/lib/core/routing/routes.dart @@ -23,7 +23,6 @@ import 'package:weblibre/features/settings/presentation/screens/web_engine_harde import 'package:weblibre/features/settings/presentation/screens/web_engine_hardening_group.dart'; import 'package:weblibre/features/settings/presentation/screens/web_engine_settings.dart'; import 'package:weblibre/features/tor/presentation/screens/tor_proxy.dart'; -import 'package:weblibre/features/user/presentation/screens/auth.dart'; import 'package:weblibre/features/web_feed/presentation/add_feed_dialog.dart'; import 'package:weblibre/features/web_feed/presentation/screens/feed_article.dart'; import 'package:weblibre/features/web_feed/presentation/screens/feed_article_list.dart'; @@ -44,11 +43,3 @@ class AboutRoute extends GoRouteData { return DialogPage(builder: (_) => const AboutDialogScreen()); } } - -@TypedGoRoute(name: 'UserAuthRoute', path: '/userAuth') -class UserAuthRoute extends GoRouteData { - @override - Page buildPage(BuildContext context, GoRouterState state) { - return DialogPage(builder: (_) => const UserAuthScreen()); - } -} diff --git a/app/lib/core/routing/routes.g.dart b/app/lib/core/routing/routes.g.dart index ae80bd29..fb5cf2a4 100644 --- a/app/lib/core/routing/routes.g.dart +++ b/app/lib/core/routing/routes.g.dart @@ -8,7 +8,6 @@ part of 'routes.dart'; List get $appRoutes => [ $aboutRoute, - $userAuthRoute, $settingsRoute, $browserRoute, $bangCategoriesRoute, @@ -37,28 +36,6 @@ extension $AboutRouteExtension on AboutRoute { void replace(BuildContext context) => context.replace(location); } -RouteBase get $userAuthRoute => GoRouteData.$route( - path: '/userAuth', - name: 'UserAuthRoute', - - factory: $UserAuthRouteExtension._fromState, -); - -extension $UserAuthRouteExtension on UserAuthRoute { - static UserAuthRoute _fromState(GoRouterState state) => UserAuthRoute(); - - String get location => GoRouteData.$location('/userAuth'); - - void go(BuildContext context) => context.go(location); - - Future push(BuildContext context) => context.push(location); - - void pushReplacement(BuildContext context) => - context.pushReplacement(location); - - void replace(BuildContext context) => context.replace(location); -} - RouteBase get $settingsRoute => GoRouteData.$route( path: '/settings', name: 'SettingsRoute', diff --git a/app/lib/features/user/domain/providers.dart b/app/lib/features/user/domain/providers.dart index f421627e..396b39d4 100644 --- a/app/lib/features/user/domain/providers.dart +++ b/app/lib/features/user/domain/providers.dart @@ -1,5 +1,4 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -import 'package:pocketbase/pocketbase.dart'; import 'package:riverpod/riverpod.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:weblibre/features/user/data/providers.dart'; @@ -21,35 +20,6 @@ Stream iconCacheSizeMegabytes(Ref ref) { return repository.cacheDao.getIconCacheSize().watchSingle(); } -@Riverpod(keepAlive: true) -AsyncAuthStore authStore(Ref ref) { - const secureStorage = FlutterSecureStorage(); - - final intial = ref.watch( - _storedAuthDataProvider.select((value) => value.valueOrNull), - ); - - return AsyncAuthStore( - initial: intial, - save: (data) async { - await secureStorage.write(key: _authKey, value: data); - }, - ); -} - -@Riverpod() -Stream authState(Ref ref) { - final authStore = ref.watch(authStoreProvider); - return authStore.onChange; -} - -@Riverpod(keepAlive: true) -PocketBase pocketBase(Ref ref) { - final authStore = ref.watch(authStoreProvider); - - return PocketBase('http://192.168.2.104:8090', authStore: authStore); -} - @Riverpod() bool incognitoModeEnabled(Ref ref) { return ref.watch( diff --git a/app/lib/features/user/domain/providers.g.dart b/app/lib/features/user/domain/providers.g.dart index dc80c5c4..9ba28c12 100644 --- a/app/lib/features/user/domain/providers.g.dart +++ b/app/lib/features/user/domain/providers.g.dart @@ -44,54 +44,6 @@ final iconCacheSizeMegabytesProvider = @Deprecated('Will be removed in 3.0. Use Ref instead') // ignore: unused_element typedef IconCacheSizeMegabytesRef = AutoDisposeStreamProviderRef; -String _$authStoreHash() => r'766c001bbb8d7dc4e148eff3816c414d78e77f26'; - -/// See also [authStore]. -@ProviderFor(authStore) -final authStoreProvider = Provider.internal( - authStore, - name: r'authStoreProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') ? null : _$authStoreHash, - dependencies: null, - allTransitiveDependencies: null, -); - -@Deprecated('Will be removed in 3.0. Use Ref instead') -// ignore: unused_element -typedef AuthStoreRef = ProviderRef; -String _$authStateHash() => r'ffa411ae0abc5c7bb3e8a93e783bd8398ce7f666'; - -/// See also [authState]. -@ProviderFor(authState) -final authStateProvider = AutoDisposeStreamProvider.internal( - authState, - name: r'authStateProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') ? null : _$authStateHash, - dependencies: null, - allTransitiveDependencies: null, -); - -@Deprecated('Will be removed in 3.0. Use Ref instead') -// ignore: unused_element -typedef AuthStateRef = AutoDisposeStreamProviderRef; -String _$pocketBaseHash() => r'9e1dc8057e300bc7ca697da9f68ec61e70fdbaab'; - -/// See also [pocketBase]. -@ProviderFor(pocketBase) -final pocketBaseProvider = Provider.internal( - pocketBase, - name: r'pocketBaseProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') ? null : _$pocketBaseHash, - dependencies: null, - allTransitiveDependencies: null, -); - -@Deprecated('Will be removed in 3.0. Use Ref instead') -// ignore: unused_element -typedef PocketBaseRef = ProviderRef; String _$incognitoModeEnabledHash() => r'3968c2d4945be09a0bc08ce0d70b0390187c44e8'; diff --git a/app/lib/features/user/domain/repositories/auth.dart b/app/lib/features/user/domain/repositories/auth.dart deleted file mode 100644 index 6375ca8f..00000000 --- a/app/lib/features/user/domain/repositories/auth.dart +++ /dev/null @@ -1,44 +0,0 @@ -import 'package:pocketbase/pocketbase.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; -import 'package:weblibre/features/user/domain/entities/auth_exception.dart'; -import 'package:weblibre/features/user/domain/providers.dart'; -import 'package:weblibre/features/user/extensions/client_exception.dart'; - -part 'auth.g.dart'; - -@Riverpod() -class AuthRepository extends _$AuthRepository { - late PocketBase _pb; - - Future authWithPassword(String user, String password) async { - try { - return await _pb.collection('users').authWithPassword(user, password); - } on ClientException catch (e) { - throw AuthException(e.errorMessage); - } - } - - Future createUserWithPassword( - String email, - String password, - ) async { - try { - return await _pb - .collection('users') - .create( - body: { - "email": email, - "password": password, - "passwordConfirm": password, - }, - ); - } on ClientException catch (e) { - throw AuthException(e.errorMessage); - } - } - - @override - void build() { - _pb = ref.watch(pocketBaseProvider); - } -} diff --git a/app/lib/features/user/domain/repositories/auth.g.dart b/app/lib/features/user/domain/repositories/auth.g.dart deleted file mode 100644 index 43ea7255..00000000 --- a/app/lib/features/user/domain/repositories/auth.g.dart +++ /dev/null @@ -1,27 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'auth.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$authRepositoryHash() => r'90ea6f082ef968831763c7f7ee31863f1fe329fe'; - -/// See also [AuthRepository]. -@ProviderFor(AuthRepository) -final authRepositoryProvider = - AutoDisposeNotifierProvider.internal( - AuthRepository.new, - name: r'authRepositoryProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') - ? null - : _$authRepositoryHash, - dependencies: null, - allTransitiveDependencies: null, - ); - -typedef _$AuthRepository = AutoDisposeNotifier; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/app/lib/features/user/extensions/client_exception.dart b/app/lib/features/user/extensions/client_exception.dart deleted file mode 100644 index 3bd5c0aa..00000000 --- a/app/lib/features/user/extensions/client_exception.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:pocketbase/pocketbase.dart'; -import 'package:weblibre/extensions/string.dart'; - -extension ClientExceptionExtension on ClientException { - String get errorMessage { - var message = "${response["message"] as String? ?? ""}\n\n"; - final data = response["data"] as Map; - try { - data.forEach((key, value) { - final detailedMessage = (value as Map)["message"]; - if (detailedMessage != null) { - message += '${key.toCapitalized()}: $detailedMessage\n'; - } - }); - } catch (_) {} - try { - if (originalError != null) { - message += ' $originalError'; - } - } catch (_) {} - - return message.trim(); - } -} diff --git a/app/lib/features/user/presentation/controllers/controllers.dart b/app/lib/features/user/presentation/controllers/controllers.dart deleted file mode 100644 index de2865d1..00000000 --- a/app/lib/features/user/presentation/controllers/controllers.dart +++ /dev/null @@ -1,35 +0,0 @@ -import 'package:riverpod_annotation/riverpod_annotation.dart'; -import 'package:weblibre/features/user/domain/repositories/auth.dart'; - -part 'controllers.g.dart'; - -@Riverpod() -class AuthController extends _$AuthController { - @override - Future build() { - return Future.value(); - } - - Future authWithPassword(String user, String password) async { - state = const AsyncLoading(); - state = await AsyncValue.guard( - () => ref - .read(authRepositoryProvider.notifier) - .authWithPassword(user, password), - ); - } - - Future registerWithPassword(String user, String password) async { - state = const AsyncLoading(); - state = await AsyncValue.guard(() { - final repo = ref.read(authRepositoryProvider.notifier); - return repo - .createUserWithPassword(user, password) - .then((_) => repo.authWithPassword(user, password)); - }); - } - - void clearState() { - state = const AsyncValue.data(null); - } -} diff --git a/app/lib/features/user/presentation/controllers/controllers.g.dart b/app/lib/features/user/presentation/controllers/controllers.g.dart deleted file mode 100644 index b79aee7a..00000000 --- a/app/lib/features/user/presentation/controllers/controllers.g.dart +++ /dev/null @@ -1,27 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'controllers.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$authControllerHash() => r'0085e324fbe093c1984eaa56dbfac33472138f9f'; - -/// See also [AuthController]. -@ProviderFor(AuthController) -final authControllerProvider = - AutoDisposeAsyncNotifierProvider.internal( - AuthController.new, - name: r'authControllerProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') - ? null - : _$authControllerHash, - dependencies: null, - allTransitiveDependencies: null, - ); - -typedef _$AuthController = AutoDisposeAsyncNotifier; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/app/lib/features/user/presentation/screens/auth.dart b/app/lib/features/user/presentation/screens/auth.dart deleted file mode 100644 index cadde9f8..00000000 --- a/app/lib/features/user/presentation/screens/auth.dart +++ /dev/null @@ -1,201 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:go_router/go_router.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:nullability/nullability.dart'; -import 'package:weblibre/features/user/domain/providers.dart'; -import 'package:weblibre/features/user/presentation/controllers/controllers.dart'; - -enum _AuthType { login, signup } - -class UserAuthScreen extends HookConsumerWidget { - const UserAuthScreen(); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final formKey = useMemoized(() => GlobalKey()); - - final authType = useState(_AuthType.login); - - final userTextController = useTextEditingController(); - final passwordTextController = useTextEditingController(); - final confirmPasswordTextController = useTextEditingController(); - - final authState = ref.watch(authControllerProvider); - - ref.listen(authStateProvider.select((value) => value.valueOrNull), ( - previous, - next, - ) { - if (next?.token.isNotEmpty ?? false) { - context.pop(true); - } - }); - - return Dialog( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Form( - key: formKey, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - TextFormField( - controller: userTextController, - decoration: const InputDecoration( - label: Text('Email'), - icon: Icon(Icons.account_circle), - ), - validator: (value) { - if (value.isEmpty) { - return 'Email must be provided'; - } - - return null; - }, - keyboardType: TextInputType.emailAddress, - ), - const SizedBox(height: 8.0), - HookBuilder( - builder: (context) { - final obscure = useState(true); - - return Column( - children: [ - TextFormField( - controller: passwordTextController, - decoration: InputDecoration( - label: const Text('Password'), - icon: const Icon(Icons.lock), - suffixIcon: IconButton( - onPressed: () { - obscure.value = !obscure.value; - }, - icon: Icon( - obscure.value - ? Icons.visibility - : Icons.visibility_off, - ), - ), - ), - obscureText: obscure.value, - validator: (value) { - if (value.isEmpty) { - return 'Password must be provided'; - } - - return null; - }, - ), - if (authType.value == _AuthType.signup) - TextFormField( - controller: confirmPasswordTextController, - decoration: InputDecoration( - label: const Text('Confirm Password'), - icon: const Icon(Icons.lock), - suffixIcon: IconButton( - onPressed: () { - obscure.value = !obscure.value; - }, - icon: Icon( - obscure.value - ? Icons.visibility - : Icons.visibility_off, - ), - ), - ), - obscureText: obscure.value, - validator: (value) { - if (value.isEmpty) { - return 'Password must be provided'; - } - - if (value != passwordTextController.text) { - return 'Password not matching'; - } - - return null; - }, - ), - ], - ); - }, - ), - const SizedBox(height: 16), - if (authState.hasError && !authState.isLoading) - Padding( - padding: const EdgeInsets.only(bottom: 16.0), - child: Text( - authState.error.toString(), - style: TextStyle( - color: Theme.of(context).colorScheme.error, - ), - ), - ), - if (!authState.isLoading) - switch (authType.value) { - _AuthType.login => FilledButton( - onPressed: () async { - if (formKey.currentState?.validate() ?? false) { - final controller = ref.read( - authControllerProvider.notifier, - ); - - await controller.authWithPassword( - userTextController.text, - passwordTextController.text, - ); - } - }, - child: const Text('Login'), - ), - _AuthType.signup => FilledButton( - onPressed: () async { - if (formKey.currentState?.validate() ?? false) { - final controller = ref.read( - authControllerProvider.notifier, - ); - - await controller.registerWithPassword( - userTextController.text, - passwordTextController.text, - ); - } - }, - child: const Text('Signup'), - ), - } - else - const CircularProgressIndicator(), - if (!authState.isLoading) - switch (authType.value) { - _AuthType.login => TextButton( - onPressed: () { - final controller = ref.read( - authControllerProvider.notifier, - ); - - controller.clearState(); - authType.value = _AuthType.signup; - }, - child: const Text('Signup'), - ), - _AuthType.signup => TextButton( - onPressed: () { - final controller = ref.read( - authControllerProvider.notifier, - ); - - controller.clearState(); - authType.value = _AuthType.login; - }, - child: const Text('Login'), - ), - }, - ], - ), - ), - ), - ); - } -} diff --git a/app/pubspec.yaml b/app/pubspec.yaml index b402aacf..58abed76 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -48,7 +48,6 @@ dependencies: package_info_plus: ^8.3.0 path: ^1.9.1 path_provider: ^2.1.5 - pocketbase: ^0.22.0 riverpod: ^2.6.1 riverpod_annotation: ^2.6.1 rss_dart: ^1.0.12