mirror of
https://github.com/Dr-Blank/Vaani.git
synced 2026-02-05 00:49:34 +00:00
refactor: update AuthenticatedUser model to require id and remove password, enhance server URI handling in AddNewServer widget
This commit is contained in:
parent
eda45efbce
commit
fa815ae206
10 changed files with 297 additions and 72 deletions
|
|
@ -7,7 +7,9 @@ import 'package:logging/logging.dart';
|
|||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:shelfsdk/audiobookshelf_api.dart';
|
||||
import 'package:vaani/db/cache_manager.dart';
|
||||
import 'package:vaani/models/error_response.dart';
|
||||
import 'package:vaani/settings/api_settings_provider.dart';
|
||||
import 'package:vaani/settings/models/authenticated_user.dart';
|
||||
import 'package:vaani/shared/extensions/obfuscation.dart';
|
||||
|
||||
part 'api_provider.g.dart';
|
||||
|
|
@ -49,6 +51,7 @@ AudiobookshelfApi authenticatedApi(AuthenticatedApiRef ref) {
|
|||
final apiSettings = ref.watch(apiSettingsProvider);
|
||||
final user = apiSettings.activeUser;
|
||||
if (user == null) {
|
||||
_logger.severe('No active user can not provide authenticated api');
|
||||
throw StateError('No active user');
|
||||
}
|
||||
return AudiobookshelfApi(
|
||||
|
|
@ -97,17 +100,26 @@ class PersonalizedView extends _$PersonalizedView {
|
|||
final api = ref.watch(authenticatedApiProvider);
|
||||
final apiSettings = ref.watch(apiSettingsProvider);
|
||||
final user = apiSettings.activeUser;
|
||||
if (user == null) {
|
||||
_logger.warning('no active user');
|
||||
yield [];
|
||||
return;
|
||||
}
|
||||
if (apiSettings.activeLibraryId == null) {
|
||||
// set it to default user library by logging in and getting the library id
|
||||
final login =
|
||||
await api.login(username: user!.username!, password: user.password!);
|
||||
final login = await ref.read(loginProvider().future);
|
||||
if (login == null) {
|
||||
_logger.shout('failed to login, not building personalized view');
|
||||
yield [];
|
||||
return;
|
||||
}
|
||||
ref.read(apiSettingsProvider.notifier).updateState(
|
||||
apiSettings.copyWith(activeLibraryId: login!.userDefaultLibraryId),
|
||||
apiSettings.copyWith(activeLibraryId: login.userDefaultLibraryId),
|
||||
);
|
||||
}
|
||||
// try to find in cache
|
||||
// final cacheKey = 'personalizedView:${apiSettings.activeLibraryId}';
|
||||
var key = 'personalizedView:${apiSettings.activeLibraryId! + user!.id!}';
|
||||
final key = 'personalizedView:${apiSettings.activeLibraryId! + user.id}';
|
||||
final cachedRes = await apiResponseCacheManager.getFileFromMemory(
|
||||
key,
|
||||
) ??
|
||||
|
|
@ -127,7 +139,7 @@ class PersonalizedView extends _$PersonalizedView {
|
|||
}
|
||||
}
|
||||
|
||||
// ! exagerated delay
|
||||
// ! exaggerated delay
|
||||
// await Future.delayed(const Duration(seconds: 2));
|
||||
final res = await api.libraries
|
||||
.getPersonalized(libraryId: apiSettings.activeLibraryId!);
|
||||
|
|
@ -151,6 +163,7 @@ class PersonalizedView extends _$PersonalizedView {
|
|||
// method to force refresh the view and ignore the cache
|
||||
Future<void> forceRefresh() async {
|
||||
// clear the cache
|
||||
// TODO: find a better way to clear the cache for only personalized view key
|
||||
return apiResponseCacheManager.emptyCache();
|
||||
}
|
||||
}
|
||||
|
|
@ -173,6 +186,47 @@ FutureOr<User> me(
|
|||
MeRef ref,
|
||||
) async {
|
||||
final api = ref.watch(authenticatedApiProvider);
|
||||
final res = await api.me.getUser();
|
||||
return res!;
|
||||
final errorResponseHandler = ErrorResponseHandler();
|
||||
final res = await api.me.getUser(
|
||||
responseErrorHandler: errorResponseHandler.storeError,
|
||||
);
|
||||
if (res == null) {
|
||||
_logger.severe(
|
||||
'me failed, got response: ${errorResponseHandler.response.obfuscate()}',
|
||||
);
|
||||
throw StateError('me failed');
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@riverpod
|
||||
FutureOr<LoginResponse?> login(
|
||||
LoginRef ref, {
|
||||
AuthenticatedUser? user,
|
||||
}) async {
|
||||
if (user == null) {
|
||||
// try to get the user from settings
|
||||
final apiSettings = ref.watch(apiSettingsProvider);
|
||||
user = apiSettings.activeUser;
|
||||
if (user == null) {
|
||||
_logger.severe('no active user to login');
|
||||
return null;
|
||||
}
|
||||
_logger.fine('no user provided, using active user: ${user.obfuscate()}');
|
||||
}
|
||||
final api = ref.watch(audiobookshelfApiProvider(user.server.serverUrl));
|
||||
api.token = user.authToken;
|
||||
var errorResponseHandler = ErrorResponseHandler();
|
||||
_logger.fine('logging in with authenticated api');
|
||||
final res = await api.misc.authorize(
|
||||
responseErrorHandler: errorResponseHandler.storeError,
|
||||
);
|
||||
if (res == null) {
|
||||
_logger.severe(
|
||||
'login failed, got response: ${errorResponseHandler.response.obfuscate()}',
|
||||
);
|
||||
return null;
|
||||
}
|
||||
_logger.fine('login response: ${res.obfuscate()}');
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ class _AudiobookshelfApiProviderElement
|
|||
Uri? get baseUrl => (origin as AudiobookshelfApiProvider).baseUrl;
|
||||
}
|
||||
|
||||
String _$authenticatedApiHash() => r'f555efb6eede590b5a8d60cad2e6bfc2847e2d14';
|
||||
String _$authenticatedApiHash() => r'e662465f01ab1a6384db4738a3ae49b5fab48a4f';
|
||||
|
||||
/// get the api instance for the authenticated user
|
||||
///
|
||||
|
|
@ -507,7 +507,7 @@ final fetchContinueListeningProvider =
|
|||
|
||||
typedef FetchContinueListeningRef
|
||||
= AutoDisposeFutureProviderRef<GetUserSessionsResponse>;
|
||||
String _$meHash() => r'bdc664c4fd867ad13018fa769ce7a6913248c44f';
|
||||
String _$meHash() => r'da5f40b8063b0c0a6651fdcc4ac2d192d0dc7df6';
|
||||
|
||||
/// See also [me].
|
||||
@ProviderFor(me)
|
||||
|
|
@ -521,7 +521,134 @@ final meProvider = AutoDisposeFutureProvider<User>.internal(
|
|||
);
|
||||
|
||||
typedef MeRef = AutoDisposeFutureProviderRef<User>;
|
||||
String _$personalizedViewHash() => r'4c392ece4650bdc36d7195a0ddb8810e8fe4caa9';
|
||||
String _$loginHash() => r'eb1c4fcef1818dce994846c1adb8eca8f6ec9259';
|
||||
|
||||
/// See also [login].
|
||||
@ProviderFor(login)
|
||||
const loginProvider = LoginFamily();
|
||||
|
||||
/// See also [login].
|
||||
class LoginFamily extends Family<AsyncValue<LoginResponse?>> {
|
||||
/// See also [login].
|
||||
const LoginFamily();
|
||||
|
||||
/// See also [login].
|
||||
LoginProvider call({
|
||||
AuthenticatedUser? user,
|
||||
}) {
|
||||
return LoginProvider(
|
||||
user: user,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
LoginProvider getProviderOverride(
|
||||
covariant LoginProvider provider,
|
||||
) {
|
||||
return call(
|
||||
user: provider.user,
|
||||
);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'loginProvider';
|
||||
}
|
||||
|
||||
/// See also [login].
|
||||
class LoginProvider extends AutoDisposeFutureProvider<LoginResponse?> {
|
||||
/// See also [login].
|
||||
LoginProvider({
|
||||
AuthenticatedUser? user,
|
||||
}) : this._internal(
|
||||
(ref) => login(
|
||||
ref as LoginRef,
|
||||
user: user,
|
||||
),
|
||||
from: loginProvider,
|
||||
name: r'loginProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$loginHash,
|
||||
dependencies: LoginFamily._dependencies,
|
||||
allTransitiveDependencies: LoginFamily._allTransitiveDependencies,
|
||||
user: user,
|
||||
);
|
||||
|
||||
LoginProvider._internal(
|
||||
super._createNotifier, {
|
||||
required super.name,
|
||||
required super.dependencies,
|
||||
required super.allTransitiveDependencies,
|
||||
required super.debugGetCreateSourceHash,
|
||||
required super.from,
|
||||
required this.user,
|
||||
}) : super.internal();
|
||||
|
||||
final AuthenticatedUser? user;
|
||||
|
||||
@override
|
||||
Override overrideWith(
|
||||
FutureOr<LoginResponse?> Function(LoginRef provider) create,
|
||||
) {
|
||||
return ProviderOverride(
|
||||
origin: this,
|
||||
override: LoginProvider._internal(
|
||||
(ref) => create(ref as LoginRef),
|
||||
from: from,
|
||||
name: null,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
debugGetCreateSourceHash: null,
|
||||
user: user,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AutoDisposeFutureProviderElement<LoginResponse?> createElement() {
|
||||
return _LoginProviderElement(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is LoginProvider && other.user == user;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, user.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
|
||||
mixin LoginRef on AutoDisposeFutureProviderRef<LoginResponse?> {
|
||||
/// The parameter `user` of this provider.
|
||||
AuthenticatedUser? get user;
|
||||
}
|
||||
|
||||
class _LoginProviderElement
|
||||
extends AutoDisposeFutureProviderElement<LoginResponse?> with LoginRef {
|
||||
_LoginProviderElement(super.provider);
|
||||
|
||||
@override
|
||||
AuthenticatedUser? get user => (origin as LoginProvider).user;
|
||||
}
|
||||
|
||||
String _$personalizedViewHash() => r'65c0bc60e312d290498ab488496495114d407ccb';
|
||||
|
||||
/// fetch the personalized view
|
||||
///
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue