mirror of
https://github.com/Dr-Blank/Vaani.git
synced 2026-04-23 14:49:37 +00:00
Compare commits
3 commits
07aea41c6e
...
e23c0b6c5f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e23c0b6c5f | ||
|
|
a520136e01 | ||
|
|
06694f5f0b |
148 changed files with 9317 additions and 11139 deletions
2
.fvmrc
2
.fvmrc
|
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"flutter": "3.32.0"
|
"flutter": "3.38.6"
|
||||||
}
|
}
|
||||||
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
|
|
@ -22,7 +22,7 @@
|
||||||
"utsname",
|
"utsname",
|
||||||
"Vaani"
|
"Vaani"
|
||||||
],
|
],
|
||||||
"dart.flutterSdkPath": ".fvm/versions/3.32.0",
|
"dart.flutterSdkPath": ".fvm/versions/3.38.6",
|
||||||
"files.exclude": {
|
"files.exclude": {
|
||||||
"**/*.freezed.dart": true,
|
"**/*.freezed.dart": true,
|
||||||
"**/*.g.dart": true
|
"**/*.g.dart": true
|
||||||
|
|
|
||||||
|
|
@ -31,10 +31,10 @@ if (keystorePropertiesFile.exists()) {
|
||||||
android {
|
android {
|
||||||
namespace "dr.blank.vaani"
|
namespace "dr.blank.vaani"
|
||||||
compileSdk flutter.compileSdkVersion
|
compileSdk flutter.compileSdkVersion
|
||||||
// ndkVersion flutter.ndkVersion
|
ndkVersion flutter.ndkVersion
|
||||||
// The NDK version is set to a specific version since it was not building
|
// The NDK version is set to a specific version since it was not building
|
||||||
// TODO remove when https://github.com/flutter/flutter/issues/139427 is closed
|
// TODO remove when https://github.com/flutter/flutter/issues/139427 is closed
|
||||||
ndkVersion = "29.0.13113456"
|
// ndkVersion = "29.0.13113456"
|
||||||
|
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
|
|
@ -64,7 +64,7 @@ android {
|
||||||
applicationId "dr.blank.vaani"
|
applicationId "dr.blank.vaani"
|
||||||
// You can update the following values to match your application needs.
|
// You can update the following values to match your application needs.
|
||||||
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
|
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
|
||||||
minSdkVersion 23
|
minSdkVersion flutter.minSdkVersion
|
||||||
targetSdkVersion flutter.targetSdkVersion
|
targetSdkVersion flutter.targetSdkVersion
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
|
|
@ -100,4 +100,4 @@ configurations.all {
|
||||||
force "androidx.core:core:1.13.1"
|
force "androidx.core:core:1.13.1"
|
||||||
force "androidx.core:core-ktx:1.13.1"
|
force "androidx.core:core-ktx:1.13.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ pluginManagement {
|
||||||
plugins {
|
plugins {
|
||||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||||
id "com.android.application" version '8.10.0' apply false
|
id "com.android.application" version '8.10.0' apply false
|
||||||
id "org.jetbrains.kotlin.android" version "2.0.20" apply false
|
id "org.jetbrains.kotlin.android" version "2.1.10" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
include ":app"
|
include ":app"
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,8 @@ import 'package:vaani/shared/extensions/obfuscation.dart';
|
||||||
part 'api_provider.g.dart';
|
part 'api_provider.g.dart';
|
||||||
|
|
||||||
// TODO: workaround for https://github.com/rrousselGit/riverpod/issues/3718
|
// TODO: workaround for https://github.com/rrousselGit/riverpod/issues/3718
|
||||||
typedef ResponseErrorHandler = void Function(
|
typedef ResponseErrorHandler =
|
||||||
Response response, [
|
void Function(Response response, [Object? error]);
|
||||||
Object? error,
|
|
||||||
]);
|
|
||||||
|
|
||||||
final _logger = Logger('api_provider');
|
final _logger = Logger('api_provider');
|
||||||
|
|
||||||
|
|
@ -39,9 +37,7 @@ AudiobookshelfApi audiobookshelfApi(Ref ref, Uri? baseUrl) {
|
||||||
// try to get the base url from app settings
|
// try to get the base url from app settings
|
||||||
final apiSettings = ref.watch(apiSettingsProvider);
|
final apiSettings = ref.watch(apiSettingsProvider);
|
||||||
baseUrl ??= apiSettings.activeServer?.serverUrl;
|
baseUrl ??= apiSettings.activeServer?.serverUrl;
|
||||||
return AudiobookshelfApi(
|
return AudiobookshelfApi(baseUrl: makeBaseUrl(baseUrl.toString()));
|
||||||
baseUrl: makeBaseUrl(baseUrl.toString()),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// get the api instance for the authenticated user
|
/// get the api instance for the authenticated user
|
||||||
|
|
@ -68,9 +64,9 @@ FutureOr<bool> isServerAlive(Ref ref, String address) async {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return await AudiobookshelfApi(baseUrl: makeBaseUrl(address))
|
return await AudiobookshelfApi(
|
||||||
.server
|
baseUrl: makeBaseUrl(address),
|
||||||
.ping() ??
|
).server.ping() ??
|
||||||
false;
|
false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -86,8 +82,9 @@ FutureOr<ServerStatusResponse?> serverStatus(
|
||||||
]) async {
|
]) async {
|
||||||
_logger.fine('fetching server status: ${baseUrl.obfuscate()}');
|
_logger.fine('fetching server status: ${baseUrl.obfuscate()}');
|
||||||
final api = ref.watch(audiobookshelfApiProvider(baseUrl));
|
final api = ref.watch(audiobookshelfApiProvider(baseUrl));
|
||||||
final res =
|
final res = await api.server.status(
|
||||||
await api.server.status(responseErrorHandler: responseErrorHandler);
|
responseErrorHandler: responseErrorHandler,
|
||||||
|
);
|
||||||
_logger.fine('server status: $res');
|
_logger.fine('server status: $res');
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -113,7 +110,9 @@ class PersonalizedView extends _$PersonalizedView {
|
||||||
yield [];
|
yield [];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ref.read(apiSettingsProvider.notifier).updateState(
|
ref
|
||||||
|
.read(apiSettingsProvider.notifier)
|
||||||
|
.updateState(
|
||||||
apiSettings.copyWith(activeLibraryId: login.userDefaultLibraryId),
|
apiSettings.copyWith(activeLibraryId: login.userDefaultLibraryId),
|
||||||
);
|
);
|
||||||
yield [];
|
yield [];
|
||||||
|
|
@ -122,9 +121,8 @@ class PersonalizedView extends _$PersonalizedView {
|
||||||
// try to find in cache
|
// try to find in cache
|
||||||
// final cacheKey = 'personalizedView:${apiSettings.activeLibraryId}';
|
// final cacheKey = 'personalizedView:${apiSettings.activeLibraryId}';
|
||||||
final key = 'personalizedView:${apiSettings.activeLibraryId! + user.id}';
|
final key = 'personalizedView:${apiSettings.activeLibraryId! + user.id}';
|
||||||
final cachedRes = await apiResponseCacheManager.getFileFromMemory(
|
final cachedRes =
|
||||||
key,
|
await apiResponseCacheManager.getFileFromMemory(key) ??
|
||||||
) ??
|
|
||||||
await apiResponseCacheManager.getFileFromCache(key);
|
await apiResponseCacheManager.getFileFromCache(key);
|
||||||
if (cachedRes != null) {
|
if (cachedRes != null) {
|
||||||
_logger.fine('reading from cache: $cachedRes for key: $key');
|
_logger.fine('reading from cache: $cachedRes for key: $key');
|
||||||
|
|
@ -143,8 +141,9 @@ class PersonalizedView extends _$PersonalizedView {
|
||||||
|
|
||||||
// ! exaggerated delay
|
// ! exaggerated delay
|
||||||
// await Future.delayed(const Duration(seconds: 2));
|
// await Future.delayed(const Duration(seconds: 2));
|
||||||
final res = await api.libraries
|
final res = await api.libraries.getPersonalized(
|
||||||
.getPersonalized(libraryId: apiSettings.activeLibraryId!);
|
libraryId: apiSettings.activeLibraryId!,
|
||||||
|
);
|
||||||
// debugPrint('personalizedView: ${res!.map((e) => e).toSet()}');
|
// debugPrint('personalizedView: ${res!.map((e) => e).toSet()}');
|
||||||
// save to cache
|
// save to cache
|
||||||
if (res != null) {
|
if (res != null) {
|
||||||
|
|
@ -172,9 +171,7 @@ class PersonalizedView extends _$PersonalizedView {
|
||||||
|
|
||||||
/// fetch continue listening audiobooks
|
/// fetch continue listening audiobooks
|
||||||
@riverpod
|
@riverpod
|
||||||
FutureOr<GetUserSessionsResponse> fetchContinueListening(
|
FutureOr<GetUserSessionsResponse> fetchContinueListening(Ref ref) async {
|
||||||
Ref ref,
|
|
||||||
) async {
|
|
||||||
final api = ref.watch(authenticatedApiProvider);
|
final api = ref.watch(authenticatedApiProvider);
|
||||||
final res = await api.me.getSessions();
|
final res = await api.me.getSessions();
|
||||||
// debugPrint(
|
// debugPrint(
|
||||||
|
|
@ -184,9 +181,7 @@ FutureOr<GetUserSessionsResponse> fetchContinueListening(
|
||||||
}
|
}
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
FutureOr<User> me(
|
FutureOr<User> me(Ref ref) async {
|
||||||
Ref ref,
|
|
||||||
) async {
|
|
||||||
final api = ref.watch(authenticatedApiProvider);
|
final api = ref.watch(authenticatedApiProvider);
|
||||||
final errorResponseHandler = ErrorResponseHandler();
|
final errorResponseHandler = ErrorResponseHandler();
|
||||||
final res = await api.me.getUser(
|
final res = await api.me.getUser(
|
||||||
|
|
@ -202,10 +197,7 @@ FutureOr<User> me(
|
||||||
}
|
}
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
FutureOr<LoginResponse?> login(
|
FutureOr<LoginResponse?> login(Ref ref, {AuthenticatedUser? user}) async {
|
||||||
Ref ref, {
|
|
||||||
AuthenticatedUser? user,
|
|
||||||
}) async {
|
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
// try to get the user from settings
|
// try to get the user from settings
|
||||||
final apiSettings = ref.watch(apiSettingsProvider);
|
final apiSettings = ref.watch(apiSettingsProvider);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -19,7 +19,7 @@ final _logger = Logger('authenticated_users_provider');
|
||||||
class AuthenticatedUsers extends _$AuthenticatedUsers {
|
class AuthenticatedUsers extends _$AuthenticatedUsers {
|
||||||
@override
|
@override
|
||||||
Set<model.AuthenticatedUser> build() {
|
Set<model.AuthenticatedUser> build() {
|
||||||
ref.listenSelf((_, __) {
|
listenSelf((_, __) {
|
||||||
writeStateToBox();
|
writeStateToBox();
|
||||||
});
|
});
|
||||||
// get the app settings
|
// get the app settings
|
||||||
|
|
@ -35,9 +35,7 @@ class AuthenticatedUsers extends _$AuthenticatedUsers {
|
||||||
Set<model.AuthenticatedUser> readFromBoxOrCreate() {
|
Set<model.AuthenticatedUser> readFromBoxOrCreate() {
|
||||||
if (_box.isNotEmpty) {
|
if (_box.isNotEmpty) {
|
||||||
final foundData = _box.getRange(0, _box.length);
|
final foundData = _box.getRange(0, _box.length);
|
||||||
_logger.fine(
|
_logger.fine('found users in box: ${foundData.obfuscate()}');
|
||||||
'found users in box: ${foundData.obfuscate()}',
|
|
||||||
);
|
|
||||||
return foundData.toSet();
|
return foundData.toSet();
|
||||||
} else {
|
} else {
|
||||||
_logger.fine('no settings found in box');
|
_logger.fine('no settings found in box');
|
||||||
|
|
@ -59,11 +57,9 @@ class AuthenticatedUsers extends _$AuthenticatedUsers {
|
||||||
ref.invalidateSelf();
|
ref.invalidateSelf();
|
||||||
if (setActive) {
|
if (setActive) {
|
||||||
final apiSettings = ref.read(apiSettingsProvider);
|
final apiSettings = ref.read(apiSettingsProvider);
|
||||||
ref.read(apiSettingsProvider.notifier).updateState(
|
ref
|
||||||
apiSettings.copyWith(
|
.read(apiSettingsProvider.notifier)
|
||||||
activeUser: user,
|
.updateState(apiSettings.copyWith(activeUser: user));
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,11 +82,9 @@ class AuthenticatedUsers extends _$AuthenticatedUsers {
|
||||||
// replace the active user with the first user in the list
|
// replace the active user with the first user in the list
|
||||||
// or null if there are no users left
|
// or null if there are no users left
|
||||||
final newActiveUser = state.isNotEmpty ? state.first : null;
|
final newActiveUser = state.isNotEmpty ? state.first : null;
|
||||||
ref.read(apiSettingsProvider.notifier).updateState(
|
ref
|
||||||
apiSettings.copyWith(
|
.read(apiSettingsProvider.notifier)
|
||||||
activeUser: newActiveUser,
|
.updateState(apiSettings.copyWith(activeUser: newActiveUser));
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,25 +6,70 @@ part of 'authenticated_users_provider.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$authenticatedUsersHash() =>
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
r'5fdd472f62fc3b73ff8417cdce9f02e86c33d00f';
|
// ignore_for_file: type=lint, type=warning
|
||||||
|
/// provides with a set of authenticated users
|
||||||
|
|
||||||
|
@ProviderFor(AuthenticatedUsers)
|
||||||
|
final authenticatedUsersProvider = AuthenticatedUsersProvider._();
|
||||||
|
|
||||||
/// provides with a set of authenticated users
|
/// provides with a set of authenticated users
|
||||||
///
|
final class AuthenticatedUsersProvider
|
||||||
/// Copied from [AuthenticatedUsers].
|
extends
|
||||||
@ProviderFor(AuthenticatedUsers)
|
$NotifierProvider<AuthenticatedUsers, Set<model.AuthenticatedUser>> {
|
||||||
final authenticatedUsersProvider = AutoDisposeNotifierProvider<
|
/// provides with a set of authenticated users
|
||||||
AuthenticatedUsers, Set<model.AuthenticatedUser>>.internal(
|
AuthenticatedUsersProvider._()
|
||||||
AuthenticatedUsers.new,
|
: super(
|
||||||
name: r'authenticatedUsersProvider',
|
from: null,
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
argument: null,
|
||||||
? null
|
retry: null,
|
||||||
: _$authenticatedUsersHash,
|
name: r'authenticatedUsersProvider',
|
||||||
dependencies: null,
|
isAutoDispose: true,
|
||||||
allTransitiveDependencies: null,
|
dependencies: null,
|
||||||
);
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
typedef _$AuthenticatedUsers
|
@override
|
||||||
= AutoDisposeNotifier<Set<model.AuthenticatedUser>>;
|
String debugGetCreateSourceHash() => _$authenticatedUsersHash();
|
||||||
// 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
|
@$internal
|
||||||
|
@override
|
||||||
|
AuthenticatedUsers create() => AuthenticatedUsers();
|
||||||
|
|
||||||
|
/// {@macro riverpod.override_with_value}
|
||||||
|
Override overrideWithValue(Set<model.AuthenticatedUser> value) {
|
||||||
|
return $ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
providerOverride: $SyncValueProvider<Set<model.AuthenticatedUser>>(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String _$authenticatedUsersHash() =>
|
||||||
|
r'c5e82cc70ffc31a0d315e3db9e07a141c583471e';
|
||||||
|
|
||||||
|
/// provides with a set of authenticated users
|
||||||
|
|
||||||
|
abstract class _$AuthenticatedUsers
|
||||||
|
extends $Notifier<Set<model.AuthenticatedUser>> {
|
||||||
|
Set<model.AuthenticatedUser> build();
|
||||||
|
@$mustCallSuper
|
||||||
|
@override
|
||||||
|
void runBuild() {
|
||||||
|
final ref =
|
||||||
|
this.ref
|
||||||
|
as $Ref<Set<model.AuthenticatedUser>, Set<model.AuthenticatedUser>>;
|
||||||
|
final element =
|
||||||
|
ref.element
|
||||||
|
as $ClassProviderElement<
|
||||||
|
AnyNotifier<
|
||||||
|
Set<model.AuthenticatedUser>,
|
||||||
|
Set<model.AuthenticatedUser>
|
||||||
|
>,
|
||||||
|
Set<model.AuthenticatedUser>,
|
||||||
|
Object?,
|
||||||
|
Object?
|
||||||
|
>;
|
||||||
|
element.handleCreate(ref, build);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,8 @@ class CoverImage extends _$CoverImage {
|
||||||
// await Future.delayed(const Duration(seconds: 2));
|
// await Future.delayed(const Duration(seconds: 2));
|
||||||
|
|
||||||
// try to get the image from the cache
|
// try to get the image from the cache
|
||||||
final file = await imageCacheManager.getFileFromMemory(itemId) ??
|
final file =
|
||||||
|
await imageCacheManager.getFileFromMemory(itemId) ??
|
||||||
await imageCacheManager.getFileFromCache(itemId);
|
await imageCacheManager.getFileFromCache(itemId);
|
||||||
|
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
|
|
@ -44,9 +45,7 @@ class CoverImage extends _$CoverImage {
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
_logger.fine(
|
_logger.fine('cover image stale for $itemId, fetching from the server');
|
||||||
'cover image stale for $itemId, fetching from the server',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_logger.fine('cover image not found in cache for $itemId');
|
_logger.fine('cover image not found in cache for $itemId');
|
||||||
|
|
|
||||||
|
|
@ -6,169 +6,94 @@ part of 'image_provider.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$coverImageHash() => r'89cc4783cbc76bb41beae34384d92fb277135c75';
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint, type=warning
|
||||||
|
|
||||||
/// 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class _$CoverImage extends BuildlessStreamNotifier<Uint8List> {
|
|
||||||
late final String itemId;
|
|
||||||
|
|
||||||
Stream<Uint8List> build(
|
|
||||||
String itemId,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See also [CoverImage].
|
|
||||||
@ProviderFor(CoverImage)
|
@ProviderFor(CoverImage)
|
||||||
const coverImageProvider = CoverImageFamily();
|
final coverImageProvider = CoverImageFamily._();
|
||||||
|
|
||||||
/// See also [CoverImage].
|
final class CoverImageProvider
|
||||||
class CoverImageFamily extends Family<AsyncValue<Uint8List>> {
|
extends $StreamNotifierProvider<CoverImage, Uint8List> {
|
||||||
/// See also [CoverImage].
|
CoverImageProvider._({
|
||||||
const CoverImageFamily();
|
required CoverImageFamily super.from,
|
||||||
|
required String super.argument,
|
||||||
|
}) : super(
|
||||||
|
retry: null,
|
||||||
|
name: r'coverImageProvider',
|
||||||
|
isAutoDispose: false,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
/// See also [CoverImage].
|
@override
|
||||||
CoverImageProvider call(
|
String debugGetCreateSourceHash() => _$coverImageHash();
|
||||||
String itemId,
|
|
||||||
) {
|
@override
|
||||||
return CoverImageProvider(
|
String toString() {
|
||||||
itemId,
|
return r'coverImageProvider'
|
||||||
);
|
''
|
||||||
|
'($argument)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@$internal
|
||||||
@override
|
@override
|
||||||
CoverImageProvider getProviderOverride(
|
CoverImage create() => CoverImage();
|
||||||
covariant CoverImageProvider provider,
|
|
||||||
) {
|
|
||||||
return call(
|
|
||||||
provider.itemId,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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'coverImageProvider';
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See also [CoverImage].
|
|
||||||
class CoverImageProvider
|
|
||||||
extends StreamNotifierProviderImpl<CoverImage, Uint8List> {
|
|
||||||
/// See also [CoverImage].
|
|
||||||
CoverImageProvider(
|
|
||||||
String itemId,
|
|
||||||
) : this._internal(
|
|
||||||
() => CoverImage()..itemId = itemId,
|
|
||||||
from: coverImageProvider,
|
|
||||||
name: r'coverImageProvider',
|
|
||||||
debugGetCreateSourceHash:
|
|
||||||
const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$coverImageHash,
|
|
||||||
dependencies: CoverImageFamily._dependencies,
|
|
||||||
allTransitiveDependencies:
|
|
||||||
CoverImageFamily._allTransitiveDependencies,
|
|
||||||
itemId: itemId,
|
|
||||||
);
|
|
||||||
|
|
||||||
CoverImageProvider._internal(
|
|
||||||
super._createNotifier, {
|
|
||||||
required super.name,
|
|
||||||
required super.dependencies,
|
|
||||||
required super.allTransitiveDependencies,
|
|
||||||
required super.debugGetCreateSourceHash,
|
|
||||||
required super.from,
|
|
||||||
required this.itemId,
|
|
||||||
}) : super.internal();
|
|
||||||
|
|
||||||
final String itemId;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Stream<Uint8List> runNotifierBuild(
|
|
||||||
covariant CoverImage notifier,
|
|
||||||
) {
|
|
||||||
return notifier.build(
|
|
||||||
itemId,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Override overrideWith(CoverImage Function() create) {
|
|
||||||
return ProviderOverride(
|
|
||||||
origin: this,
|
|
||||||
override: CoverImageProvider._internal(
|
|
||||||
() => create()..itemId = itemId,
|
|
||||||
from: from,
|
|
||||||
name: null,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
debugGetCreateSourceHash: null,
|
|
||||||
itemId: itemId,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
StreamNotifierProviderElement<CoverImage, Uint8List> createElement() {
|
|
||||||
return _CoverImageProviderElement(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return other is CoverImageProvider && other.itemId == itemId;
|
return other is CoverImageProvider && other.argument == argument;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode {
|
int get hashCode {
|
||||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
return argument.hashCode;
|
||||||
hash = _SystemHash.combine(hash, itemId.hashCode);
|
|
||||||
|
|
||||||
return _SystemHash.finish(hash);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
String _$coverImageHash() => r'89cc4783cbc76bb41beae34384d92fb277135c75';
|
||||||
// ignore: unused_element
|
|
||||||
mixin CoverImageRef on StreamNotifierProviderRef<Uint8List> {
|
|
||||||
/// The parameter `itemId` of this provider.
|
|
||||||
String get itemId;
|
|
||||||
}
|
|
||||||
|
|
||||||
class _CoverImageProviderElement
|
final class CoverImageFamily extends $Family
|
||||||
extends StreamNotifierProviderElement<CoverImage, Uint8List>
|
with
|
||||||
with CoverImageRef {
|
$ClassFamilyOverride<
|
||||||
_CoverImageProviderElement(super.provider);
|
CoverImage,
|
||||||
|
AsyncValue<Uint8List>,
|
||||||
|
Uint8List,
|
||||||
|
Stream<Uint8List>,
|
||||||
|
String
|
||||||
|
> {
|
||||||
|
CoverImageFamily._()
|
||||||
|
: super(
|
||||||
|
retry: null,
|
||||||
|
name: r'coverImageProvider',
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
isAutoDispose: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
CoverImageProvider call(String itemId) =>
|
||||||
|
CoverImageProvider._(argument: itemId, from: this);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get itemId => (origin as CoverImageProvider).itemId;
|
String toString() => r'coverImageProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _$CoverImage extends $StreamNotifier<Uint8List> {
|
||||||
|
late final _$args = ref.$arg as String;
|
||||||
|
String get itemId => _$args;
|
||||||
|
|
||||||
|
Stream<Uint8List> build(String itemId);
|
||||||
|
@$mustCallSuper
|
||||||
|
@override
|
||||||
|
void runBuild() {
|
||||||
|
final ref = this.ref as $Ref<AsyncValue<Uint8List>, Uint8List>;
|
||||||
|
final element =
|
||||||
|
ref.element
|
||||||
|
as $ClassProviderElement<
|
||||||
|
AnyNotifier<AsyncValue<Uint8List>, Uint8List>,
|
||||||
|
AsyncValue<Uint8List>,
|
||||||
|
Object?,
|
||||||
|
Object?
|
||||||
|
>;
|
||||||
|
element.handleCreate(ref, () => build(_$args));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 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
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@ class LibraryItem extends _$LibraryItem {
|
||||||
|
|
||||||
// look for the item in the cache
|
// look for the item in the cache
|
||||||
final key = CacheKey.libraryItem(id);
|
final key = CacheKey.libraryItem(id);
|
||||||
final cachedFile = await apiResponseCacheManager.getFileFromMemory(key) ??
|
final cachedFile =
|
||||||
|
await apiResponseCacheManager.getFileFromMemory(key) ??
|
||||||
await apiResponseCacheManager.getFileFromCache(key);
|
await apiResponseCacheManager.getFileFromCache(key);
|
||||||
if (cachedFile != null) {
|
if (cachedFile != null) {
|
||||||
_logger.fine(
|
_logger.fine(
|
||||||
|
|
|
||||||
|
|
@ -6,184 +6,112 @@ part of 'library_item_provider.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$libraryItemHash() => r'a3cfa7f912e9498a70b5782899018b6964d6445c';
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint, type=warning
|
||||||
/// 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class _$LibraryItem
|
|
||||||
extends BuildlessStreamNotifier<shelfsdk.LibraryItemExpanded> {
|
|
||||||
late final String id;
|
|
||||||
|
|
||||||
Stream<shelfsdk.LibraryItemExpanded> build(
|
|
||||||
String id,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// provides the library item for the given id
|
/// provides the library item for the given id
|
||||||
///
|
|
||||||
/// Copied from [LibraryItem].
|
|
||||||
@ProviderFor(LibraryItem)
|
@ProviderFor(LibraryItem)
|
||||||
const libraryItemProvider = LibraryItemFamily();
|
final libraryItemProvider = LibraryItemFamily._();
|
||||||
|
|
||||||
/// provides the library item for the given id
|
/// provides the library item for the given id
|
||||||
///
|
final class LibraryItemProvider
|
||||||
/// Copied from [LibraryItem].
|
extends $StreamNotifierProvider<LibraryItem, shelfsdk.LibraryItemExpanded> {
|
||||||
class LibraryItemFamily
|
|
||||||
extends Family<AsyncValue<shelfsdk.LibraryItemExpanded>> {
|
|
||||||
/// provides the library item for the given id
|
/// provides the library item for the given id
|
||||||
///
|
LibraryItemProvider._({
|
||||||
/// Copied from [LibraryItem].
|
required LibraryItemFamily super.from,
|
||||||
const LibraryItemFamily();
|
required String super.argument,
|
||||||
|
}) : super(
|
||||||
|
retry: null,
|
||||||
|
name: r'libraryItemProvider',
|
||||||
|
isAutoDispose: false,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
/// provides the library item for the given id
|
@override
|
||||||
///
|
String debugGetCreateSourceHash() => _$libraryItemHash();
|
||||||
/// Copied from [LibraryItem].
|
|
||||||
LibraryItemProvider call(
|
@override
|
||||||
String id,
|
String toString() {
|
||||||
) {
|
return r'libraryItemProvider'
|
||||||
return LibraryItemProvider(
|
''
|
||||||
id,
|
'($argument)';
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@$internal
|
||||||
@override
|
@override
|
||||||
LibraryItemProvider getProviderOverride(
|
LibraryItem create() => LibraryItem();
|
||||||
covariant LibraryItemProvider provider,
|
|
||||||
) {
|
|
||||||
return call(
|
|
||||||
provider.id,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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'libraryItemProvider';
|
|
||||||
}
|
|
||||||
|
|
||||||
/// provides the library item for the given id
|
|
||||||
///
|
|
||||||
/// Copied from [LibraryItem].
|
|
||||||
class LibraryItemProvider extends StreamNotifierProviderImpl<LibraryItem,
|
|
||||||
shelfsdk.LibraryItemExpanded> {
|
|
||||||
/// provides the library item for the given id
|
|
||||||
///
|
|
||||||
/// Copied from [LibraryItem].
|
|
||||||
LibraryItemProvider(
|
|
||||||
String id,
|
|
||||||
) : this._internal(
|
|
||||||
() => LibraryItem()..id = id,
|
|
||||||
from: libraryItemProvider,
|
|
||||||
name: r'libraryItemProvider',
|
|
||||||
debugGetCreateSourceHash:
|
|
||||||
const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$libraryItemHash,
|
|
||||||
dependencies: LibraryItemFamily._dependencies,
|
|
||||||
allTransitiveDependencies:
|
|
||||||
LibraryItemFamily._allTransitiveDependencies,
|
|
||||||
id: id,
|
|
||||||
);
|
|
||||||
|
|
||||||
LibraryItemProvider._internal(
|
|
||||||
super._createNotifier, {
|
|
||||||
required super.name,
|
|
||||||
required super.dependencies,
|
|
||||||
required super.allTransitiveDependencies,
|
|
||||||
required super.debugGetCreateSourceHash,
|
|
||||||
required super.from,
|
|
||||||
required this.id,
|
|
||||||
}) : super.internal();
|
|
||||||
|
|
||||||
final String id;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Stream<shelfsdk.LibraryItemExpanded> runNotifierBuild(
|
|
||||||
covariant LibraryItem notifier,
|
|
||||||
) {
|
|
||||||
return notifier.build(
|
|
||||||
id,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Override overrideWith(LibraryItem Function() create) {
|
|
||||||
return ProviderOverride(
|
|
||||||
origin: this,
|
|
||||||
override: LibraryItemProvider._internal(
|
|
||||||
() => create()..id = id,
|
|
||||||
from: from,
|
|
||||||
name: null,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
debugGetCreateSourceHash: null,
|
|
||||||
id: id,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
StreamNotifierProviderElement<LibraryItem, shelfsdk.LibraryItemExpanded>
|
|
||||||
createElement() {
|
|
||||||
return _LibraryItemProviderElement(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return other is LibraryItemProvider && other.id == id;
|
return other is LibraryItemProvider && other.argument == argument;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode {
|
int get hashCode {
|
||||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
return argument.hashCode;
|
||||||
hash = _SystemHash.combine(hash, id.hashCode);
|
|
||||||
|
|
||||||
return _SystemHash.finish(hash);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
String _$libraryItemHash() => r'a3cfa7f912e9498a70b5782899018b6964d6445c';
|
||||||
// ignore: unused_element
|
|
||||||
mixin LibraryItemRef
|
|
||||||
on StreamNotifierProviderRef<shelfsdk.LibraryItemExpanded> {
|
|
||||||
/// The parameter `id` of this provider.
|
|
||||||
String get id;
|
|
||||||
}
|
|
||||||
|
|
||||||
class _LibraryItemProviderElement extends StreamNotifierProviderElement<
|
/// provides the library item for the given id
|
||||||
LibraryItem, shelfsdk.LibraryItemExpanded> with LibraryItemRef {
|
|
||||||
_LibraryItemProviderElement(super.provider);
|
final class LibraryItemFamily extends $Family
|
||||||
|
with
|
||||||
|
$ClassFamilyOverride<
|
||||||
|
LibraryItem,
|
||||||
|
AsyncValue<shelfsdk.LibraryItemExpanded>,
|
||||||
|
shelfsdk.LibraryItemExpanded,
|
||||||
|
Stream<shelfsdk.LibraryItemExpanded>,
|
||||||
|
String
|
||||||
|
> {
|
||||||
|
LibraryItemFamily._()
|
||||||
|
: super(
|
||||||
|
retry: null,
|
||||||
|
name: r'libraryItemProvider',
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
isAutoDispose: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// provides the library item for the given id
|
||||||
|
|
||||||
|
LibraryItemProvider call(String id) =>
|
||||||
|
LibraryItemProvider._(argument: id, from: this);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get id => (origin as LibraryItemProvider).id;
|
String toString() => r'libraryItemProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// provides the library item for the given id
|
||||||
|
|
||||||
|
abstract class _$LibraryItem
|
||||||
|
extends $StreamNotifier<shelfsdk.LibraryItemExpanded> {
|
||||||
|
late final _$args = ref.$arg as String;
|
||||||
|
String get id => _$args;
|
||||||
|
|
||||||
|
Stream<shelfsdk.LibraryItemExpanded> build(String id);
|
||||||
|
@$mustCallSuper
|
||||||
|
@override
|
||||||
|
void runBuild() {
|
||||||
|
final ref =
|
||||||
|
this.ref
|
||||||
|
as $Ref<
|
||||||
|
AsyncValue<shelfsdk.LibraryItemExpanded>,
|
||||||
|
shelfsdk.LibraryItemExpanded
|
||||||
|
>;
|
||||||
|
final element =
|
||||||
|
ref.element
|
||||||
|
as $ClassProviderElement<
|
||||||
|
AnyNotifier<
|
||||||
|
AsyncValue<shelfsdk.LibraryItemExpanded>,
|
||||||
|
shelfsdk.LibraryItemExpanded
|
||||||
|
>,
|
||||||
|
AsyncValue<shelfsdk.LibraryItemExpanded>,
|
||||||
|
Object?,
|
||||||
|
Object?
|
||||||
|
>;
|
||||||
|
element.handleCreate(ref, () => build(_$args));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 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
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart' show Ref;
|
import 'package:hooks_riverpod/hooks_riverpod.dart'
|
||||||
|
show Ref, ProviderListenableSelect;
|
||||||
import 'package:logging/logging.dart' show Logger;
|
import 'package:logging/logging.dart' show Logger;
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
|
|
@ -32,8 +33,9 @@ Future<Library?> library(Ref ref, String id) async {
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
Future<Library?> currentLibrary(Ref ref) async {
|
Future<Library?> currentLibrary(Ref ref) async {
|
||||||
final libraryId =
|
final libraryId = ref.watch(
|
||||||
ref.watch(apiSettingsProvider.select((s) => s.activeLibraryId));
|
apiSettingsProvider.select((s) => s.activeLibraryId),
|
||||||
|
);
|
||||||
if (libraryId == null) {
|
if (libraryId == null) {
|
||||||
_logger.warning('No active library id found');
|
_logger.warning('No active library id found');
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -6,187 +6,153 @@ part of 'library_provider.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$libraryHash() => r'f8a34100acb58f02fa958c71a629577bf815710e';
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint, type=warning
|
||||||
|
|
||||||
/// 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See also [library].
|
|
||||||
@ProviderFor(library)
|
@ProviderFor(library)
|
||||||
const libraryProvider = LibraryFamily();
|
final libraryProvider = LibraryFamily._();
|
||||||
|
|
||||||
/// See also [library].
|
final class LibraryProvider
|
||||||
class LibraryFamily extends Family<AsyncValue<Library?>> {
|
extends
|
||||||
/// See also [library].
|
$FunctionalProvider<AsyncValue<Library?>, Library?, FutureOr<Library?>>
|
||||||
const LibraryFamily();
|
with $FutureModifier<Library?>, $FutureProvider<Library?> {
|
||||||
|
LibraryProvider._({
|
||||||
|
required LibraryFamily super.from,
|
||||||
|
required String super.argument,
|
||||||
|
}) : super(
|
||||||
|
retry: null,
|
||||||
|
name: r'libraryProvider',
|
||||||
|
isAutoDispose: true,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
/// See also [library].
|
@override
|
||||||
LibraryProvider call(
|
String debugGetCreateSourceHash() => _$libraryHash();
|
||||||
String id,
|
|
||||||
) {
|
@override
|
||||||
return LibraryProvider(
|
String toString() {
|
||||||
id,
|
return r'libraryProvider'
|
||||||
);
|
''
|
||||||
|
'($argument)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@$internal
|
||||||
@override
|
@override
|
||||||
LibraryProvider getProviderOverride(
|
$FutureProviderElement<Library?> $createElement($ProviderPointer pointer) =>
|
||||||
covariant LibraryProvider provider,
|
$FutureProviderElement(pointer);
|
||||||
) {
|
|
||||||
return call(
|
|
||||||
provider.id,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
FutureOr<Library?> create(Ref ref) {
|
||||||
|
final argument = this.argument as String;
|
||||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
return library(ref, argument);
|
||||||
|
|
||||||
@override
|
|
||||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
|
||||||
_allTransitiveDependencies;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String? get name => r'libraryProvider';
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See also [library].
|
|
||||||
class LibraryProvider extends AutoDisposeFutureProvider<Library?> {
|
|
||||||
/// See also [library].
|
|
||||||
LibraryProvider(
|
|
||||||
String id,
|
|
||||||
) : this._internal(
|
|
||||||
(ref) => library(
|
|
||||||
ref as LibraryRef,
|
|
||||||
id,
|
|
||||||
),
|
|
||||||
from: libraryProvider,
|
|
||||||
name: r'libraryProvider',
|
|
||||||
debugGetCreateSourceHash:
|
|
||||||
const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$libraryHash,
|
|
||||||
dependencies: LibraryFamily._dependencies,
|
|
||||||
allTransitiveDependencies: LibraryFamily._allTransitiveDependencies,
|
|
||||||
id: id,
|
|
||||||
);
|
|
||||||
|
|
||||||
LibraryProvider._internal(
|
|
||||||
super._createNotifier, {
|
|
||||||
required super.name,
|
|
||||||
required super.dependencies,
|
|
||||||
required super.allTransitiveDependencies,
|
|
||||||
required super.debugGetCreateSourceHash,
|
|
||||||
required super.from,
|
|
||||||
required this.id,
|
|
||||||
}) : super.internal();
|
|
||||||
|
|
||||||
final String id;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Override overrideWith(
|
|
||||||
FutureOr<Library?> Function(LibraryRef provider) create,
|
|
||||||
) {
|
|
||||||
return ProviderOverride(
|
|
||||||
origin: this,
|
|
||||||
override: LibraryProvider._internal(
|
|
||||||
(ref) => create(ref as LibraryRef),
|
|
||||||
from: from,
|
|
||||||
name: null,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
debugGetCreateSourceHash: null,
|
|
||||||
id: id,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
AutoDisposeFutureProviderElement<Library?> createElement() {
|
|
||||||
return _LibraryProviderElement(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return other is LibraryProvider && other.id == id;
|
return other is LibraryProvider && other.argument == argument;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode {
|
int get hashCode {
|
||||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
return argument.hashCode;
|
||||||
hash = _SystemHash.combine(hash, id.hashCode);
|
|
||||||
|
|
||||||
return _SystemHash.finish(hash);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
String _$libraryHash() => r'f8a34100acb58f02fa958c71a629577bf815710e';
|
||||||
// ignore: unused_element
|
|
||||||
mixin LibraryRef on AutoDisposeFutureProviderRef<Library?> {
|
|
||||||
/// The parameter `id` of this provider.
|
|
||||||
String get id;
|
|
||||||
}
|
|
||||||
|
|
||||||
class _LibraryProviderElement extends AutoDisposeFutureProviderElement<Library?>
|
final class LibraryFamily extends $Family
|
||||||
with LibraryRef {
|
with $FunctionalFamilyOverride<FutureOr<Library?>, String> {
|
||||||
_LibraryProviderElement(super.provider);
|
LibraryFamily._()
|
||||||
|
: super(
|
||||||
|
retry: null,
|
||||||
|
name: r'libraryProvider',
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
isAutoDispose: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
LibraryProvider call(String id) =>
|
||||||
|
LibraryProvider._(argument: id, from: this);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get id => (origin as LibraryProvider).id;
|
String toString() => r'libraryProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProviderFor(currentLibrary)
|
||||||
|
final currentLibraryProvider = CurrentLibraryProvider._();
|
||||||
|
|
||||||
|
final class CurrentLibraryProvider
|
||||||
|
extends
|
||||||
|
$FunctionalProvider<AsyncValue<Library?>, Library?, FutureOr<Library?>>
|
||||||
|
with $FutureModifier<Library?>, $FutureProvider<Library?> {
|
||||||
|
CurrentLibraryProvider._()
|
||||||
|
: super(
|
||||||
|
from: null,
|
||||||
|
argument: null,
|
||||||
|
retry: null,
|
||||||
|
name: r'currentLibraryProvider',
|
||||||
|
isAutoDispose: true,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$currentLibraryHash();
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
$FutureProviderElement<Library?> $createElement($ProviderPointer pointer) =>
|
||||||
|
$FutureProviderElement(pointer);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOr<Library?> create(Ref ref) {
|
||||||
|
return currentLibrary(ref);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$currentLibraryHash() => r'658498a531e04a01e2b3915a3319101285601118';
|
String _$currentLibraryHash() => r'658498a531e04a01e2b3915a3319101285601118';
|
||||||
|
|
||||||
/// See also [currentLibrary].
|
@ProviderFor(Libraries)
|
||||||
@ProviderFor(currentLibrary)
|
final librariesProvider = LibrariesProvider._();
|
||||||
final currentLibraryProvider = AutoDisposeFutureProvider<Library?>.internal(
|
|
||||||
currentLibrary,
|
final class LibrariesProvider
|
||||||
name: r'currentLibraryProvider',
|
extends $AsyncNotifierProvider<Libraries, List<Library>> {
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
LibrariesProvider._()
|
||||||
? null
|
: super(
|
||||||
: _$currentLibraryHash,
|
from: null,
|
||||||
dependencies: null,
|
argument: null,
|
||||||
allTransitiveDependencies: null,
|
retry: null,
|
||||||
);
|
name: r'librariesProvider',
|
||||||
|
isAutoDispose: true,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$librariesHash();
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
Libraries create() => Libraries();
|
||||||
|
}
|
||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
|
||||||
// ignore: unused_element
|
|
||||||
typedef CurrentLibraryRef = AutoDisposeFutureProviderRef<Library?>;
|
|
||||||
String _$librariesHash() => r'95ebd4d1ac0cc2acf7617dc22895eff0ca30600f';
|
String _$librariesHash() => r'95ebd4d1ac0cc2acf7617dc22895eff0ca30600f';
|
||||||
|
|
||||||
/// See also [Libraries].
|
abstract class _$Libraries extends $AsyncNotifier<List<Library>> {
|
||||||
@ProviderFor(Libraries)
|
FutureOr<List<Library>> build();
|
||||||
final librariesProvider =
|
@$mustCallSuper
|
||||||
AutoDisposeAsyncNotifierProvider<Libraries, List<Library>>.internal(
|
@override
|
||||||
Libraries.new,
|
void runBuild() {
|
||||||
name: r'librariesProvider',
|
final ref = this.ref as $Ref<AsyncValue<List<Library>>, List<Library>>;
|
||||||
debugGetCreateSourceHash:
|
final element =
|
||||||
const bool.fromEnvironment('dart.vm.product') ? null : _$librariesHash,
|
ref.element
|
||||||
dependencies: null,
|
as $ClassProviderElement<
|
||||||
allTransitiveDependencies: null,
|
AnyNotifier<AsyncValue<List<Library>>, List<Library>>,
|
||||||
);
|
AsyncValue<List<Library>>,
|
||||||
|
Object?,
|
||||||
typedef _$Libraries = AutoDisposeAsyncNotifier<List<Library>>;
|
Object?
|
||||||
// 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
|
element.handleCreate(ref, build);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ class ServerAlreadyExistsException implements Exception {
|
||||||
class AudiobookShelfServer extends _$AudiobookShelfServer {
|
class AudiobookShelfServer extends _$AudiobookShelfServer {
|
||||||
@override
|
@override
|
||||||
Set<model.AudiobookShelfServer> build() {
|
Set<model.AudiobookShelfServer> build() {
|
||||||
ref.listenSelf((_, __) {
|
listenSelf((_, __) {
|
||||||
writeStateToBox();
|
writeStateToBox();
|
||||||
});
|
});
|
||||||
// get the app settings
|
// get the app settings
|
||||||
|
|
@ -80,11 +80,9 @@ class AudiobookShelfServer extends _$AudiobookShelfServer {
|
||||||
// remove the server from the active server
|
// remove the server from the active server
|
||||||
final apiSettings = ref.read(apiSettingsProvider);
|
final apiSettings = ref.read(apiSettingsProvider);
|
||||||
if (apiSettings.activeServer == server) {
|
if (apiSettings.activeServer == server) {
|
||||||
ref.read(apiSettingsProvider.notifier).updateState(
|
ref
|
||||||
apiSettings.copyWith(
|
.read(apiSettingsProvider.notifier)
|
||||||
activeServer: null,
|
.updateState(apiSettings.copyWith(activeServer: null));
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
// remove the users of this server
|
// remove the users of this server
|
||||||
if (removeUsers) {
|
if (removeUsers) {
|
||||||
|
|
|
||||||
|
|
@ -6,25 +6,78 @@ part of 'server_provider.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$audiobookShelfServerHash() =>
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
r'31a96b431221965cd586aad670a32ca901539e41';
|
// ignore_for_file: type=lint, type=warning
|
||||||
|
/// provides with a set of servers added by the user
|
||||||
|
|
||||||
|
@ProviderFor(AudiobookShelfServer)
|
||||||
|
final audiobookShelfServerProvider = AudiobookShelfServerProvider._();
|
||||||
|
|
||||||
/// provides with a set of servers added by the user
|
/// provides with a set of servers added by the user
|
||||||
///
|
final class AudiobookShelfServerProvider
|
||||||
/// Copied from [AudiobookShelfServer].
|
extends
|
||||||
@ProviderFor(AudiobookShelfServer)
|
$NotifierProvider<
|
||||||
final audiobookShelfServerProvider = AutoDisposeNotifierProvider<
|
AudiobookShelfServer,
|
||||||
AudiobookShelfServer, Set<model.AudiobookShelfServer>>.internal(
|
Set<model.AudiobookShelfServer>
|
||||||
AudiobookShelfServer.new,
|
> {
|
||||||
name: r'audiobookShelfServerProvider',
|
/// provides with a set of servers added by the user
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
AudiobookShelfServerProvider._()
|
||||||
? null
|
: super(
|
||||||
: _$audiobookShelfServerHash,
|
from: null,
|
||||||
dependencies: null,
|
argument: null,
|
||||||
allTransitiveDependencies: null,
|
retry: null,
|
||||||
);
|
name: r'audiobookShelfServerProvider',
|
||||||
|
isAutoDispose: true,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
typedef _$AudiobookShelfServer
|
@override
|
||||||
= AutoDisposeNotifier<Set<model.AudiobookShelfServer>>;
|
String debugGetCreateSourceHash() => _$audiobookShelfServerHash();
|
||||||
// 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
|
@$internal
|
||||||
|
@override
|
||||||
|
AudiobookShelfServer create() => AudiobookShelfServer();
|
||||||
|
|
||||||
|
/// {@macro riverpod.override_with_value}
|
||||||
|
Override overrideWithValue(Set<model.AudiobookShelfServer> value) {
|
||||||
|
return $ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
providerOverride: $SyncValueProvider<Set<model.AudiobookShelfServer>>(
|
||||||
|
value,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String _$audiobookShelfServerHash() =>
|
||||||
|
r'144817dcb3704b80c5b60763167fcf932f00c29c';
|
||||||
|
|
||||||
|
/// provides with a set of servers added by the user
|
||||||
|
|
||||||
|
abstract class _$AudiobookShelfServer
|
||||||
|
extends $Notifier<Set<model.AudiobookShelfServer>> {
|
||||||
|
Set<model.AudiobookShelfServer> build();
|
||||||
|
@$mustCallSuper
|
||||||
|
@override
|
||||||
|
void runBuild() {
|
||||||
|
final ref =
|
||||||
|
this.ref
|
||||||
|
as $Ref<
|
||||||
|
Set<model.AudiobookShelfServer>,
|
||||||
|
Set<model.AudiobookShelfServer>
|
||||||
|
>;
|
||||||
|
final element =
|
||||||
|
ref.element
|
||||||
|
as $ClassProviderElement<
|
||||||
|
AnyNotifier<
|
||||||
|
Set<model.AudiobookShelfServer>,
|
||||||
|
Set<model.AudiobookShelfServer>
|
||||||
|
>,
|
||||||
|
Set<model.AudiobookShelfServer>,
|
||||||
|
Object?,
|
||||||
|
Object?
|
||||||
|
>;
|
||||||
|
element.handleCreate(ref, build);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:flutter/foundation.dart' show immutable;
|
import 'package:flutter/foundation.dart' show immutable;
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive_plus_secure/hive_plus_secure.dart';
|
||||||
import 'package:vaani/features/per_book_settings/models/book_settings.dart';
|
import 'package:vaani/features/per_book_settings/models/book_settings.dart';
|
||||||
import 'package:vaani/settings/models/models.dart';
|
import 'package:vaani/settings/models/models.dart';
|
||||||
|
|
||||||
|
|
@ -14,14 +14,17 @@ class AvailableHiveBoxes {
|
||||||
static final apiSettingsBox = Hive.box<ApiSettings>(name: 'apiSettings');
|
static final apiSettingsBox = Hive.box<ApiSettings>(name: 'apiSettings');
|
||||||
|
|
||||||
/// stores the a list of [AudiobookShelfServer]
|
/// stores the a list of [AudiobookShelfServer]
|
||||||
static final serverBox =
|
static final serverBox = Hive.box<AudiobookShelfServer>(
|
||||||
Hive.box<AudiobookShelfServer>(name: 'audiobookShelfServer');
|
name: 'audiobookShelfServer',
|
||||||
|
);
|
||||||
|
|
||||||
/// stores the a list of [AuthenticatedUser]
|
/// stores the a list of [AuthenticatedUser]
|
||||||
static final authenticatedUserBox =
|
static final authenticatedUserBox = Hive.box<AuthenticatedUser>(
|
||||||
Hive.box<AuthenticatedUser>(name: 'authenticatedUser');
|
name: 'authenticatedUser',
|
||||||
|
);
|
||||||
|
|
||||||
/// stores the a list of [BookSettings]
|
/// stores the a list of [BookSettings]
|
||||||
static final individualBookSettingsBox =
|
static final individualBookSettingsBox = Hive.box<BookSettings>(
|
||||||
Hive.box<BookSettings>(name: 'bookSettings');
|
name: 'bookSettings',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
66
lib/db/cache/schemas/image.dart
vendored
66
lib/db/cache/schemas/image.dart
vendored
|
|
@ -1,39 +1,39 @@
|
||||||
import 'package:isar/isar.dart';
|
// import 'package:isar/isar.dart';
|
||||||
|
|
||||||
part 'image.g.dart';
|
// part 'image.g.dart';
|
||||||
|
|
||||||
/// Represents a cover image for a library item
|
// /// Represents a cover image for a library item
|
||||||
///
|
// ///
|
||||||
/// stores 2 paths, one is thumbnail and the other is the full size image
|
// /// stores 2 paths, one is thumbnail and the other is the full size image
|
||||||
/// both are optional
|
// /// both are optional
|
||||||
/// also stores last fetched date for the image
|
// /// also stores last fetched date for the image
|
||||||
/// Id is passed as a parameter to the collection annotation (the lib_item_id)
|
// /// Id is passed as a parameter to the collection annotation (the lib_item_id)
|
||||||
/// also index the id
|
// /// also index the id
|
||||||
/// This is because the image is a part of the library item and the library item
|
// /// This is because the image is a part of the library item and the library item
|
||||||
/// is the parent of the image
|
// /// is the parent of the image
|
||||||
@Collection(ignore: {'path'})
|
// @Collection(ignore: {'path'})
|
||||||
@Name('CacheImage')
|
// @Name('CacheImage')
|
||||||
class Image {
|
// class Image {
|
||||||
@Id()
|
// @Id()
|
||||||
int id;
|
// int id;
|
||||||
|
|
||||||
String? thumbnailPath;
|
// String? thumbnailPath;
|
||||||
String? imagePath;
|
// String? imagePath;
|
||||||
DateTime lastSaved;
|
// DateTime lastSaved;
|
||||||
|
|
||||||
Image({
|
// Image({
|
||||||
required this.id,
|
// required this.id,
|
||||||
this.thumbnailPath,
|
// this.thumbnailPath,
|
||||||
this.imagePath,
|
// this.imagePath,
|
||||||
}) : lastSaved = DateTime.now();
|
// }) : lastSaved = DateTime.now();
|
||||||
|
|
||||||
/// returns the path to the image
|
// /// returns the path to the image
|
||||||
String? get path => thumbnailPath ?? imagePath;
|
// String? get path => thumbnailPath ?? imagePath;
|
||||||
|
|
||||||
/// automatically updates the last fetched date when saving a new path
|
// /// automatically updates the last fetched date when saving a new path
|
||||||
void updatePath(String? thumbnailPath, String? imagePath) async {
|
// void updatePath(String? thumbnailPath, String? imagePath) async {
|
||||||
this.thumbnailPath = thumbnailPath;
|
// this.thumbnailPath = thumbnailPath;
|
||||||
this.imagePath = imagePath;
|
// this.imagePath = imagePath;
|
||||||
lastSaved = DateTime.now();
|
// lastSaved = DateTime.now();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
|
||||||
1009
lib/db/cache/schemas/image.g.dart
vendored
1009
lib/db/cache/schemas/image.g.dart
vendored
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive_plus_secure/hive_plus_secure.dart';
|
||||||
import 'package:path/path.dart' as p;
|
import 'package:path/path.dart' as p;
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:vaani/main.dart';
|
import 'package:vaani/main.dart';
|
||||||
|
|
@ -13,12 +13,7 @@ Future initStorage() async {
|
||||||
final dir = await getApplicationDocumentsDirectory();
|
final dir = await getApplicationDocumentsDirectory();
|
||||||
|
|
||||||
// use vaani as the directory for hive
|
// use vaani as the directory for hive
|
||||||
final storageDir = Directory(
|
final storageDir = Directory(p.join(dir.path, AppMetadata.appNameLowerCase));
|
||||||
p.join(
|
|
||||||
dir.path,
|
|
||||||
AppMetadata.appNameLowerCase,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
await storageDir.create(recursive: true);
|
await storageDir.create(recursive: true);
|
||||||
|
|
||||||
Hive.defaultDirectory = storageDir.path;
|
Hive.defaultDirectory = storageDir.path;
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,29 @@
|
||||||
// a table to track preferences of player for each book
|
// // a table to track preferences of player for each book
|
||||||
import 'package:isar/isar.dart';
|
// import 'package:isar/isar.dart';
|
||||||
|
|
||||||
part 'book_prefs.g.dart';
|
// part 'book_prefs.g.dart';
|
||||||
|
|
||||||
/// stores the preferences of the player for a book
|
// /// stores the preferences of the player for a book
|
||||||
@Collection()
|
// @Collection()
|
||||||
@Name('BookPrefs')
|
// @Name('BookPrefs')
|
||||||
class BookPrefs {
|
// class BookPrefs {
|
||||||
@Id()
|
// @Id()
|
||||||
int libItemId;
|
// int libItemId;
|
||||||
|
|
||||||
double? speed;
|
// double? speed;
|
||||||
// double? volume;
|
// // double? volume;
|
||||||
// Duration? sleepTimer;
|
// // Duration? sleepTimer;
|
||||||
// bool? showTotalProgress;
|
// // bool? showTotalProgress;
|
||||||
// bool? showChapterProgress;
|
// // bool? showChapterProgress;
|
||||||
// bool? useChapterInfo;
|
// // bool? useChapterInfo;
|
||||||
|
|
||||||
BookPrefs({
|
// BookPrefs({
|
||||||
required this.libItemId,
|
// required this.libItemId,
|
||||||
this.speed,
|
// this.speed,
|
||||||
// this.volume,
|
// // this.volume,
|
||||||
// this.sleepTimer,
|
// // this.sleepTimer,
|
||||||
// this.showTotalProgress,
|
// // this.showTotalProgress,
|
||||||
// this.showChapterProgress,
|
// // this.showChapterProgress,
|
||||||
// this.useChapterInfo,
|
// // this.useChapterInfo,
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
|
||||||
|
|
@ -1,496 +0,0 @@
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'book_prefs.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// _IsarCollectionGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
// coverage:ignore-file
|
|
||||||
// ignore_for_file: duplicate_ignore, invalid_use_of_protected_member, lines_longer_than_80_chars, constant_identifier_names, avoid_js_rounded_ints, no_leading_underscores_for_local_identifiers, require_trailing_commas, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_in_if_null_operators, library_private_types_in_public_api, prefer_const_constructors
|
|
||||||
// ignore_for_file: type=lint
|
|
||||||
|
|
||||||
extension GetBookPrefsCollection on Isar {
|
|
||||||
IsarCollection<int, BookPrefs> get bookPrefs => this.collection();
|
|
||||||
}
|
|
||||||
|
|
||||||
const BookPrefsSchema = IsarGeneratedSchema(
|
|
||||||
schema: IsarSchema(
|
|
||||||
name: 'BookPrefs',
|
|
||||||
idName: 'libItemId',
|
|
||||||
embedded: false,
|
|
||||||
properties: [
|
|
||||||
IsarPropertySchema(
|
|
||||||
name: 'speed',
|
|
||||||
type: IsarType.double,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
indexes: [],
|
|
||||||
),
|
|
||||||
converter: IsarObjectConverter<int, BookPrefs>(
|
|
||||||
serialize: serializeBookPrefs,
|
|
||||||
deserialize: deserializeBookPrefs,
|
|
||||||
deserializeProperty: deserializeBookPrefsProp,
|
|
||||||
),
|
|
||||||
embeddedSchemas: [],
|
|
||||||
);
|
|
||||||
|
|
||||||
@isarProtected
|
|
||||||
int serializeBookPrefs(IsarWriter writer, BookPrefs object) {
|
|
||||||
IsarCore.writeDouble(writer, 1, object.speed ?? double.nan);
|
|
||||||
return object.libItemId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@isarProtected
|
|
||||||
BookPrefs deserializeBookPrefs(IsarReader reader) {
|
|
||||||
final int _libItemId;
|
|
||||||
_libItemId = IsarCore.readId(reader);
|
|
||||||
final double? _speed;
|
|
||||||
{
|
|
||||||
final value = IsarCore.readDouble(reader, 1);
|
|
||||||
if (value.isNaN) {
|
|
||||||
_speed = null;
|
|
||||||
} else {
|
|
||||||
_speed = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final object = BookPrefs(
|
|
||||||
libItemId: _libItemId,
|
|
||||||
speed: _speed,
|
|
||||||
);
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
@isarProtected
|
|
||||||
dynamic deserializeBookPrefsProp(IsarReader reader, int property) {
|
|
||||||
switch (property) {
|
|
||||||
case 0:
|
|
||||||
return IsarCore.readId(reader);
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
final value = IsarCore.readDouble(reader, 1);
|
|
||||||
if (value.isNaN) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
throw ArgumentError('Unknown property: $property');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class _BookPrefsUpdate {
|
|
||||||
bool call({
|
|
||||||
required int libItemId,
|
|
||||||
double? speed,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
class _BookPrefsUpdateImpl implements _BookPrefsUpdate {
|
|
||||||
const _BookPrefsUpdateImpl(this.collection);
|
|
||||||
|
|
||||||
final IsarCollection<int, BookPrefs> collection;
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool call({
|
|
||||||
required int libItemId,
|
|
||||||
Object? speed = ignore,
|
|
||||||
}) {
|
|
||||||
return collection.updateProperties([
|
|
||||||
libItemId
|
|
||||||
], {
|
|
||||||
if (speed != ignore) 1: speed as double?,
|
|
||||||
}) >
|
|
||||||
0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class _BookPrefsUpdateAll {
|
|
||||||
int call({
|
|
||||||
required List<int> libItemId,
|
|
||||||
double? speed,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
class _BookPrefsUpdateAllImpl implements _BookPrefsUpdateAll {
|
|
||||||
const _BookPrefsUpdateAllImpl(this.collection);
|
|
||||||
|
|
||||||
final IsarCollection<int, BookPrefs> collection;
|
|
||||||
|
|
||||||
@override
|
|
||||||
int call({
|
|
||||||
required List<int> libItemId,
|
|
||||||
Object? speed = ignore,
|
|
||||||
}) {
|
|
||||||
return collection.updateProperties(libItemId, {
|
|
||||||
if (speed != ignore) 1: speed as double?,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BookPrefsUpdate on IsarCollection<int, BookPrefs> {
|
|
||||||
_BookPrefsUpdate get update => _BookPrefsUpdateImpl(this);
|
|
||||||
|
|
||||||
_BookPrefsUpdateAll get updateAll => _BookPrefsUpdateAllImpl(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class _BookPrefsQueryUpdate {
|
|
||||||
int call({
|
|
||||||
double? speed,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
class _BookPrefsQueryUpdateImpl implements _BookPrefsQueryUpdate {
|
|
||||||
const _BookPrefsQueryUpdateImpl(this.query, {this.limit});
|
|
||||||
|
|
||||||
final IsarQuery<BookPrefs> query;
|
|
||||||
final int? limit;
|
|
||||||
|
|
||||||
@override
|
|
||||||
int call({
|
|
||||||
Object? speed = ignore,
|
|
||||||
}) {
|
|
||||||
return query.updateProperties(limit: limit, {
|
|
||||||
if (speed != ignore) 1: speed as double?,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BookPrefsQueryUpdate on IsarQuery<BookPrefs> {
|
|
||||||
_BookPrefsQueryUpdate get updateFirst =>
|
|
||||||
_BookPrefsQueryUpdateImpl(this, limit: 1);
|
|
||||||
|
|
||||||
_BookPrefsQueryUpdate get updateAll => _BookPrefsQueryUpdateImpl(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
class _BookPrefsQueryBuilderUpdateImpl implements _BookPrefsQueryUpdate {
|
|
||||||
const _BookPrefsQueryBuilderUpdateImpl(this.query, {this.limit});
|
|
||||||
|
|
||||||
final QueryBuilder<BookPrefs, BookPrefs, QOperations> query;
|
|
||||||
final int? limit;
|
|
||||||
|
|
||||||
@override
|
|
||||||
int call({
|
|
||||||
Object? speed = ignore,
|
|
||||||
}) {
|
|
||||||
final q = query.build();
|
|
||||||
try {
|
|
||||||
return q.updateProperties(limit: limit, {
|
|
||||||
if (speed != ignore) 1: speed as double?,
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
q.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BookPrefsQueryBuilderUpdate
|
|
||||||
on QueryBuilder<BookPrefs, BookPrefs, QOperations> {
|
|
||||||
_BookPrefsQueryUpdate get updateFirst =>
|
|
||||||
_BookPrefsQueryBuilderUpdateImpl(this, limit: 1);
|
|
||||||
|
|
||||||
_BookPrefsQueryUpdate get updateAll => _BookPrefsQueryBuilderUpdateImpl(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BookPrefsQueryFilter
|
|
||||||
on QueryBuilder<BookPrefs, BookPrefs, QFilterCondition> {
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterFilterCondition> libItemIdEqualTo(
|
|
||||||
int value,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
EqualCondition(
|
|
||||||
property: 0,
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterFilterCondition>
|
|
||||||
libItemIdGreaterThan(
|
|
||||||
int value,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
GreaterCondition(
|
|
||||||
property: 0,
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterFilterCondition>
|
|
||||||
libItemIdGreaterThanOrEqualTo(
|
|
||||||
int value,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
GreaterOrEqualCondition(
|
|
||||||
property: 0,
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterFilterCondition> libItemIdLessThan(
|
|
||||||
int value,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
LessCondition(
|
|
||||||
property: 0,
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterFilterCondition>
|
|
||||||
libItemIdLessThanOrEqualTo(
|
|
||||||
int value,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
LessOrEqualCondition(
|
|
||||||
property: 0,
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterFilterCondition> libItemIdBetween(
|
|
||||||
int lower,
|
|
||||||
int upper,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
BetweenCondition(
|
|
||||||
property: 0,
|
|
||||||
lower: lower,
|
|
||||||
upper: upper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterFilterCondition> speedIsNull() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(const IsNullCondition(property: 1));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterFilterCondition> speedIsNotNull() {
|
|
||||||
return QueryBuilder.apply(not(), (query) {
|
|
||||||
return query.addFilterCondition(const IsNullCondition(property: 1));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterFilterCondition> speedEqualTo(
|
|
||||||
double? value, {
|
|
||||||
double epsilon = Filter.epsilon,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
EqualCondition(
|
|
||||||
property: 1,
|
|
||||||
value: value,
|
|
||||||
epsilon: epsilon,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterFilterCondition> speedGreaterThan(
|
|
||||||
double? value, {
|
|
||||||
double epsilon = Filter.epsilon,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
GreaterCondition(
|
|
||||||
property: 1,
|
|
||||||
value: value,
|
|
||||||
epsilon: epsilon,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterFilterCondition>
|
|
||||||
speedGreaterThanOrEqualTo(
|
|
||||||
double? value, {
|
|
||||||
double epsilon = Filter.epsilon,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
GreaterOrEqualCondition(
|
|
||||||
property: 1,
|
|
||||||
value: value,
|
|
||||||
epsilon: epsilon,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterFilterCondition> speedLessThan(
|
|
||||||
double? value, {
|
|
||||||
double epsilon = Filter.epsilon,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
LessCondition(
|
|
||||||
property: 1,
|
|
||||||
value: value,
|
|
||||||
epsilon: epsilon,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterFilterCondition>
|
|
||||||
speedLessThanOrEqualTo(
|
|
||||||
double? value, {
|
|
||||||
double epsilon = Filter.epsilon,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
LessOrEqualCondition(
|
|
||||||
property: 1,
|
|
||||||
value: value,
|
|
||||||
epsilon: epsilon,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterFilterCondition> speedBetween(
|
|
||||||
double? lower,
|
|
||||||
double? upper, {
|
|
||||||
double epsilon = Filter.epsilon,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
BetweenCondition(
|
|
||||||
property: 1,
|
|
||||||
lower: lower,
|
|
||||||
upper: upper,
|
|
||||||
epsilon: epsilon,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BookPrefsQueryObject
|
|
||||||
on QueryBuilder<BookPrefs, BookPrefs, QFilterCondition> {}
|
|
||||||
|
|
||||||
extension BookPrefsQuerySortBy on QueryBuilder<BookPrefs, BookPrefs, QSortBy> {
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterSortBy> sortByLibItemId() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterSortBy> sortByLibItemIdDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(0, sort: Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterSortBy> sortBySpeed() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterSortBy> sortBySpeedDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(1, sort: Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BookPrefsQuerySortThenBy
|
|
||||||
on QueryBuilder<BookPrefs, BookPrefs, QSortThenBy> {
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterSortBy> thenByLibItemId() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterSortBy> thenByLibItemIdDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(0, sort: Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterSortBy> thenBySpeed() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterSortBy> thenBySpeedDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(1, sort: Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BookPrefsQueryWhereDistinct
|
|
||||||
on QueryBuilder<BookPrefs, BookPrefs, QDistinct> {
|
|
||||||
QueryBuilder<BookPrefs, BookPrefs, QAfterDistinct> distinctBySpeed() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addDistinctBy(1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BookPrefsQueryProperty1
|
|
||||||
on QueryBuilder<BookPrefs, BookPrefs, QProperty> {
|
|
||||||
QueryBuilder<BookPrefs, int, QAfterProperty> libItemIdProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addProperty(0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, double?, QAfterProperty> speedProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addProperty(1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BookPrefsQueryProperty2<R>
|
|
||||||
on QueryBuilder<BookPrefs, R, QAfterProperty> {
|
|
||||||
QueryBuilder<BookPrefs, (R, int), QAfterProperty> libItemIdProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addProperty(0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, (R, double?), QAfterProperty> speedProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addProperty(1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BookPrefsQueryProperty3<R1, R2>
|
|
||||||
on QueryBuilder<BookPrefs, (R1, R2), QAfterProperty> {
|
|
||||||
QueryBuilder<BookPrefs, (R1, R2, int), QOperations> libItemIdProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addProperty(0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<BookPrefs, (R1, R2, double?), QOperations> speedProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addProperty(1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive_plus_secure/hive_plus_secure.dart';
|
||||||
import 'package:vaani/features/per_book_settings/models/book_settings.dart';
|
import 'package:vaani/features/per_book_settings/models/book_settings.dart';
|
||||||
import 'package:vaani/settings/models/models.dart';
|
import 'package:vaani/settings/models/models.dart';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,17 +67,13 @@ class AudiobookDownloadManager {
|
||||||
|
|
||||||
late StreamSubscription<TaskUpdate> _updatesSubscription;
|
late StreamSubscription<TaskUpdate> _updatesSubscription;
|
||||||
|
|
||||||
Future<void> queueAudioBookDownload(
|
Future<void> queueAudioBookDownload(LibraryItemExpanded item) async {
|
||||||
LibraryItemExpanded item,
|
|
||||||
) async {
|
|
||||||
_logger.info('queuing download for item: ${item.id}');
|
_logger.info('queuing download for item: ${item.id}');
|
||||||
// create a download task for each file in the item
|
// create a download task for each file in the item
|
||||||
final directory = await getApplicationSupportDirectory();
|
final directory = await getApplicationSupportDirectory();
|
||||||
for (final file in item.libraryFiles) {
|
for (final file in item.libraryFiles) {
|
||||||
// check if the file is already downloaded
|
// check if the file is already downloaded
|
||||||
if (isFileDownloaded(
|
if (isFileDownloaded(constructFilePath(directory, item, file))) {
|
||||||
constructFilePath(directory, item, file),
|
|
||||||
)) {
|
|
||||||
_logger.info('file already downloaded: ${file.metadata.filename}');
|
_logger.info('file already downloaded: ${file.metadata.filename}');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -105,8 +101,7 @@ class AudiobookDownloadManager {
|
||||||
Directory directory,
|
Directory directory,
|
||||||
LibraryItemExpanded item,
|
LibraryItemExpanded item,
|
||||||
LibraryFile file,
|
LibraryFile file,
|
||||||
) =>
|
) => '${directory.path}/${item.relPath}/${file.metadata.filename}';
|
||||||
'${directory.path}/${item.relPath}/${file.metadata.filename}';
|
|
||||||
|
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_updatesSubscription.cancel();
|
_updatesSubscription.cancel();
|
||||||
|
|
|
||||||
|
|
@ -52,13 +52,9 @@ class DownloadManager extends _$DownloadManager {
|
||||||
return manager;
|
return manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> queueAudioBookDownload(
|
Future<void> queueAudioBookDownload(LibraryItemExpanded item) async {
|
||||||
LibraryItemExpanded item,
|
|
||||||
) async {
|
|
||||||
_logger.fine('queueing download for ${item.id}');
|
_logger.fine('queueing download for ${item.id}');
|
||||||
await state.queueAudioBookDownload(
|
await state.queueAudioBookDownload(item);
|
||||||
item,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteDownloadedItem(LibraryItemExpanded item) async {
|
Future<void> deleteDownloadedItem(LibraryItemExpanded item) async {
|
||||||
|
|
@ -83,58 +79,57 @@ class ItemDownloadProgress extends _$ItemDownloadProgress {
|
||||||
Future<double?> build(String id) async {
|
Future<double?> build(String id) async {
|
||||||
final item = await ref.watch(libraryItemProvider(id).future);
|
final item = await ref.watch(libraryItemProvider(id).future);
|
||||||
final manager = ref.read(downloadManagerProvider);
|
final manager = ref.read(downloadManagerProvider);
|
||||||
manager.taskUpdateStream.map((taskUpdate) {
|
manager.taskUpdateStream
|
||||||
if (taskUpdate is! TaskProgressUpdate) {
|
.map((taskUpdate) {
|
||||||
return null;
|
if (taskUpdate is! TaskProgressUpdate) {
|
||||||
}
|
return null;
|
||||||
if (taskUpdate.task.group == id) {
|
}
|
||||||
return taskUpdate;
|
if (taskUpdate.task.group == id) {
|
||||||
}
|
return taskUpdate;
|
||||||
}).listen((task) async {
|
}
|
||||||
if (task != null) {
|
})
|
||||||
final totalSize = item.totalSize;
|
.listen((task) async {
|
||||||
// if total size is 0, return 0
|
if (task != null) {
|
||||||
if (totalSize == 0) {
|
final totalSize = item.totalSize;
|
||||||
state = const AsyncValue.data(0.0);
|
// if total size is 0, return 0
|
||||||
return;
|
if (totalSize == 0) {
|
||||||
}
|
state = const AsyncValue.data(0.0);
|
||||||
final downloadedFiles = await manager.getDownloadedFilesMetadata(item);
|
return;
|
||||||
// calculate total size of downloaded files and total size of item, then divide
|
}
|
||||||
// to get percentage
|
final downloadedFiles = await manager.getDownloadedFilesMetadata(
|
||||||
final downloadedSize = downloadedFiles.fold<int>(
|
item,
|
||||||
0,
|
);
|
||||||
(previousValue, element) => previousValue + element.metadata.size,
|
// calculate total size of downloaded files and total size of item, then divide
|
||||||
);
|
// to get percentage
|
||||||
|
final downloadedSize = downloadedFiles.fold<int>(
|
||||||
|
0,
|
||||||
|
(previousValue, element) => previousValue + element.metadata.size,
|
||||||
|
);
|
||||||
|
|
||||||
final inProgressFileSize = task.progress * task.expectedFileSize;
|
final inProgressFileSize = task.progress * task.expectedFileSize;
|
||||||
final totalDownloadedSize = downloadedSize + inProgressFileSize;
|
final totalDownloadedSize = downloadedSize + inProgressFileSize;
|
||||||
final progress = totalDownloadedSize / totalSize;
|
final progress = totalDownloadedSize / totalSize;
|
||||||
// if current progress is more than calculated progress, do not update
|
// if current progress is more than calculated progress, do not update
|
||||||
if (progress < (state.valueOrNull ?? 0.0)) {
|
if (progress < (state.value ?? 0.0)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
state = AsyncValue.data(progress.clamp(0.0, 1.0));
|
state = AsyncValue.data(progress.clamp(0.0, 1.0));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
FutureOr<List<TaskRecord>> downloadHistory(
|
FutureOr<List<TaskRecord>> downloadHistory(Ref ref, {String? group}) async {
|
||||||
Ref ref, {
|
|
||||||
String? group,
|
|
||||||
}) async {
|
|
||||||
return await FileDownloader().database.allRecords(group: group);
|
return await FileDownloader().database.allRecords(group: group);
|
||||||
}
|
}
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
class IsItemDownloaded extends _$IsItemDownloaded {
|
class IsItemDownloaded extends _$IsItemDownloaded {
|
||||||
@override
|
@override
|
||||||
FutureOr<bool> build(
|
FutureOr<bool> build(LibraryItemExpanded item) {
|
||||||
LibraryItemExpanded item,
|
|
||||||
) {
|
|
||||||
final manager = ref.watch(downloadManagerProvider);
|
final manager = ref.watch(downloadManagerProvider);
|
||||||
return manager.isItemDownloaded(item);
|
return manager.isItemDownloaded(item);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -11,9 +11,7 @@ class DownloadsPage extends HookConsumerWidget {
|
||||||
final downloadHistory = ref.watch(downloadHistoryProvider());
|
final downloadHistory = ref.watch(downloadHistoryProvider());
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(title: const Text('Downloads')),
|
||||||
title: const Text('Downloads'),
|
|
||||||
),
|
|
||||||
body: Center(
|
body: Center(
|
||||||
// history of downloads
|
// history of downloads
|
||||||
child: downloadHistory.when(
|
child: downloadHistory.when(
|
||||||
|
|
|
||||||
|
|
@ -6,24 +6,64 @@ part of 'search_controller.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint, type=warning
|
||||||
|
/// The controller for the search bar.
|
||||||
|
|
||||||
|
@ProviderFor(GlobalSearchController)
|
||||||
|
final globalSearchControllerProvider = GlobalSearchControllerProvider._();
|
||||||
|
|
||||||
|
/// The controller for the search bar.
|
||||||
|
final class GlobalSearchControllerProvider
|
||||||
|
extends $NotifierProvider<GlobalSearchController, Raw<SearchController>> {
|
||||||
|
/// The controller for the search bar.
|
||||||
|
GlobalSearchControllerProvider._()
|
||||||
|
: super(
|
||||||
|
from: null,
|
||||||
|
argument: null,
|
||||||
|
retry: null,
|
||||||
|
name: r'globalSearchControllerProvider',
|
||||||
|
isAutoDispose: false,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$globalSearchControllerHash();
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
GlobalSearchController create() => GlobalSearchController();
|
||||||
|
|
||||||
|
/// {@macro riverpod.override_with_value}
|
||||||
|
Override overrideWithValue(Raw<SearchController> value) {
|
||||||
|
return $ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
providerOverride: $SyncValueProvider<Raw<SearchController>>(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String _$globalSearchControllerHash() =>
|
String _$globalSearchControllerHash() =>
|
||||||
r'd854ace6f2e00a10fc33aba63051375f82ad1b10';
|
r'd854ace6f2e00a10fc33aba63051375f82ad1b10';
|
||||||
|
|
||||||
/// The controller for the search bar.
|
/// The controller for the search bar.
|
||||||
///
|
|
||||||
/// Copied from [GlobalSearchController].
|
|
||||||
@ProviderFor(GlobalSearchController)
|
|
||||||
final globalSearchControllerProvider =
|
|
||||||
NotifierProvider<GlobalSearchController, Raw<SearchController>>.internal(
|
|
||||||
GlobalSearchController.new,
|
|
||||||
name: r'globalSearchControllerProvider',
|
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$globalSearchControllerHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef _$GlobalSearchController = Notifier<Raw<SearchController>>;
|
abstract class _$GlobalSearchController
|
||||||
// ignore_for_file: type=lint
|
extends $Notifier<Raw<SearchController>> {
|
||||||
// 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
|
Raw<SearchController> build();
|
||||||
|
@$mustCallSuper
|
||||||
|
@override
|
||||||
|
void runBuild() {
|
||||||
|
final ref = this.ref as $Ref<Raw<SearchController>, Raw<SearchController>>;
|
||||||
|
final element =
|
||||||
|
ref.element
|
||||||
|
as $ClassProviderElement<
|
||||||
|
AnyNotifier<Raw<SearchController>, Raw<SearchController>>,
|
||||||
|
Raw<SearchController>,
|
||||||
|
Object?,
|
||||||
|
Object?
|
||||||
|
>;
|
||||||
|
element.handleCreate(ref, build);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,186 +6,94 @@ part of 'search_result_provider.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$searchResultHash() => r'33785de298ad0d53c9d21e8fec88ba2f22f1363f';
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint, type=warning
|
||||||
/// 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The provider for the search result.
|
/// The provider for the search result.
|
||||||
///
|
|
||||||
/// Copied from [searchResult].
|
|
||||||
@ProviderFor(searchResult)
|
@ProviderFor(searchResult)
|
||||||
const searchResultProvider = SearchResultFamily();
|
final searchResultProvider = SearchResultFamily._();
|
||||||
|
|
||||||
/// The provider for the search result.
|
/// The provider for the search result.
|
||||||
///
|
|
||||||
/// Copied from [searchResult].
|
|
||||||
class SearchResultFamily extends Family<AsyncValue<LibrarySearchResponse?>> {
|
|
||||||
/// The provider for the search result.
|
|
||||||
///
|
|
||||||
/// Copied from [searchResult].
|
|
||||||
const SearchResultFamily();
|
|
||||||
|
|
||||||
|
final class SearchResultProvider
|
||||||
|
extends
|
||||||
|
$FunctionalProvider<
|
||||||
|
AsyncValue<LibrarySearchResponse?>,
|
||||||
|
LibrarySearchResponse?,
|
||||||
|
FutureOr<LibrarySearchResponse?>
|
||||||
|
>
|
||||||
|
with
|
||||||
|
$FutureModifier<LibrarySearchResponse?>,
|
||||||
|
$FutureProvider<LibrarySearchResponse?> {
|
||||||
/// The provider for the search result.
|
/// The provider for the search result.
|
||||||
///
|
SearchResultProvider._({
|
||||||
/// Copied from [searchResult].
|
required SearchResultFamily super.from,
|
||||||
SearchResultProvider call(
|
required (String, {int limit}) super.argument,
|
||||||
String query, {
|
}) : super(
|
||||||
int limit = 25,
|
retry: null,
|
||||||
}) {
|
name: r'searchResultProvider',
|
||||||
return SearchResultProvider(
|
isAutoDispose: true,
|
||||||
query,
|
dependencies: null,
|
||||||
limit: limit,
|
$allTransitiveDependencies: null,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$searchResultHash();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return r'searchResultProvider'
|
||||||
|
''
|
||||||
|
'$argument';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@$internal
|
||||||
@override
|
@override
|
||||||
SearchResultProvider getProviderOverride(
|
$FutureProviderElement<LibrarySearchResponse?> $createElement(
|
||||||
covariant SearchResultProvider provider,
|
$ProviderPointer pointer,
|
||||||
) {
|
) => $FutureProviderElement(pointer);
|
||||||
return call(
|
|
||||||
provider.query,
|
|
||||||
limit: provider.limit,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
FutureOr<LibrarySearchResponse?> create(Ref ref) {
|
||||||
|
final argument = this.argument as (String, {int limit});
|
||||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
return searchResult(ref, argument.$1, limit: argument.limit);
|
||||||
|
|
||||||
@override
|
|
||||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
|
||||||
_allTransitiveDependencies;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String? get name => r'searchResultProvider';
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The provider for the search result.
|
|
||||||
///
|
|
||||||
/// Copied from [searchResult].
|
|
||||||
class SearchResultProvider
|
|
||||||
extends AutoDisposeFutureProvider<LibrarySearchResponse?> {
|
|
||||||
/// The provider for the search result.
|
|
||||||
///
|
|
||||||
/// Copied from [searchResult].
|
|
||||||
SearchResultProvider(
|
|
||||||
String query, {
|
|
||||||
int limit = 25,
|
|
||||||
}) : this._internal(
|
|
||||||
(ref) => searchResult(
|
|
||||||
ref as SearchResultRef,
|
|
||||||
query,
|
|
||||||
limit: limit,
|
|
||||||
),
|
|
||||||
from: searchResultProvider,
|
|
||||||
name: r'searchResultProvider',
|
|
||||||
debugGetCreateSourceHash:
|
|
||||||
const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$searchResultHash,
|
|
||||||
dependencies: SearchResultFamily._dependencies,
|
|
||||||
allTransitiveDependencies:
|
|
||||||
SearchResultFamily._allTransitiveDependencies,
|
|
||||||
query: query,
|
|
||||||
limit: limit,
|
|
||||||
);
|
|
||||||
|
|
||||||
SearchResultProvider._internal(
|
|
||||||
super._createNotifier, {
|
|
||||||
required super.name,
|
|
||||||
required super.dependencies,
|
|
||||||
required super.allTransitiveDependencies,
|
|
||||||
required super.debugGetCreateSourceHash,
|
|
||||||
required super.from,
|
|
||||||
required this.query,
|
|
||||||
required this.limit,
|
|
||||||
}) : super.internal();
|
|
||||||
|
|
||||||
final String query;
|
|
||||||
final int limit;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Override overrideWith(
|
|
||||||
FutureOr<LibrarySearchResponse?> Function(SearchResultRef provider) create,
|
|
||||||
) {
|
|
||||||
return ProviderOverride(
|
|
||||||
origin: this,
|
|
||||||
override: SearchResultProvider._internal(
|
|
||||||
(ref) => create(ref as SearchResultRef),
|
|
||||||
from: from,
|
|
||||||
name: null,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
debugGetCreateSourceHash: null,
|
|
||||||
query: query,
|
|
||||||
limit: limit,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
AutoDisposeFutureProviderElement<LibrarySearchResponse?> createElement() {
|
|
||||||
return _SearchResultProviderElement(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return other is SearchResultProvider &&
|
return other is SearchResultProvider && other.argument == argument;
|
||||||
other.query == query &&
|
|
||||||
other.limit == limit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode {
|
int get hashCode {
|
||||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
return argument.hashCode;
|
||||||
hash = _SystemHash.combine(hash, query.hashCode);
|
|
||||||
hash = _SystemHash.combine(hash, limit.hashCode);
|
|
||||||
|
|
||||||
return _SystemHash.finish(hash);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
String _$searchResultHash() => r'33785de298ad0d53c9d21e8fec88ba2f22f1363f';
|
||||||
// ignore: unused_element
|
|
||||||
mixin SearchResultRef on AutoDisposeFutureProviderRef<LibrarySearchResponse?> {
|
|
||||||
/// The parameter `query` of this provider.
|
|
||||||
String get query;
|
|
||||||
|
|
||||||
/// The parameter `limit` of this provider.
|
/// The provider for the search result.
|
||||||
int get limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
class _SearchResultProviderElement
|
final class SearchResultFamily extends $Family
|
||||||
extends AutoDisposeFutureProviderElement<LibrarySearchResponse?>
|
with
|
||||||
with SearchResultRef {
|
$FunctionalFamilyOverride<
|
||||||
_SearchResultProviderElement(super.provider);
|
FutureOr<LibrarySearchResponse?>,
|
||||||
|
(String, {int limit})
|
||||||
|
> {
|
||||||
|
SearchResultFamily._()
|
||||||
|
: super(
|
||||||
|
retry: null,
|
||||||
|
name: r'searchResultProvider',
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
isAutoDispose: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// The provider for the search result.
|
||||||
|
|
||||||
|
SearchResultProvider call(String query, {int limit = 25}) =>
|
||||||
|
SearchResultProvider._(argument: (query, limit: limit), from: this);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get query => (origin as SearchResultProvider).query;
|
String toString() => r'searchResultProvider';
|
||||||
@override
|
|
||||||
int get limit => (origin as SearchResultProvider).limit;
|
|
||||||
}
|
}
|
||||||
// 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
|
|
||||||
|
|
|
||||||
|
|
@ -28,18 +28,14 @@ class ExplorePage extends HookConsumerWidget {
|
||||||
final settings = ref.watch(appSettingsProvider);
|
final settings = ref.watch(appSettingsProvider);
|
||||||
final api = ref.watch(authenticatedApiProvider);
|
final api = ref.watch(authenticatedApiProvider);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(title: const Text('Explore')),
|
||||||
title: const Text('Explore'),
|
|
||||||
),
|
|
||||||
body: const MySearchBar(),
|
body: const MySearchBar(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MySearchBar extends HookConsumerWidget {
|
class MySearchBar extends HookConsumerWidget {
|
||||||
const MySearchBar({
|
const MySearchBar({super.key});
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
|
@ -61,8 +57,11 @@ class MySearchBar extends HookConsumerWidget {
|
||||||
currentQuery = query;
|
currentQuery = query;
|
||||||
|
|
||||||
// In a real application, there should be some error handling here.
|
// In a real application, there should be some error handling here.
|
||||||
final options = await api.libraries
|
final options = await api.libraries.search(
|
||||||
.search(libraryId: settings.activeLibraryId!, query: query, limit: 3);
|
libraryId: settings.activeLibraryId!,
|
||||||
|
query: query,
|
||||||
|
limit: 3,
|
||||||
|
);
|
||||||
|
|
||||||
// If another search happened after this one, throw away these options.
|
// If another search happened after this one, throw away these options.
|
||||||
if (currentQuery != query) {
|
if (currentQuery != query) {
|
||||||
|
|
@ -97,11 +96,10 @@ class MySearchBar extends HookConsumerWidget {
|
||||||
// opacity: 0.5 for the hint text
|
// opacity: 0.5 for the hint text
|
||||||
hintStyle: WidgetStatePropertyAll(
|
hintStyle: WidgetStatePropertyAll(
|
||||||
Theme.of(context).textTheme.bodyMedium!.copyWith(
|
Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||||
color: Theme.of(context)
|
color: Theme.of(
|
||||||
.colorScheme
|
context,
|
||||||
.onSurface
|
).colorScheme.onSurface.withValues(alpha: 0.5),
|
||||||
.withValues(alpha: 0.5),
|
),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
textInputAction: TextInputAction.search,
|
textInputAction: TextInputAction.search,
|
||||||
onTapOutside: (_) {
|
onTapOutside: (_) {
|
||||||
|
|
@ -120,12 +118,7 @@ class MySearchBar extends HookConsumerWidget {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
viewOnSubmitted: (value) {
|
viewOnSubmitted: (value) {
|
||||||
context.pushNamed(
|
context.pushNamed(Routes.search.name, queryParameters: {'q': value});
|
||||||
Routes.search.name,
|
|
||||||
queryParameters: {
|
|
||||||
'q': value,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
suggestionsBuilder: (context, controller) async {
|
suggestionsBuilder: (context, controller) async {
|
||||||
// check if the search controller is empty
|
// check if the search controller is empty
|
||||||
|
|
@ -191,14 +184,12 @@ List<Widget> buildBookSearchResult(
|
||||||
SearchResultMiniSection(
|
SearchResultMiniSection(
|
||||||
// title: 'Books',
|
// title: 'Books',
|
||||||
category: SearchResultCategory.books,
|
category: SearchResultCategory.books,
|
||||||
options: options.book.map(
|
options: options.book.map((result) {
|
||||||
(result) {
|
// convert result to a book object
|
||||||
// convert result to a book object
|
final book = result.libraryItem.media.asBookExpanded;
|
||||||
final book = result.libraryItem.media.asBookExpanded;
|
final metadata = book.metadata.asBookMetadataExpanded;
|
||||||
final metadata = book.metadata.asBookMetadataExpanded;
|
return BookSearchResultMini(book: book, metadata: metadata);
|
||||||
return BookSearchResultMini(book: book, metadata: metadata);
|
}),
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -207,11 +198,9 @@ List<Widget> buildBookSearchResult(
|
||||||
SearchResultMiniSection(
|
SearchResultMiniSection(
|
||||||
// title: 'Authors',
|
// title: 'Authors',
|
||||||
category: SearchResultCategory.authors,
|
category: SearchResultCategory.authors,
|
||||||
options: options.authors.map(
|
options: options.authors.map((result) {
|
||||||
(result) {
|
return ListTile(title: Text(result.name));
|
||||||
return ListTile(title: Text(result.name));
|
}),
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -232,7 +221,7 @@ class BookSearchResultMini extends HookConsumerWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final item = ref.watch(libraryItemProvider(book.libraryItemId)).valueOrNull;
|
final item = ref.watch(libraryItemProvider(book.libraryItemId)).value;
|
||||||
final image = item == null
|
final image = item == null
|
||||||
? const AsyncValue.loading()
|
? const AsyncValue.loading()
|
||||||
: ref.watch(coverImageProvider(item.id));
|
: ref.watch(coverImageProvider(item.id));
|
||||||
|
|
@ -245,10 +234,7 @@ class BookSearchResultMini extends HookConsumerWidget {
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(5),
|
borderRadius: BorderRadius.circular(5),
|
||||||
child: image.when(
|
child: image.when(
|
||||||
data: (bytes) => Image.memory(
|
data: (bytes) => Image.memory(bytes, fit: BoxFit.cover),
|
||||||
bytes,
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
),
|
|
||||||
loading: () => const BookCoverSkeleton(),
|
loading: () => const BookCoverSkeleton(),
|
||||||
error: (error, _) => const Icon(Icons.error),
|
error: (error, _) => const Icon(Icons.error),
|
||||||
),
|
),
|
||||||
|
|
@ -259,11 +245,7 @@ class BookSearchResultMini extends HookConsumerWidget {
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
metadata.authors
|
metadata.authors.map((author) => author.name).join(', '),
|
||||||
.map(
|
|
||||||
(author) => author.name,
|
|
||||||
)
|
|
||||||
.join(', '),
|
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
// navigate to the book details page
|
// navigate to the book details page
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,7 @@ import 'package:vaani/features/explore/providers/search_result_provider.dart';
|
||||||
import 'package:vaani/features/explore/view/explore_page.dart';
|
import 'package:vaani/features/explore/view/explore_page.dart';
|
||||||
import 'package:vaani/shared/extensions/model_conversions.dart';
|
import 'package:vaani/shared/extensions/model_conversions.dart';
|
||||||
|
|
||||||
enum SearchResultCategory {
|
enum SearchResultCategory { books, authors, series, tags, narrators }
|
||||||
books,
|
|
||||||
authors,
|
|
||||||
series,
|
|
||||||
tags,
|
|
||||||
narrators,
|
|
||||||
}
|
|
||||||
|
|
||||||
class SearchResultPage extends HookConsumerWidget {
|
class SearchResultPage extends HookConsumerWidget {
|
||||||
const SearchResultPage({
|
const SearchResultPage({
|
||||||
|
|
@ -41,9 +35,7 @@ class SearchResultPage extends HookConsumerWidget {
|
||||||
body: results.when(
|
body: results.when(
|
||||||
data: (options) {
|
data: (options) {
|
||||||
if (options == null) {
|
if (options == null) {
|
||||||
return Container(
|
return Container(child: const Text('No data found'));
|
||||||
child: const Text('No data found'),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (options is BookLibrarySearchResponse) {
|
if (options is BookLibrarySearchResponse) {
|
||||||
if (category == null) {
|
if (category == null) {
|
||||||
|
|
@ -51,18 +43,15 @@ class SearchResultPage extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
return switch (category!) {
|
return switch (category!) {
|
||||||
SearchResultCategory.books => ListView.builder(
|
SearchResultCategory.books => ListView.builder(
|
||||||
itemCount: options.book.length,
|
itemCount: options.book.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final book =
|
final book =
|
||||||
options.book[index].libraryItem.media.asBookExpanded;
|
options.book[index].libraryItem.media.asBookExpanded;
|
||||||
final metadata = book.metadata.asBookMetadataExpanded;
|
final metadata = book.metadata.asBookMetadataExpanded;
|
||||||
|
|
||||||
return BookSearchResultMini(
|
return BookSearchResultMini(book: book, metadata: metadata);
|
||||||
book: book,
|
},
|
||||||
metadata: metadata,
|
),
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
SearchResultCategory.authors => Container(),
|
SearchResultCategory.authors => Container(),
|
||||||
SearchResultCategory.series => Container(),
|
SearchResultCategory.series => Container(),
|
||||||
SearchResultCategory.tags => Container(),
|
SearchResultCategory.tags => Container(),
|
||||||
|
|
@ -71,12 +60,8 @@ class SearchResultPage extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
loading: () => const Center(
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
child: CircularProgressIndicator(),
|
error: (error, stackTrace) => Center(child: Text('Error: $error')),
|
||||||
),
|
|
||||||
error: (error, stackTrace) => Center(
|
|
||||||
child: Text('Error: $error'),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,16 +26,13 @@ import 'package:vaani/shared/extensions/model_conversions.dart';
|
||||||
import 'package:vaani/shared/utils.dart';
|
import 'package:vaani/shared/utils.dart';
|
||||||
|
|
||||||
class LibraryItemActions extends HookConsumerWidget {
|
class LibraryItemActions extends HookConsumerWidget {
|
||||||
const LibraryItemActions({
|
const LibraryItemActions({super.key, required this.id});
|
||||||
super.key,
|
|
||||||
required this.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
final String id;
|
final String id;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final item = ref.watch(libraryItemProvider(id)).valueOrNull;
|
final item = ref.watch(libraryItemProvider(id)).value;
|
||||||
if (item == null) {
|
if (item == null) {
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
|
|
@ -68,9 +65,7 @@ class LibraryItemActions extends HookConsumerWidget {
|
||||||
// read list button
|
// read list button
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {},
|
onPressed: () {},
|
||||||
icon: const Icon(
|
icon: const Icon(Icons.playlist_add_rounded),
|
||||||
Icons.playlist_add_rounded,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
// share button
|
// share button
|
||||||
IconButton(
|
IconButton(
|
||||||
|
|
@ -79,8 +74,9 @@ class LibraryItemActions extends HookConsumerWidget {
|
||||||
var currentServerUrl =
|
var currentServerUrl =
|
||||||
apiSettings.activeServer!.serverUrl;
|
apiSettings.activeServer!.serverUrl;
|
||||||
if (!currentServerUrl.hasScheme) {
|
if (!currentServerUrl.hasScheme) {
|
||||||
currentServerUrl =
|
currentServerUrl = Uri.https(
|
||||||
Uri.https(currentServerUrl.toString());
|
currentServerUrl.toString(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
handleLaunchUrl(
|
handleLaunchUrl(
|
||||||
Uri.parse(
|
Uri.parse(
|
||||||
|
|
@ -140,7 +136,8 @@ class LibraryItemActions extends HookConsumerWidget {
|
||||||
.database
|
.database
|
||||||
.deleteRecordWithId(
|
.deleteRecordWithId(
|
||||||
record
|
record
|
||||||
.task.taskId,
|
.task
|
||||||
|
.taskId,
|
||||||
);
|
);
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
|
|
@ -161,8 +158,8 @@ class LibraryItemActions extends HookConsumerWidget {
|
||||||
// open the file location
|
// open the file location
|
||||||
final didOpen =
|
final didOpen =
|
||||||
await FileDownloader().openFile(
|
await FileDownloader().openFile(
|
||||||
task: record.task,
|
task: record.task,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!didOpen) {
|
if (!didOpen) {
|
||||||
appLogger.warning(
|
appLogger.warning(
|
||||||
|
|
@ -182,16 +179,13 @@ class LibraryItemActions extends HookConsumerWidget {
|
||||||
loading: () => const Center(
|
loading: () => const Center(
|
||||||
child: CircularProgressIndicator(),
|
child: CircularProgressIndicator(),
|
||||||
),
|
),
|
||||||
error: (error, stackTrace) => Center(
|
error: (error, stackTrace) =>
|
||||||
child: Text('Error: $error'),
|
Center(child: Text('Error: $error')),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
icon: const Icon(
|
icon: const Icon(Icons.more_vert_rounded),
|
||||||
Icons.more_vert_rounded,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -206,25 +200,20 @@ class LibraryItemActions extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class LibItemDownloadButton extends HookConsumerWidget {
|
class LibItemDownloadButton extends HookConsumerWidget {
|
||||||
const LibItemDownloadButton({
|
const LibItemDownloadButton({super.key, required this.item});
|
||||||
super.key,
|
|
||||||
required this.item,
|
|
||||||
});
|
|
||||||
|
|
||||||
final shelfsdk.LibraryItemExpanded item;
|
final shelfsdk.LibraryItemExpanded item;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final isItemDownloaded = ref.watch(isItemDownloadedProvider(item));
|
final isItemDownloaded = ref.watch(isItemDownloadedProvider(item));
|
||||||
if (isItemDownloaded.valueOrNull ?? false) {
|
if (isItemDownloaded.value ?? false) {
|
||||||
return AlreadyItemDownloadedButton(item: item);
|
return AlreadyItemDownloadedButton(item: item);
|
||||||
}
|
}
|
||||||
final isItemDownloading = ref.watch(isItemDownloadingProvider(item.id));
|
final isItemDownloading = ref.watch(isItemDownloadingProvider(item.id));
|
||||||
|
|
||||||
return isItemDownloading
|
return isItemDownloading
|
||||||
? ItemCurrentlyInDownloadQueue(
|
? ItemCurrentlyInDownloadQueue(item: item)
|
||||||
item: item,
|
|
||||||
)
|
|
||||||
: IconButton(
|
: IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
appLogger.fine('Pressed download button');
|
appLogger.fine('Pressed download button');
|
||||||
|
|
@ -233,18 +222,13 @@ class LibItemDownloadButton extends HookConsumerWidget {
|
||||||
.read(downloadManagerProvider.notifier)
|
.read(downloadManagerProvider.notifier)
|
||||||
.queueAudioBookDownload(item);
|
.queueAudioBookDownload(item);
|
||||||
},
|
},
|
||||||
icon: const Icon(
|
icon: const Icon(Icons.download_rounded),
|
||||||
Icons.download_rounded,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ItemCurrentlyInDownloadQueue extends HookConsumerWidget {
|
class ItemCurrentlyInDownloadQueue extends HookConsumerWidget {
|
||||||
const ItemCurrentlyInDownloadQueue({
|
const ItemCurrentlyInDownloadQueue({super.key, required this.item});
|
||||||
super.key,
|
|
||||||
required this.item,
|
|
||||||
});
|
|
||||||
|
|
||||||
final shelfsdk.LibraryItemExpanded item;
|
final shelfsdk.LibraryItemExpanded item;
|
||||||
|
|
||||||
|
|
@ -252,7 +236,7 @@ class ItemCurrentlyInDownloadQueue extends HookConsumerWidget {
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final progress = ref
|
final progress = ref
|
||||||
.watch(itemDownloadProgressProvider(item.id))
|
.watch(itemDownloadProgressProvider(item.id))
|
||||||
.valueOrNull
|
.value
|
||||||
?.clamp(0.05, 1.0);
|
?.clamp(0.05, 1.0);
|
||||||
|
|
||||||
if (progress == 1) {
|
if (progress == 1) {
|
||||||
|
|
@ -263,17 +247,12 @@ class ItemCurrentlyInDownloadQueue extends HookConsumerWidget {
|
||||||
return Stack(
|
return Stack(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
children: [
|
children: [
|
||||||
CircularProgressIndicator(
|
CircularProgressIndicator(value: progress, strokeWidth: 2),
|
||||||
value: progress,
|
|
||||||
strokeWidth: 2,
|
|
||||||
),
|
|
||||||
const Icon(
|
const Icon(
|
||||||
Icons.download,
|
Icons.download,
|
||||||
// color: Theme.of(context).progressIndicatorTheme.color,
|
// color: Theme.of(context).progressIndicatorTheme.color,
|
||||||
)
|
|
||||||
.animate(
|
|
||||||
onPlay: (controller) => controller.repeat(),
|
|
||||||
)
|
)
|
||||||
|
.animate(onPlay: (controller) => controller.repeat())
|
||||||
.fade(
|
.fade(
|
||||||
duration: shimmerDuration,
|
duration: shimmerDuration,
|
||||||
end: 1,
|
end: 1,
|
||||||
|
|
@ -292,10 +271,7 @@ class ItemCurrentlyInDownloadQueue extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class AlreadyItemDownloadedButton extends HookConsumerWidget {
|
class AlreadyItemDownloadedButton extends HookConsumerWidget {
|
||||||
const AlreadyItemDownloadedButton({
|
const AlreadyItemDownloadedButton({super.key, required this.item});
|
||||||
super.key,
|
|
||||||
required this.item,
|
|
||||||
});
|
|
||||||
|
|
||||||
final shelfsdk.LibraryItemExpanded item;
|
final shelfsdk.LibraryItemExpanded item;
|
||||||
|
|
||||||
|
|
@ -317,25 +293,18 @@ class AlreadyItemDownloadedButton extends HookConsumerWidget {
|
||||||
top: 8.0,
|
top: 8.0,
|
||||||
bottom: (isBookPlaying ? playerMinHeight : 0) + 8,
|
bottom: (isBookPlaying ? playerMinHeight : 0) + 8,
|
||||||
),
|
),
|
||||||
child: DownloadSheet(
|
child: DownloadSheet(item: item),
|
||||||
item: item,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
icon: const Icon(
|
icon: const Icon(Icons.download_done_rounded),
|
||||||
Icons.download_done_rounded,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DownloadSheet extends HookConsumerWidget {
|
class DownloadSheet extends HookConsumerWidget {
|
||||||
const DownloadSheet({
|
const DownloadSheet({super.key, required this.item});
|
||||||
super.key,
|
|
||||||
required this.item,
|
|
||||||
});
|
|
||||||
|
|
||||||
final shelfsdk.LibraryItemExpanded item;
|
final shelfsdk.LibraryItemExpanded item;
|
||||||
|
|
||||||
|
|
@ -367,9 +336,7 @@ class DownloadSheet extends HookConsumerWidget {
|
||||||
// ),
|
// ),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('Delete'),
|
title: const Text('Delete'),
|
||||||
leading: const Icon(
|
leading: const Icon(Icons.delete_rounded),
|
||||||
Icons.delete_rounded,
|
|
||||||
),
|
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
// show the delete dialog
|
// show the delete dialog
|
||||||
final wasDeleted = await showDialog<bool>(
|
final wasDeleted = await showDialog<bool>(
|
||||||
|
|
@ -387,9 +354,7 @@ class DownloadSheet extends HookConsumerWidget {
|
||||||
// delete the file
|
// delete the file
|
||||||
ref
|
ref
|
||||||
.read(downloadManagerProvider.notifier)
|
.read(downloadManagerProvider.notifier)
|
||||||
.deleteDownloadedItem(
|
.deleteDownloadedItem(item);
|
||||||
item,
|
|
||||||
);
|
|
||||||
GoRouter.of(context).pop(true);
|
GoRouter.of(context).pop(true);
|
||||||
},
|
},
|
||||||
child: const Text('Yes'),
|
child: const Text('Yes'),
|
||||||
|
|
@ -409,11 +374,7 @@ class DownloadSheet extends HookConsumerWidget {
|
||||||
appLogger.fine('Deleted ${item.media.metadata.title}');
|
appLogger.fine('Deleted ${item.media.metadata.title}');
|
||||||
GoRouter.of(context).pop();
|
GoRouter.of(context).pop();
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(content: Text('Deleted ${item.media.metadata.title}')),
|
||||||
content: Text(
|
|
||||||
'Deleted ${item.media.metadata.title}',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -424,9 +385,7 @@ class DownloadSheet extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _LibraryItemPlayButton extends HookConsumerWidget {
|
class _LibraryItemPlayButton extends HookConsumerWidget {
|
||||||
const _LibraryItemPlayButton({
|
const _LibraryItemPlayButton({required this.item});
|
||||||
required this.item,
|
|
||||||
});
|
|
||||||
|
|
||||||
final shelfsdk.LibraryItemExpanded item;
|
final shelfsdk.LibraryItemExpanded item;
|
||||||
|
|
||||||
|
|
@ -477,9 +436,7 @@ class _LibraryItemPlayButton extends HookConsumerWidget {
|
||||||
),
|
),
|
||||||
label: Text(getPlayDisplayText()),
|
label: Text(getPlayDisplayText()),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)),
|
||||||
borderRadius: BorderRadius.circular(4),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -502,11 +459,11 @@ class DynamicItemPlayIcon extends StatelessWidget {
|
||||||
return Icon(
|
return Icon(
|
||||||
isCurrentBookSetInPlayer
|
isCurrentBookSetInPlayer
|
||||||
? isPlayingThisBook
|
? isPlayingThisBook
|
||||||
? Icons.pause_rounded
|
? Icons.pause_rounded
|
||||||
: Icons.play_arrow_rounded
|
: Icons.play_arrow_rounded
|
||||||
: isBookCompleted
|
: isBookCompleted
|
||||||
? Icons.replay_rounded
|
? Icons.replay_rounded
|
||||||
: Icons.play_arrow_rounded,
|
: Icons.play_arrow_rounded,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -529,8 +486,9 @@ Future<void> libraryItemPlayButtonOnPressed({
|
||||||
appLogger.info('Setting the book ${book.libraryItemId}');
|
appLogger.info('Setting the book ${book.libraryItemId}');
|
||||||
appLogger.info('Initial position: ${userMediaProgress?.currentTime}');
|
appLogger.info('Initial position: ${userMediaProgress?.currentTime}');
|
||||||
final downloadManager = ref.watch(simpleDownloadManagerProvider);
|
final downloadManager = ref.watch(simpleDownloadManagerProvider);
|
||||||
final libItem =
|
final libItem = await ref.read(
|
||||||
await ref.read(libraryItemProvider(book.libraryItemId).future);
|
libraryItemProvider(book.libraryItemId).future,
|
||||||
|
);
|
||||||
final downloadedUris = await downloadManager.getDownloadedFilesUri(libItem);
|
final downloadedUris = await downloadManager.getDownloadedFilesUri(libItem);
|
||||||
setSourceFuture = player.setSourceAudiobook(
|
setSourceFuture = player.setSourceAudiobook(
|
||||||
book,
|
book,
|
||||||
|
|
@ -546,8 +504,9 @@ Future<void> libraryItemPlayButtonOnPressed({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// set the volume as this is the first time playing and dismissing causes the volume to go to 0
|
// set the volume as this is the first time playing and dismissing causes the volume to go to 0
|
||||||
var bookPlayerSettings =
|
var bookPlayerSettings = ref
|
||||||
ref.read(bookSettingsProvider(book.libraryItemId)).playerSettings;
|
.read(bookSettingsProvider(book.libraryItemId))
|
||||||
|
.playerSettings;
|
||||||
var appPlayerSettings = ref.read(appSettingsProvider).playerSettings;
|
var appPlayerSettings = ref.read(appSettingsProvider).playerSettings;
|
||||||
|
|
||||||
var configurePlayerForEveryBook =
|
var configurePlayerForEveryBook =
|
||||||
|
|
@ -559,14 +518,14 @@ Future<void> libraryItemPlayButtonOnPressed({
|
||||||
player.setVolume(
|
player.setVolume(
|
||||||
configurePlayerForEveryBook
|
configurePlayerForEveryBook
|
||||||
? bookPlayerSettings.preferredDefaultVolume ??
|
? bookPlayerSettings.preferredDefaultVolume ??
|
||||||
appPlayerSettings.preferredDefaultVolume
|
appPlayerSettings.preferredDefaultVolume
|
||||||
: appPlayerSettings.preferredDefaultVolume,
|
: appPlayerSettings.preferredDefaultVolume,
|
||||||
),
|
),
|
||||||
// set the speed
|
// set the speed
|
||||||
player.setSpeed(
|
player.setSpeed(
|
||||||
configurePlayerForEveryBook
|
configurePlayerForEveryBook
|
||||||
? bookPlayerSettings.preferredDefaultSpeed ??
|
? bookPlayerSettings.preferredDefaultSpeed ??
|
||||||
appPlayerSettings.preferredDefaultSpeed
|
appPlayerSettings.preferredDefaultSpeed
|
||||||
: appPlayerSettings.preferredDefaultSpeed,
|
: appPlayerSettings.preferredDefaultSpeed,
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -42,14 +42,13 @@ class LibraryItemHeroSection extends HookConsumerWidget {
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Hero(
|
Hero(
|
||||||
tag: HeroTagPrefixes.bookCover +
|
tag:
|
||||||
|
HeroTagPrefixes.bookCover +
|
||||||
itemId +
|
itemId +
|
||||||
(extraMap?.heroTagSuffix ?? ''),
|
(extraMap?.heroTagSuffix ?? ''),
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
child: _BookCover(
|
child: _BookCover(itemId: itemId),
|
||||||
itemId: itemId,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// a progress bar
|
// a progress bar
|
||||||
|
|
@ -59,9 +58,7 @@ class LibraryItemHeroSection extends HookConsumerWidget {
|
||||||
right: 8.0,
|
right: 8.0,
|
||||||
left: 8.0,
|
left: 8.0,
|
||||||
),
|
),
|
||||||
child: _LibraryItemProgressIndicator(
|
child: _LibraryItemProgressIndicator(id: itemId),
|
||||||
id: itemId,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -77,10 +74,7 @@ class LibraryItemHeroSection extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _BookDetails extends HookConsumerWidget {
|
class _BookDetails extends HookConsumerWidget {
|
||||||
const _BookDetails({
|
const _BookDetails({required this.id, this.extraMap});
|
||||||
required this.id,
|
|
||||||
this.extraMap,
|
|
||||||
});
|
|
||||||
|
|
||||||
final String id;
|
final String id;
|
||||||
final LibraryItemExtras? extraMap;
|
final LibraryItemExtras? extraMap;
|
||||||
|
|
@ -90,7 +84,7 @@ class _BookDetails extends HookConsumerWidget {
|
||||||
final itemFromApi = ref.watch(libraryItemProvider(id));
|
final itemFromApi = ref.watch(libraryItemProvider(id));
|
||||||
|
|
||||||
final itemBookMetadata =
|
final itemBookMetadata =
|
||||||
itemFromApi.valueOrNull?.media.metadata.asBookMetadataExpanded;
|
itemFromApi.value?.media.metadata.asBookMetadataExpanded;
|
||||||
|
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
|
|
@ -99,10 +93,7 @@ class _BookDetails extends HookConsumerWidget {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
_BookTitle(
|
_BookTitle(extraMap: extraMap, itemBookMetadata: itemBookMetadata),
|
||||||
extraMap: extraMap,
|
|
||||||
itemBookMetadata: itemBookMetadata,
|
|
||||||
),
|
|
||||||
Container(
|
Container(
|
||||||
margin: const EdgeInsets.symmetric(vertical: 16),
|
margin: const EdgeInsets.symmetric(vertical: 16),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
|
@ -134,16 +125,14 @@ class _BookDetails extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _LibraryItemProgressIndicator extends HookConsumerWidget {
|
class _LibraryItemProgressIndicator extends HookConsumerWidget {
|
||||||
const _LibraryItemProgressIndicator({
|
const _LibraryItemProgressIndicator({required this.id});
|
||||||
required this.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
final String id;
|
final String id;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final player = ref.watch(audiobookPlayerProvider);
|
final player = ref.watch(audiobookPlayerProvider);
|
||||||
final libraryItem = ref.watch(libraryItemProvider(id)).valueOrNull;
|
final libraryItem = ref.watch(libraryItemProvider(id)).value;
|
||||||
if (libraryItem == null) {
|
if (libraryItem == null) {
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
|
|
@ -157,13 +146,15 @@ class _LibraryItemProgressIndicator extends HookConsumerWidget {
|
||||||
Duration remainingTime;
|
Duration remainingTime;
|
||||||
if (player.book?.libraryItemId == libraryItem.id) {
|
if (player.book?.libraryItemId == libraryItem.id) {
|
||||||
// final positionStream = useStream(player.slowPositionStream);
|
// final positionStream = useStream(player.slowPositionStream);
|
||||||
progress = (player.positionInBook).inSeconds /
|
progress =
|
||||||
|
(player.positionInBook).inSeconds /
|
||||||
libraryItem.media.asBookExpanded.duration.inSeconds;
|
libraryItem.media.asBookExpanded.duration.inSeconds;
|
||||||
remainingTime =
|
remainingTime =
|
||||||
libraryItem.media.asBookExpanded.duration - player.positionInBook;
|
libraryItem.media.asBookExpanded.duration - player.positionInBook;
|
||||||
} else {
|
} else {
|
||||||
progress = mediaProgress?.progress ?? 0;
|
progress = mediaProgress?.progress ?? 0;
|
||||||
remainingTime = (libraryItem.media.asBookExpanded.duration -
|
remainingTime =
|
||||||
|
(libraryItem.media.asBookExpanded.duration -
|
||||||
mediaProgress!.currentTime);
|
mediaProgress!.currentTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -190,20 +181,17 @@ class _LibraryItemProgressIndicator extends HookConsumerWidget {
|
||||||
semanticsLabel: 'Book progress',
|
semanticsLabel: 'Book progress',
|
||||||
semanticsValue: '${progressInPercent.toStringAsFixed(2)}%',
|
semanticsValue: '${progressInPercent.toStringAsFixed(2)}%',
|
||||||
),
|
),
|
||||||
const SizedBox.square(
|
const SizedBox.square(dimension: 4.0),
|
||||||
dimension: 4.0,
|
|
||||||
),
|
|
||||||
// time remaining
|
// time remaining
|
||||||
Text(
|
Text(
|
||||||
// only show 2 decimal places
|
// only show 2 decimal places
|
||||||
'${remainingTime.smartBinaryFormat} left',
|
'${remainingTime.smartBinaryFormat} left',
|
||||||
|
|
||||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||||
color: Theme.of(context)
|
color: Theme.of(
|
||||||
.colorScheme
|
context,
|
||||||
.onSurface
|
).colorScheme.onSurface.withValues(alpha: 0.75),
|
||||||
.withValues(alpha: 0.75),
|
),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -212,10 +200,7 @@ class _LibraryItemProgressIndicator extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _HeroSectionSubLabelWithIcon extends HookConsumerWidget {
|
class _HeroSectionSubLabelWithIcon extends HookConsumerWidget {
|
||||||
const _HeroSectionSubLabelWithIcon({
|
const _HeroSectionSubLabelWithIcon({required this.icon, required this.text});
|
||||||
required this.icon,
|
|
||||||
required this.text,
|
|
||||||
});
|
|
||||||
|
|
||||||
final IconData icon;
|
final IconData icon;
|
||||||
final Widget text;
|
final Widget text;
|
||||||
|
|
@ -225,8 +210,10 @@ class _HeroSectionSubLabelWithIcon extends HookConsumerWidget {
|
||||||
final themeData = Theme.of(context);
|
final themeData = Theme.of(context);
|
||||||
final useFontAwesome =
|
final useFontAwesome =
|
||||||
icon.runtimeType == FontAwesomeIcons.book.runtimeType;
|
icon.runtimeType == FontAwesomeIcons.book.runtimeType;
|
||||||
final useMaterialThemeOnItemPage =
|
final useMaterialThemeOnItemPage = ref
|
||||||
ref.watch(appSettingsProvider).themeSettings.useMaterialThemeOnItemPage;
|
.watch(appSettingsProvider)
|
||||||
|
.themeSettings
|
||||||
|
.useMaterialThemeOnItemPage;
|
||||||
final color = useMaterialThemeOnItemPage
|
final color = useMaterialThemeOnItemPage
|
||||||
? themeData.colorScheme.primary
|
? themeData.colorScheme.primary
|
||||||
: themeData.colorScheme.onSurface.withValues(alpha: 0.75);
|
: themeData.colorScheme.onSurface.withValues(alpha: 0.75);
|
||||||
|
|
@ -237,20 +224,10 @@ class _HeroSectionSubLabelWithIcon extends HookConsumerWidget {
|
||||||
Container(
|
Container(
|
||||||
margin: const EdgeInsets.only(right: 8, top: 2),
|
margin: const EdgeInsets.only(right: 8, top: 2),
|
||||||
child: useFontAwesome
|
child: useFontAwesome
|
||||||
? FaIcon(
|
? FaIcon(icon, size: 16, color: color)
|
||||||
icon,
|
: Icon(icon, size: 16, color: color),
|
||||||
size: 16,
|
|
||||||
color: color,
|
|
||||||
)
|
|
||||||
: Icon(
|
|
||||||
icon,
|
|
||||||
size: 16,
|
|
||||||
color: color,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: text,
|
|
||||||
),
|
),
|
||||||
|
Expanded(child: text),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
@ -338,9 +315,7 @@ class _BookNarrators extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _BookCover extends HookConsumerWidget {
|
class _BookCover extends HookConsumerWidget {
|
||||||
const _BookCover({
|
const _BookCover({required this.itemId});
|
||||||
required this.itemId,
|
|
||||||
});
|
|
||||||
|
|
||||||
final String itemId;
|
final String itemId;
|
||||||
|
|
||||||
|
|
@ -358,11 +333,12 @@ class _BookCover extends HookConsumerWidget {
|
||||||
themeOfLibraryItemProvider(
|
themeOfLibraryItemProvider(
|
||||||
itemId,
|
itemId,
|
||||||
brightness: Theme.of(context).brightness,
|
brightness: Theme.of(context).brightness,
|
||||||
highContrast: themeSettings.highContrast ||
|
highContrast:
|
||||||
|
themeSettings.highContrast ||
|
||||||
MediaQuery.of(context).highContrast,
|
MediaQuery.of(context).highContrast,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.valueOrNull;
|
.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ThemeSwitcher(
|
return ThemeSwitcher(
|
||||||
|
|
@ -391,15 +367,10 @@ class _BookCover extends HookConsumerWidget {
|
||||||
return const Icon(Icons.error);
|
return const Icon(Icons.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Image.memory(
|
return Image.memory(image, fit: BoxFit.cover);
|
||||||
image,
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
loading: () {
|
loading: () {
|
||||||
return const Center(
|
return const Center(child: BookCoverSkeleton());
|
||||||
child: BookCoverSkeleton(),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
error: (error, stack) {
|
error: (error, stack) {
|
||||||
return const Center(child: Icon(Icons.error));
|
return const Center(child: Icon(Icons.error));
|
||||||
|
|
@ -411,10 +382,7 @@ class _BookCover extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _BookTitle extends StatelessWidget {
|
class _BookTitle extends StatelessWidget {
|
||||||
const _BookTitle({
|
const _BookTitle({required this.extraMap, required this.itemBookMetadata});
|
||||||
required this.extraMap,
|
|
||||||
required this.itemBookMetadata,
|
|
||||||
});
|
|
||||||
|
|
||||||
final LibraryItemExtras? extraMap;
|
final LibraryItemExtras? extraMap;
|
||||||
final shelfsdk.BookMetadataExpanded? itemBookMetadata;
|
final shelfsdk.BookMetadataExpanded? itemBookMetadata;
|
||||||
|
|
@ -426,7 +394,8 @@ class _BookTitle extends StatelessWidget {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Hero(
|
Hero(
|
||||||
tag: HeroTagPrefixes.bookTitle +
|
tag:
|
||||||
|
HeroTagPrefixes.bookTitle +
|
||||||
// itemId +
|
// itemId +
|
||||||
(extraMap?.heroTagSuffix ?? ''),
|
(extraMap?.heroTagSuffix ?? ''),
|
||||||
child: Text(
|
child: Text(
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,13 @@ import 'package:vaani/api/library_item_provider.dart';
|
||||||
import 'package:vaani/shared/extensions/model_conversions.dart';
|
import 'package:vaani/shared/extensions/model_conversions.dart';
|
||||||
|
|
||||||
class LibraryItemMetadata extends HookConsumerWidget {
|
class LibraryItemMetadata extends HookConsumerWidget {
|
||||||
const LibraryItemMetadata({
|
const LibraryItemMetadata({super.key, required this.id});
|
||||||
super.key,
|
|
||||||
required this.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
final String id;
|
final String id;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final item = ref.watch(libraryItemProvider(id)).valueOrNull;
|
final item = ref.watch(libraryItemProvider(id)).value;
|
||||||
|
|
||||||
/// formats the duration of the book as `10h 30m`
|
/// formats the duration of the book as `10h 30m`
|
||||||
///
|
///
|
||||||
|
|
@ -72,7 +69,8 @@ class LibraryItemMetadata extends HookConsumerWidget {
|
||||||
),
|
),
|
||||||
_MetadataItem(
|
_MetadataItem(
|
||||||
title: 'Published',
|
title: 'Published',
|
||||||
value: itemBookMetadata?.publishedDate ??
|
value:
|
||||||
|
itemBookMetadata?.publishedDate ??
|
||||||
itemBookMetadata?.publishedYear ??
|
itemBookMetadata?.publishedYear ??
|
||||||
'Unknown',
|
'Unknown',
|
||||||
),
|
),
|
||||||
|
|
@ -87,22 +85,18 @@ class LibraryItemMetadata extends HookConsumerWidget {
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
// alternate between metadata and vertical divider
|
// alternate between metadata and vertical divider
|
||||||
children: List.generate(
|
children: List.generate(children.length * 2 - 1, (index) {
|
||||||
children.length * 2 - 1,
|
if (index.isEven) {
|
||||||
(index) {
|
return children[index ~/ 2];
|
||||||
if (index.isEven) {
|
}
|
||||||
return children[index ~/ 2];
|
return VerticalDivider(
|
||||||
}
|
indent: 6,
|
||||||
return VerticalDivider(
|
endIndent: 6,
|
||||||
indent: 6,
|
color: Theme.of(
|
||||||
endIndent: 6,
|
context,
|
||||||
color: Theme.of(context)
|
).colorScheme.onSurface.withValues(alpha: 0.6),
|
||||||
.colorScheme
|
);
|
||||||
.onSurface
|
}),
|
||||||
.withValues(alpha: 0.6),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
@ -111,10 +105,7 @@ class LibraryItemMetadata extends HookConsumerWidget {
|
||||||
|
|
||||||
/// key-value pair to display as column
|
/// key-value pair to display as column
|
||||||
class _MetadataItem extends StatelessWidget {
|
class _MetadataItem extends StatelessWidget {
|
||||||
const _MetadataItem({
|
const _MetadataItem({required this.title, required this.value});
|
||||||
required this.title,
|
|
||||||
required this.value,
|
|
||||||
});
|
|
||||||
|
|
||||||
final String title;
|
final String title;
|
||||||
final String value;
|
final String value;
|
||||||
|
|
|
||||||
|
|
@ -16,49 +16,43 @@ import 'library_item_hero_section.dart';
|
||||||
import 'library_item_metadata.dart';
|
import 'library_item_metadata.dart';
|
||||||
|
|
||||||
class LibraryItemPage extends HookConsumerWidget {
|
class LibraryItemPage extends HookConsumerWidget {
|
||||||
const LibraryItemPage({
|
const LibraryItemPage({super.key, required this.itemId, this.extra});
|
||||||
super.key,
|
|
||||||
required this.itemId,
|
|
||||||
this.extra,
|
|
||||||
});
|
|
||||||
|
|
||||||
final String itemId;
|
final String itemId;
|
||||||
final Object? extra;
|
final Object? extra;
|
||||||
static const double _showFabThreshold = 300.0;
|
static const double _showFabThreshold = 300.0;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final additionalItemData =
|
final additionalItemData = extra is LibraryItemExtras
|
||||||
extra is LibraryItemExtras ? extra as LibraryItemExtras : null;
|
? extra as LibraryItemExtras
|
||||||
|
: null;
|
||||||
final scrollController = useScrollController();
|
final scrollController = useScrollController();
|
||||||
final showFab = useState(false);
|
final showFab = useState(false);
|
||||||
|
|
||||||
// Effect to listen to scroll changes and update FAB visibility
|
// Effect to listen to scroll changes and update FAB visibility
|
||||||
useEffect(
|
useEffect(() {
|
||||||
() {
|
void listener() {
|
||||||
void listener() {
|
if (!scrollController.hasClients) {
|
||||||
if (!scrollController.hasClients) {
|
return; // Ensure controller is attached
|
||||||
return; // Ensure controller is attached
|
|
||||||
}
|
|
||||||
final shouldShow = scrollController.offset > _showFabThreshold;
|
|
||||||
// Update state only if it changes and widget is still mounted
|
|
||||||
if (showFab.value != shouldShow && context.mounted) {
|
|
||||||
showFab.value = shouldShow;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
final shouldShow = scrollController.offset > _showFabThreshold;
|
||||||
|
// Update state only if it changes and widget is still mounted
|
||||||
|
if (showFab.value != shouldShow && context.mounted) {
|
||||||
|
showFab.value = shouldShow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
scrollController.addListener(listener);
|
scrollController.addListener(listener);
|
||||||
// Initial check in case the view starts scrolled (less likely but safe)
|
// Initial check in case the view starts scrolled (less likely but safe)
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
if (scrollController.hasClients && context.mounted) {
|
if (scrollController.hasClients && context.mounted) {
|
||||||
listener();
|
listener();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Cleanup: remove the listener when the widget is disposed
|
// Cleanup: remove the listener when the widget is disposed
|
||||||
return () => scrollController.removeListener(listener);
|
return () => scrollController.removeListener(listener);
|
||||||
},
|
}, [scrollController]); // Re-run effect if scrollController changes
|
||||||
[scrollController],
|
|
||||||
); // Re-run effect if scrollController changes
|
|
||||||
|
|
||||||
// --- FAB Scroll-to-Top Logic ---
|
// --- FAB Scroll-to-Top Logic ---
|
||||||
void scrollToTop() {
|
void scrollToTop() {
|
||||||
|
|
@ -82,10 +76,7 @@ class LibraryItemPage extends HookConsumerWidget {
|
||||||
transitionBuilder: (Widget child, Animation<double> animation) {
|
transitionBuilder: (Widget child, Animation<double> animation) {
|
||||||
return ScaleTransition(
|
return ScaleTransition(
|
||||||
scale: animation,
|
scale: animation,
|
||||||
child: FadeTransition(
|
child: FadeTransition(opacity: animation, child: child),
|
||||||
opacity: animation,
|
|
||||||
child: child,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: showFab.value
|
child: showFab.value
|
||||||
|
|
@ -96,9 +87,7 @@ class LibraryItemPage extends HookConsumerWidget {
|
||||||
tooltip: 'Scroll to top',
|
tooltip: 'Scroll to top',
|
||||||
child: const Icon(Icons.arrow_upward),
|
child: const Icon(Icons.arrow_upward),
|
||||||
)
|
)
|
||||||
: const SizedBox.shrink(
|
: const SizedBox.shrink(key: ValueKey('fab-empty')),
|
||||||
key: ValueKey('fab-empty'),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
body: CustomScrollView(
|
body: CustomScrollView(
|
||||||
controller: scrollController,
|
controller: scrollController,
|
||||||
|
|
@ -115,17 +104,11 @@ class LibraryItemPage extends HookConsumerWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// a horizontal display with dividers of metadata
|
// a horizontal display with dividers of metadata
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(child: LibraryItemMetadata(id: itemId)),
|
||||||
child: LibraryItemMetadata(id: itemId),
|
|
||||||
),
|
|
||||||
// a row of actions like play, download, share, etc
|
// a row of actions like play, download, share, etc
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(child: LibraryItemActions(id: itemId)),
|
||||||
child: LibraryItemActions(id: itemId),
|
|
||||||
),
|
|
||||||
// a expandable section for book description
|
// a expandable section for book description
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(child: LibraryItemDescription(id: itemId)),
|
||||||
child: LibraryItemDescription(id: itemId),
|
|
||||||
),
|
|
||||||
// a padding at the bottom to make sure the last item is not hidden by mini player
|
// a padding at the bottom to make sure the last item is not hidden by mini player
|
||||||
const SliverToBoxAdapter(child: MiniPlayerBottomPadding()),
|
const SliverToBoxAdapter(child: MiniPlayerBottomPadding()),
|
||||||
],
|
],
|
||||||
|
|
@ -137,15 +120,12 @@ class LibraryItemPage extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class LibraryItemDescription extends HookConsumerWidget {
|
class LibraryItemDescription extends HookConsumerWidget {
|
||||||
const LibraryItemDescription({
|
const LibraryItemDescription({super.key, required this.id});
|
||||||
super.key,
|
|
||||||
required this.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
final String id;
|
final String id;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final item = ref.watch(libraryItemProvider(id)).valueOrNull;
|
final item = ref.watch(libraryItemProvider(id)).value;
|
||||||
if (item == null) {
|
if (item == null) {
|
||||||
return const SizedBox();
|
return const SizedBox();
|
||||||
}
|
}
|
||||||
|
|
@ -160,16 +140,21 @@ class LibraryItemDescription extends HookConsumerWidget {
|
||||||
double calculateWidth(
|
double calculateWidth(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
BoxConstraints constraints, {
|
BoxConstraints constraints, {
|
||||||
|
|
||||||
/// width ratio of the cover image to the available width
|
/// width ratio of the cover image to the available width
|
||||||
double widthRatio = 0.4,
|
double widthRatio = 0.4,
|
||||||
|
|
||||||
/// height ratio of the cover image to the available height
|
/// height ratio of the cover image to the available height
|
||||||
double maxHeightToUse = 0.25,
|
double maxHeightToUse = 0.25,
|
||||||
}) {
|
}) {
|
||||||
final availHeight =
|
final availHeight = min(
|
||||||
min(constraints.maxHeight, MediaQuery.of(context).size.height);
|
constraints.maxHeight,
|
||||||
final availWidth =
|
MediaQuery.of(context).size.height,
|
||||||
min(constraints.maxWidth, MediaQuery.of(context).size.width);
|
);
|
||||||
|
final availWidth = min(
|
||||||
|
constraints.maxWidth,
|
||||||
|
MediaQuery.of(context).size.width,
|
||||||
|
);
|
||||||
|
|
||||||
// make the width widthRatio of the available width
|
// make the width widthRatio of the available width
|
||||||
var width = availWidth * widthRatio;
|
var width = availWidth * widthRatio;
|
||||||
|
|
|
||||||
|
|
@ -17,32 +17,30 @@ class LibraryItemSliverAppBar extends HookConsumerWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final item = ref.watch(libraryItemProvider(id)).valueOrNull;
|
final item = ref.watch(libraryItemProvider(id)).value;
|
||||||
|
|
||||||
final showTitle = useState(false);
|
final showTitle = useState(false);
|
||||||
|
|
||||||
useEffect(
|
useEffect(() {
|
||||||
() {
|
void listener() {
|
||||||
void listener() {
|
final shouldShow =
|
||||||
final shouldShow = scrollController.hasClients &&
|
scrollController.hasClients &&
|
||||||
scrollController.offset > _showTitleThreshold;
|
scrollController.offset > _showTitleThreshold;
|
||||||
if (showTitle.value != shouldShow) {
|
if (showTitle.value != shouldShow) {
|
||||||
showTitle.value = shouldShow;
|
showTitle.value = shouldShow;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
scrollController.addListener(listener);
|
scrollController.addListener(listener);
|
||||||
// Trigger listener once initially in case the view starts scrolled
|
// Trigger listener once initially in case the view starts scrolled
|
||||||
// (though unlikely for this specific use case, it's good practice)
|
// (though unlikely for this specific use case, it's good practice)
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
if (scrollController.hasClients) {
|
if (scrollController.hasClients) {
|
||||||
listener();
|
listener();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return () => scrollController.removeListener(listener);
|
return () => scrollController.removeListener(listener);
|
||||||
},
|
}, [scrollController]);
|
||||||
[scrollController],
|
|
||||||
);
|
|
||||||
|
|
||||||
return SliverAppBar(
|
return SliverAppBar(
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ class LibraryBrowserPage extends HookConsumerWidget {
|
||||||
const LibraryBrowserPage({super.key});
|
const LibraryBrowserPage({super.key});
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final currentLibrary = ref.watch(currentLibraryProvider).valueOrNull;
|
final currentLibrary = ref.watch(currentLibraryProvider).value;
|
||||||
|
|
||||||
// Determine the icon to use, with a fallback
|
// Determine the icon to use, with a fallback
|
||||||
final IconData libraryIconData =
|
final IconData libraryIconData =
|
||||||
|
|
@ -41,43 +41,41 @@ class LibraryBrowserPage extends HookConsumerWidget {
|
||||||
title: Text(appBarTitle),
|
title: Text(appBarTitle),
|
||||||
),
|
),
|
||||||
SliverList(
|
SliverList(
|
||||||
delegate: SliverChildListDelegate(
|
delegate: SliverChildListDelegate([
|
||||||
[
|
ListTile(
|
||||||
ListTile(
|
title: const Text('Authors'),
|
||||||
title: const Text('Authors'),
|
leading: const Icon(Icons.person),
|
||||||
leading: const Icon(Icons.person),
|
trailing: const Icon(Icons.chevron_right),
|
||||||
trailing: const Icon(Icons.chevron_right),
|
onTap: () {
|
||||||
onTap: () {
|
showNotImplementedToast(context);
|
||||||
showNotImplementedToast(context);
|
},
|
||||||
},
|
),
|
||||||
),
|
ListTile(
|
||||||
ListTile(
|
title: const Text('Genres'),
|
||||||
title: const Text('Genres'),
|
leading: const Icon(Icons.category),
|
||||||
leading: const Icon(Icons.category),
|
trailing: const Icon(Icons.chevron_right),
|
||||||
trailing: const Icon(Icons.chevron_right),
|
onTap: () {
|
||||||
onTap: () {
|
showNotImplementedToast(context);
|
||||||
showNotImplementedToast(context);
|
},
|
||||||
},
|
),
|
||||||
),
|
ListTile(
|
||||||
ListTile(
|
title: const Text('Series'),
|
||||||
title: const Text('Series'),
|
leading: const Icon(Icons.list),
|
||||||
leading: const Icon(Icons.list),
|
trailing: const Icon(Icons.chevron_right),
|
||||||
trailing: const Icon(Icons.chevron_right),
|
onTap: () {
|
||||||
onTap: () {
|
showNotImplementedToast(context);
|
||||||
showNotImplementedToast(context);
|
},
|
||||||
},
|
),
|
||||||
),
|
// Downloads
|
||||||
// Downloads
|
ListTile(
|
||||||
ListTile(
|
title: const Text('Downloads'),
|
||||||
title: const Text('Downloads'),
|
leading: const Icon(Icons.download),
|
||||||
leading: const Icon(Icons.download),
|
trailing: const Icon(Icons.chevron_right),
|
||||||
trailing: const Icon(Icons.chevron_right),
|
onTap: () {
|
||||||
onTap: () {
|
GoRouter.of(context).pushNamed(Routes.downloads.name);
|
||||||
GoRouter.of(context).pushNamed(Routes.downloads.name);
|
},
|
||||||
},
|
),
|
||||||
),
|
]),
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,10 @@ String generateZipFileName() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Level parseLevel(String level) {
|
Level parseLevel(String level) {
|
||||||
return Level.LEVELS
|
return Level.LEVELS.firstWhere(
|
||||||
.firstWhere((l) => l.name == level, orElse: () => Level.ALL);
|
(l) => l.name == level,
|
||||||
|
orElse: () => Level.ALL,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
LogRecord parseLogLine(String line) {
|
LogRecord parseLogLine(String line) {
|
||||||
|
|
|
||||||
|
|
@ -6,20 +6,48 @@ part of 'logs_provider.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint, type=warning
|
||||||
|
|
||||||
|
@ProviderFor(Logs)
|
||||||
|
final logsProvider = LogsProvider._();
|
||||||
|
|
||||||
|
final class LogsProvider extends $AsyncNotifierProvider<Logs, List<LogRecord>> {
|
||||||
|
LogsProvider._()
|
||||||
|
: super(
|
||||||
|
from: null,
|
||||||
|
argument: null,
|
||||||
|
retry: null,
|
||||||
|
name: r'logsProvider',
|
||||||
|
isAutoDispose: true,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$logsHash();
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
Logs create() => Logs();
|
||||||
|
}
|
||||||
|
|
||||||
String _$logsHash() => r'aa9d3d56586cba6ddf69615320ea605d071ea5e2';
|
String _$logsHash() => r'aa9d3d56586cba6ddf69615320ea605d071ea5e2';
|
||||||
|
|
||||||
/// See also [Logs].
|
abstract class _$Logs extends $AsyncNotifier<List<LogRecord>> {
|
||||||
@ProviderFor(Logs)
|
FutureOr<List<LogRecord>> build();
|
||||||
final logsProvider =
|
@$mustCallSuper
|
||||||
AutoDisposeAsyncNotifierProvider<Logs, List<LogRecord>>.internal(
|
@override
|
||||||
Logs.new,
|
void runBuild() {
|
||||||
name: r'logsProvider',
|
final ref = this.ref as $Ref<AsyncValue<List<LogRecord>>, List<LogRecord>>;
|
||||||
debugGetCreateSourceHash:
|
final element =
|
||||||
const bool.fromEnvironment('dart.vm.product') ? null : _$logsHash,
|
ref.element
|
||||||
dependencies: null,
|
as $ClassProviderElement<
|
||||||
allTransitiveDependencies: null,
|
AnyNotifier<AsyncValue<List<LogRecord>>, List<LogRecord>>,
|
||||||
);
|
AsyncValue<List<LogRecord>>,
|
||||||
|
Object?,
|
||||||
typedef _$Logs = AutoDisposeAsyncNotifier<List<LogRecord>>;
|
Object?
|
||||||
// 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
|
element.handleCreate(ref, build);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,8 +54,9 @@ class LogsPage extends HookConsumerWidget {
|
||||||
icon: const Icon(Icons.share),
|
icon: const Icon(Icons.share),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
appLogger.info('Preparing logs for sharing');
|
appLogger.info('Preparing logs for sharing');
|
||||||
final zipLogFilePath =
|
final zipLogFilePath = await ref
|
||||||
await ref.read(logsProvider.notifier).getZipFilePath();
|
.read(logsProvider.notifier)
|
||||||
|
.getZipFilePath();
|
||||||
|
|
||||||
// submit logs
|
// submit logs
|
||||||
final result = await Share.shareXFiles([XFile(zipLogFilePath)]);
|
final result = await Share.shareXFiles([XFile(zipLogFilePath)]);
|
||||||
|
|
@ -169,7 +170,6 @@ class LogsPage extends HookConsumerWidget {
|
||||||
children: [
|
children: [
|
||||||
// a filter for log levels, loggers, and search
|
// a filter for log levels, loggers, and search
|
||||||
// TODO: implement filters and search
|
// TODO: implement filters and search
|
||||||
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: logs.when(
|
child: logs.when(
|
||||||
data: (logRecords) {
|
data: (logRecords) {
|
||||||
|
|
@ -243,9 +243,7 @@ class LogRecordTile extends StatelessWidget {
|
||||||
style: const TextStyle(fontStyle: FontStyle.italic),
|
style: const TextStyle(fontStyle: FontStyle.italic),
|
||||||
),
|
),
|
||||||
const TextSpan(text: '\n\n'),
|
const TextSpan(text: '\n\n'),
|
||||||
TextSpan(
|
TextSpan(text: logRecord.message),
|
||||||
text: logRecord.message,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
part 'flow.freezed.dart';
|
part 'flow.freezed.dart';
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class Flow with _$Flow {
|
sealed class Flow with _$Flow {
|
||||||
const factory Flow({
|
const factory Flow({
|
||||||
required Uri serverUri,
|
required Uri serverUri,
|
||||||
required String state,
|
required String state,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// coverage:ignore-file
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// coverage:ignore-file
|
||||||
// ignore_for_file: type=lint
|
// 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
|
// 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
|
||||||
|
|
||||||
|
|
@ -9,241 +9,272 @@ part of 'flow.dart';
|
||||||
// FreezedGenerator
|
// FreezedGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
|
// dart format off
|
||||||
T _$identity<T>(T value) => value;
|
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#adding-getters-and-methods-to-our-models');
|
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$Flow {
|
mixin _$Flow {
|
||||||
Uri get serverUri => throw _privateConstructorUsedError;
|
|
||||||
String get state => throw _privateConstructorUsedError;
|
|
||||||
String get verifier => throw _privateConstructorUsedError;
|
|
||||||
Cookie get cookie => throw _privateConstructorUsedError;
|
|
||||||
bool get isFlowComplete => throw _privateConstructorUsedError;
|
|
||||||
String? get authToken => throw _privateConstructorUsedError;
|
|
||||||
|
|
||||||
/// Create a copy of Flow
|
Uri get serverUri; String get state; String get verifier; Cookie get cookie; bool get isFlowComplete; String? get authToken;
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// Create a copy of Flow
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
$FlowCopyWith<Flow> get copyWith => throw _privateConstructorUsedError;
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$FlowCopyWith<Flow> get copyWith => _$FlowCopyWithImpl<Flow>(this as Flow, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is Flow&&(identical(other.serverUri, serverUri) || other.serverUri == serverUri)&&(identical(other.state, state) || other.state == state)&&(identical(other.verifier, verifier) || other.verifier == verifier)&&(identical(other.cookie, cookie) || other.cookie == cookie)&&(identical(other.isFlowComplete, isFlowComplete) || other.isFlowComplete == isFlowComplete)&&(identical(other.authToken, authToken) || other.authToken == authToken));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,serverUri,state,verifier,cookie,isFlowComplete,authToken);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'Flow(serverUri: $serverUri, state: $state, verifier: $verifier, cookie: $cookie, isFlowComplete: $isFlowComplete, authToken: $authToken)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
abstract class $FlowCopyWith<$Res> {
|
abstract mixin class $FlowCopyWith<$Res> {
|
||||||
factory $FlowCopyWith(Flow value, $Res Function(Flow) then) =
|
factory $FlowCopyWith(Flow value, $Res Function(Flow) _then) = _$FlowCopyWithImpl;
|
||||||
_$FlowCopyWithImpl<$Res, Flow>;
|
@useResult
|
||||||
@useResult
|
$Res call({
|
||||||
$Res call(
|
Uri serverUri, String state, String verifier, Cookie cookie, bool isFlowComplete, String? authToken
|
||||||
{Uri serverUri,
|
});
|
||||||
String state,
|
|
||||||
String verifier,
|
|
||||||
Cookie cookie,
|
|
||||||
bool isFlowComplete,
|
|
||||||
String? authToken});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
class _$FlowCopyWithImpl<$Res, $Val extends Flow>
|
class _$FlowCopyWithImpl<$Res>
|
||||||
implements $FlowCopyWith<$Res> {
|
implements $FlowCopyWith<$Res> {
|
||||||
_$FlowCopyWithImpl(this._value, this._then);
|
_$FlowCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
// ignore: unused_field
|
final Flow _self;
|
||||||
final $Val _value;
|
final $Res Function(Flow) _then;
|
||||||
// ignore: unused_field
|
|
||||||
final $Res Function($Val) _then;
|
|
||||||
|
|
||||||
/// Create a copy of Flow
|
/// Create a copy of Flow
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline') @override $Res call({Object? serverUri = null,Object? state = null,Object? verifier = null,Object? cookie = null,Object? isFlowComplete = null,Object? authToken = freezed,}) {
|
||||||
@override
|
return _then(_self.copyWith(
|
||||||
$Res call({
|
serverUri: null == serverUri ? _self.serverUri : serverUri // ignore: cast_nullable_to_non_nullable
|
||||||
Object? serverUri = null,
|
as Uri,state: null == state ? _self.state : state // ignore: cast_nullable_to_non_nullable
|
||||||
Object? state = null,
|
as String,verifier: null == verifier ? _self.verifier : verifier // ignore: cast_nullable_to_non_nullable
|
||||||
Object? verifier = null,
|
as String,cookie: null == cookie ? _self.cookie : cookie // ignore: cast_nullable_to_non_nullable
|
||||||
Object? cookie = null,
|
as Cookie,isFlowComplete: null == isFlowComplete ? _self.isFlowComplete : isFlowComplete // ignore: cast_nullable_to_non_nullable
|
||||||
Object? isFlowComplete = null,
|
as bool,authToken: freezed == authToken ? _self.authToken : authToken // ignore: cast_nullable_to_non_nullable
|
||||||
Object? authToken = freezed,
|
as String?,
|
||||||
}) {
|
));
|
||||||
return _then(_value.copyWith(
|
|
||||||
serverUri: null == serverUri
|
|
||||||
? _value.serverUri
|
|
||||||
: serverUri // ignore: cast_nullable_to_non_nullable
|
|
||||||
as Uri,
|
|
||||||
state: null == state
|
|
||||||
? _value.state
|
|
||||||
: state // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
|
||||||
verifier: null == verifier
|
|
||||||
? _value.verifier
|
|
||||||
: verifier // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
|
||||||
cookie: null == cookie
|
|
||||||
? _value.cookie
|
|
||||||
: cookie // ignore: cast_nullable_to_non_nullable
|
|
||||||
as Cookie,
|
|
||||||
isFlowComplete: null == isFlowComplete
|
|
||||||
? _value.isFlowComplete
|
|
||||||
: isFlowComplete // ignore: cast_nullable_to_non_nullable
|
|
||||||
as bool,
|
|
||||||
authToken: freezed == authToken
|
|
||||||
? _value.authToken
|
|
||||||
: authToken // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String?,
|
|
||||||
) as $Val);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
abstract class _$$FlowImplCopyWith<$Res> implements $FlowCopyWith<$Res> {
|
|
||||||
factory _$$FlowImplCopyWith(
|
|
||||||
_$FlowImpl value, $Res Function(_$FlowImpl) then) =
|
|
||||||
__$$FlowImplCopyWithImpl<$Res>;
|
|
||||||
@override
|
|
||||||
@useResult
|
|
||||||
$Res call(
|
|
||||||
{Uri serverUri,
|
|
||||||
String state,
|
|
||||||
String verifier,
|
|
||||||
Cookie cookie,
|
|
||||||
bool isFlowComplete,
|
|
||||||
String? authToken});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
class __$$FlowImplCopyWithImpl<$Res>
|
|
||||||
extends _$FlowCopyWithImpl<$Res, _$FlowImpl>
|
|
||||||
implements _$$FlowImplCopyWith<$Res> {
|
|
||||||
__$$FlowImplCopyWithImpl(_$FlowImpl _value, $Res Function(_$FlowImpl) _then)
|
|
||||||
: super(_value, _then);
|
|
||||||
|
|
||||||
/// Create a copy of Flow
|
/// Adds pattern-matching-related methods to [Flow].
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
extension FlowPatterns on Flow {
|
||||||
@pragma('vm:prefer-inline')
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
@override
|
///
|
||||||
$Res call({
|
/// It is equivalent to doing:
|
||||||
Object? serverUri = null,
|
/// ```dart
|
||||||
Object? state = null,
|
/// switch (sealedClass) {
|
||||||
Object? verifier = null,
|
/// case final Subclass value:
|
||||||
Object? cookie = null,
|
/// return ...;
|
||||||
Object? isFlowComplete = null,
|
/// case _:
|
||||||
Object? authToken = freezed,
|
/// return orElse();
|
||||||
}) {
|
/// }
|
||||||
return _then(_$FlowImpl(
|
/// ```
|
||||||
serverUri: null == serverUri
|
|
||||||
? _value.serverUri
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _Flow value)? $default,{required TResult orElse(),}){
|
||||||
: serverUri // ignore: cast_nullable_to_non_nullable
|
final _that = this;
|
||||||
as Uri,
|
switch (_that) {
|
||||||
state: null == state
|
case _Flow() when $default != null:
|
||||||
? _value.state
|
return $default(_that);case _:
|
||||||
: state // ignore: cast_nullable_to_non_nullable
|
return orElse();
|
||||||
as String,
|
|
||||||
verifier: null == verifier
|
}
|
||||||
? _value.verifier
|
}
|
||||||
: verifier // ignore: cast_nullable_to_non_nullable
|
/// A `switch`-like method, using callbacks.
|
||||||
as String,
|
///
|
||||||
cookie: null == cookie
|
/// Callbacks receives the raw object, upcasted.
|
||||||
? _value.cookie
|
/// It is equivalent to doing:
|
||||||
: cookie // ignore: cast_nullable_to_non_nullable
|
/// ```dart
|
||||||
as Cookie,
|
/// switch (sealedClass) {
|
||||||
isFlowComplete: null == isFlowComplete
|
/// case final Subclass value:
|
||||||
? _value.isFlowComplete
|
/// return ...;
|
||||||
: isFlowComplete // ignore: cast_nullable_to_non_nullable
|
/// case final Subclass2 value:
|
||||||
as bool,
|
/// return ...;
|
||||||
authToken: freezed == authToken
|
/// }
|
||||||
? _value.authToken
|
/// ```
|
||||||
: authToken // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String?,
|
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _Flow value) $default,){
|
||||||
));
|
final _that = this;
|
||||||
}
|
switch (_that) {
|
||||||
|
case _Flow():
|
||||||
|
return $default(_that);}
|
||||||
|
}
|
||||||
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _Flow value)? $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _Flow() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to an `orElse` callback.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( Uri serverUri, String state, String verifier, Cookie cookie, bool isFlowComplete, String? authToken)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _Flow() when $default != null:
|
||||||
|
return $default(_that.serverUri,_that.state,_that.verifier,_that.cookie,_that.isFlowComplete,_that.authToken);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// As opposed to `map`, this offers destructuring.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case Subclass2(:final field2):
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( Uri serverUri, String state, String verifier, Cookie cookie, bool isFlowComplete, String? authToken) $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _Flow():
|
||||||
|
return $default(_that.serverUri,_that.state,_that.verifier,_that.cookie,_that.isFlowComplete,_that.authToken);}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to returning `null`
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( Uri serverUri, String state, String verifier, Cookie cookie, bool isFlowComplete, String? authToken)? $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _Flow() when $default != null:
|
||||||
|
return $default(_that.serverUri,_that.state,_that.verifier,_that.cookie,_that.isFlowComplete,_that.authToken);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
|
|
||||||
class _$FlowImpl implements _Flow {
|
|
||||||
const _$FlowImpl(
|
|
||||||
{required this.serverUri,
|
|
||||||
required this.state,
|
|
||||||
required this.verifier,
|
|
||||||
required this.cookie,
|
|
||||||
this.isFlowComplete = false,
|
|
||||||
this.authToken});
|
|
||||||
|
|
||||||
@override
|
class _Flow implements Flow {
|
||||||
final Uri serverUri;
|
const _Flow({required this.serverUri, required this.state, required this.verifier, required this.cookie, this.isFlowComplete = false, this.authToken});
|
||||||
@override
|
|
||||||
final String state;
|
|
||||||
@override
|
|
||||||
final String verifier;
|
|
||||||
@override
|
|
||||||
final Cookie cookie;
|
|
||||||
@override
|
|
||||||
@JsonKey()
|
|
||||||
final bool isFlowComplete;
|
|
||||||
@override
|
|
||||||
final String? authToken;
|
|
||||||
|
|
||||||
@override
|
@override final Uri serverUri;
|
||||||
String toString() {
|
@override final String state;
|
||||||
return 'Flow(serverUri: $serverUri, state: $state, verifier: $verifier, cookie: $cookie, isFlowComplete: $isFlowComplete, authToken: $authToken)';
|
@override final String verifier;
|
||||||
}
|
@override final Cookie cookie;
|
||||||
|
@override@JsonKey() final bool isFlowComplete;
|
||||||
|
@override final String? authToken;
|
||||||
|
|
||||||
@override
|
/// Create a copy of Flow
|
||||||
bool operator ==(Object other) {
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
return identical(this, other) ||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
(other.runtimeType == runtimeType &&
|
@pragma('vm:prefer-inline')
|
||||||
other is _$FlowImpl &&
|
_$FlowCopyWith<_Flow> get copyWith => __$FlowCopyWithImpl<_Flow>(this, _$identity);
|
||||||
(identical(other.serverUri, serverUri) ||
|
|
||||||
other.serverUri == serverUri) &&
|
|
||||||
(identical(other.state, state) || other.state == state) &&
|
|
||||||
(identical(other.verifier, verifier) ||
|
|
||||||
other.verifier == verifier) &&
|
|
||||||
(identical(other.cookie, cookie) || other.cookie == cookie) &&
|
|
||||||
(identical(other.isFlowComplete, isFlowComplete) ||
|
|
||||||
other.isFlowComplete == isFlowComplete) &&
|
|
||||||
(identical(other.authToken, authToken) ||
|
|
||||||
other.authToken == authToken));
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode => Object.hash(runtimeType, serverUri, state, verifier,
|
|
||||||
cookie, isFlowComplete, authToken);
|
|
||||||
|
|
||||||
/// Create a copy of Flow
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
@override
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
bool operator ==(Object other) {
|
||||||
@override
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Flow&&(identical(other.serverUri, serverUri) || other.serverUri == serverUri)&&(identical(other.state, state) || other.state == state)&&(identical(other.verifier, verifier) || other.verifier == verifier)&&(identical(other.cookie, cookie) || other.cookie == cookie)&&(identical(other.isFlowComplete, isFlowComplete) || other.isFlowComplete == isFlowComplete)&&(identical(other.authToken, authToken) || other.authToken == authToken));
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
_$$FlowImplCopyWith<_$FlowImpl> get copyWith =>
|
|
||||||
__$$FlowImplCopyWithImpl<_$FlowImpl>(this, _$identity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class _Flow implements Flow {
|
|
||||||
const factory _Flow(
|
|
||||||
{required final Uri serverUri,
|
|
||||||
required final String state,
|
|
||||||
required final String verifier,
|
|
||||||
required final Cookie cookie,
|
|
||||||
final bool isFlowComplete,
|
|
||||||
final String? authToken}) = _$FlowImpl;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Uri get serverUri;
|
int get hashCode => Object.hash(runtimeType,serverUri,state,verifier,cookie,isFlowComplete,authToken);
|
||||||
@override
|
|
||||||
String get state;
|
|
||||||
@override
|
|
||||||
String get verifier;
|
|
||||||
@override
|
|
||||||
Cookie get cookie;
|
|
||||||
@override
|
|
||||||
bool get isFlowComplete;
|
|
||||||
@override
|
|
||||||
String? get authToken;
|
|
||||||
|
|
||||||
/// Create a copy of Flow
|
@override
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
String toString() {
|
||||||
@override
|
return 'Flow(serverUri: $serverUri, state: $state, verifier: $verifier, cookie: $cookie, isFlowComplete: $isFlowComplete, authToken: $authToken)';
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
_$$FlowImplCopyWith<_$FlowImpl> get copyWith =>
|
|
||||||
throw _privateConstructorUsedError;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$FlowCopyWith<$Res> implements $FlowCopyWith<$Res> {
|
||||||
|
factory _$FlowCopyWith(_Flow value, $Res Function(_Flow) _then) = __$FlowCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
Uri serverUri, String state, String verifier, Cookie cookie, bool isFlowComplete, String? authToken
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$FlowCopyWithImpl<$Res>
|
||||||
|
implements _$FlowCopyWith<$Res> {
|
||||||
|
__$FlowCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _Flow _self;
|
||||||
|
final $Res Function(_Flow) _then;
|
||||||
|
|
||||||
|
/// Create a copy of Flow
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? serverUri = null,Object? state = null,Object? verifier = null,Object? cookie = null,Object? isFlowComplete = null,Object? authToken = freezed,}) {
|
||||||
|
return _then(_Flow(
|
||||||
|
serverUri: null == serverUri ? _self.serverUri : serverUri // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Uri,state: null == state ? _self.state : state // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,verifier: null == verifier ? _self.verifier : verifier // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,cookie: null == cookie ? _self.cookie : cookie // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Cookie,isFlowComplete: null == isFlowComplete ? _self.isFlowComplete : isFlowComplete // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,authToken: freezed == authToken ? _self.authToken : authToken // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// dart format on
|
||||||
|
|
|
||||||
|
|
@ -53,8 +53,10 @@ class OauthFlows extends _$OauthFlows {
|
||||||
}
|
}
|
||||||
state = {
|
state = {
|
||||||
...state,
|
...state,
|
||||||
oauthState: state[oauthState]!
|
oauthState: state[oauthState]!.copyWith(
|
||||||
.copyWith(isFlowComplete: true, authToken: authToken),
|
isFlowComplete: true,
|
||||||
|
authToken: authToken,
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,221 +6,167 @@ part of 'oauth_provider.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$loginInExchangeForCodeHash() =>
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
r'bfc3945529048a0f536052fd5579b76457560fcd';
|
// ignore_for_file: type=lint, type=warning
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
@ProviderFor(OauthFlows)
|
||||||
class _SystemHash {
|
final oauthFlowsProvider = OauthFlowsProvider._();
|
||||||
_SystemHash._();
|
|
||||||
|
|
||||||
static int combine(int hash, int value) {
|
final class OauthFlowsProvider
|
||||||
// ignore: parameter_assignments
|
extends $NotifierProvider<OauthFlows, Map<State, Flow>> {
|
||||||
hash = 0x1fffffff & (hash + value);
|
OauthFlowsProvider._()
|
||||||
// ignore: parameter_assignments
|
: super(
|
||||||
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
from: null,
|
||||||
return hash ^ (hash >> 6);
|
argument: null,
|
||||||
}
|
retry: null,
|
||||||
|
name: r'oauthFlowsProvider',
|
||||||
static int finish(int hash) {
|
isAutoDispose: false,
|
||||||
// ignore: parameter_assignments
|
|
||||||
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
|
||||||
// ignore: parameter_assignments
|
|
||||||
hash = hash ^ (hash >> 11);
|
|
||||||
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// the code returned by the server in exchange for the verifier
|
|
||||||
///
|
|
||||||
/// Copied from [loginInExchangeForCode].
|
|
||||||
@ProviderFor(loginInExchangeForCode)
|
|
||||||
const loginInExchangeForCodeProvider = LoginInExchangeForCodeFamily();
|
|
||||||
|
|
||||||
/// the code returned by the server in exchange for the verifier
|
|
||||||
///
|
|
||||||
/// Copied from [loginInExchangeForCode].
|
|
||||||
class LoginInExchangeForCodeFamily extends Family<AsyncValue<String?>> {
|
|
||||||
/// the code returned by the server in exchange for the verifier
|
|
||||||
///
|
|
||||||
/// Copied from [loginInExchangeForCode].
|
|
||||||
const LoginInExchangeForCodeFamily();
|
|
||||||
|
|
||||||
/// the code returned by the server in exchange for the verifier
|
|
||||||
///
|
|
||||||
/// Copied from [loginInExchangeForCode].
|
|
||||||
LoginInExchangeForCodeProvider call({
|
|
||||||
required String oauthState,
|
|
||||||
required String code,
|
|
||||||
ErrorResponseHandler? responseHandler,
|
|
||||||
}) {
|
|
||||||
return LoginInExchangeForCodeProvider(
|
|
||||||
oauthState: oauthState,
|
|
||||||
code: code,
|
|
||||||
responseHandler: responseHandler,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
LoginInExchangeForCodeProvider getProviderOverride(
|
|
||||||
covariant LoginInExchangeForCodeProvider provider,
|
|
||||||
) {
|
|
||||||
return call(
|
|
||||||
oauthState: provider.oauthState,
|
|
||||||
code: provider.code,
|
|
||||||
responseHandler: provider.responseHandler,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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'loginInExchangeForCodeProvider';
|
|
||||||
}
|
|
||||||
|
|
||||||
/// the code returned by the server in exchange for the verifier
|
|
||||||
///
|
|
||||||
/// Copied from [loginInExchangeForCode].
|
|
||||||
class LoginInExchangeForCodeProvider
|
|
||||||
extends AutoDisposeFutureProvider<String?> {
|
|
||||||
/// the code returned by the server in exchange for the verifier
|
|
||||||
///
|
|
||||||
/// Copied from [loginInExchangeForCode].
|
|
||||||
LoginInExchangeForCodeProvider({
|
|
||||||
required String oauthState,
|
|
||||||
required String code,
|
|
||||||
ErrorResponseHandler? responseHandler,
|
|
||||||
}) : this._internal(
|
|
||||||
(ref) => loginInExchangeForCode(
|
|
||||||
ref as LoginInExchangeForCodeRef,
|
|
||||||
oauthState: oauthState,
|
|
||||||
code: code,
|
|
||||||
responseHandler: responseHandler,
|
|
||||||
),
|
|
||||||
from: loginInExchangeForCodeProvider,
|
|
||||||
name: r'loginInExchangeForCodeProvider',
|
|
||||||
debugGetCreateSourceHash:
|
|
||||||
const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$loginInExchangeForCodeHash,
|
|
||||||
dependencies: LoginInExchangeForCodeFamily._dependencies,
|
|
||||||
allTransitiveDependencies:
|
|
||||||
LoginInExchangeForCodeFamily._allTransitiveDependencies,
|
|
||||||
oauthState: oauthState,
|
|
||||||
code: code,
|
|
||||||
responseHandler: responseHandler,
|
|
||||||
);
|
|
||||||
|
|
||||||
LoginInExchangeForCodeProvider._internal(
|
|
||||||
super._createNotifier, {
|
|
||||||
required super.name,
|
|
||||||
required super.dependencies,
|
|
||||||
required super.allTransitiveDependencies,
|
|
||||||
required super.debugGetCreateSourceHash,
|
|
||||||
required super.from,
|
|
||||||
required this.oauthState,
|
|
||||||
required this.code,
|
|
||||||
required this.responseHandler,
|
|
||||||
}) : super.internal();
|
|
||||||
|
|
||||||
final String oauthState;
|
|
||||||
final String code;
|
|
||||||
final ErrorResponseHandler? responseHandler;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Override overrideWith(
|
|
||||||
FutureOr<String?> Function(LoginInExchangeForCodeRef provider) create,
|
|
||||||
) {
|
|
||||||
return ProviderOverride(
|
|
||||||
origin: this,
|
|
||||||
override: LoginInExchangeForCodeProvider._internal(
|
|
||||||
(ref) => create(ref as LoginInExchangeForCodeRef),
|
|
||||||
from: from,
|
|
||||||
name: null,
|
|
||||||
dependencies: null,
|
dependencies: null,
|
||||||
allTransitiveDependencies: null,
|
$allTransitiveDependencies: null,
|
||||||
debugGetCreateSourceHash: null,
|
);
|
||||||
oauthState: oauthState,
|
|
||||||
code: code,
|
|
||||||
responseHandler: responseHandler,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
AutoDisposeFutureProviderElement<String?> createElement() {
|
String debugGetCreateSourceHash() => _$oauthFlowsHash();
|
||||||
return _LoginInExchangeForCodeProviderElement(this);
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
OauthFlows create() => OauthFlows();
|
||||||
|
|
||||||
|
/// {@macro riverpod.override_with_value}
|
||||||
|
Override overrideWithValue(Map<State, Flow> value) {
|
||||||
|
return $ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
providerOverride: $SyncValueProvider<Map<State, Flow>>(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String _$oauthFlowsHash() => r'4e278baa0bf26f2a10694ca2caadb68dd5b6156f';
|
||||||
|
|
||||||
|
abstract class _$OauthFlows extends $Notifier<Map<State, Flow>> {
|
||||||
|
Map<State, Flow> build();
|
||||||
|
@$mustCallSuper
|
||||||
|
@override
|
||||||
|
void runBuild() {
|
||||||
|
final ref = this.ref as $Ref<Map<State, Flow>, Map<State, Flow>>;
|
||||||
|
final element =
|
||||||
|
ref.element
|
||||||
|
as $ClassProviderElement<
|
||||||
|
AnyNotifier<Map<State, Flow>, Map<State, Flow>>,
|
||||||
|
Map<State, Flow>,
|
||||||
|
Object?,
|
||||||
|
Object?
|
||||||
|
>;
|
||||||
|
element.handleCreate(ref, build);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// the code returned by the server in exchange for the verifier
|
||||||
|
|
||||||
|
@ProviderFor(loginInExchangeForCode)
|
||||||
|
final loginInExchangeForCodeProvider = LoginInExchangeForCodeFamily._();
|
||||||
|
|
||||||
|
/// the code returned by the server in exchange for the verifier
|
||||||
|
|
||||||
|
final class LoginInExchangeForCodeProvider
|
||||||
|
extends $FunctionalProvider<AsyncValue<String?>, String?, FutureOr<String?>>
|
||||||
|
with $FutureModifier<String?>, $FutureProvider<String?> {
|
||||||
|
/// the code returned by the server in exchange for the verifier
|
||||||
|
LoginInExchangeForCodeProvider._({
|
||||||
|
required LoginInExchangeForCodeFamily super.from,
|
||||||
|
required ({
|
||||||
|
State oauthState,
|
||||||
|
Code code,
|
||||||
|
ErrorResponseHandler? responseHandler,
|
||||||
|
})
|
||||||
|
super.argument,
|
||||||
|
}) : super(
|
||||||
|
retry: null,
|
||||||
|
name: r'loginInExchangeForCodeProvider',
|
||||||
|
isAutoDispose: true,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$loginInExchangeForCodeHash();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return r'loginInExchangeForCodeProvider'
|
||||||
|
''
|
||||||
|
'$argument';
|
||||||
|
}
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
$FutureProviderElement<String?> $createElement($ProviderPointer pointer) =>
|
||||||
|
$FutureProviderElement(pointer);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOr<String?> create(Ref ref) {
|
||||||
|
final argument =
|
||||||
|
this.argument
|
||||||
|
as ({
|
||||||
|
State oauthState,
|
||||||
|
Code code,
|
||||||
|
ErrorResponseHandler? responseHandler,
|
||||||
|
});
|
||||||
|
return loginInExchangeForCode(
|
||||||
|
ref,
|
||||||
|
oauthState: argument.oauthState,
|
||||||
|
code: argument.code,
|
||||||
|
responseHandler: argument.responseHandler,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return other is LoginInExchangeForCodeProvider &&
|
return other is LoginInExchangeForCodeProvider &&
|
||||||
other.oauthState == oauthState &&
|
other.argument == argument;
|
||||||
other.code == code &&
|
|
||||||
other.responseHandler == responseHandler;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode {
|
int get hashCode {
|
||||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
return argument.hashCode;
|
||||||
hash = _SystemHash.combine(hash, oauthState.hashCode);
|
|
||||||
hash = _SystemHash.combine(hash, code.hashCode);
|
|
||||||
hash = _SystemHash.combine(hash, responseHandler.hashCode);
|
|
||||||
|
|
||||||
return _SystemHash.finish(hash);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
String _$loginInExchangeForCodeHash() =>
|
||||||
// ignore: unused_element
|
r'bfc3945529048a0f536052fd5579b76457560fcd';
|
||||||
mixin LoginInExchangeForCodeRef on AutoDisposeFutureProviderRef<String?> {
|
|
||||||
/// The parameter `oauthState` of this provider.
|
|
||||||
String get oauthState;
|
|
||||||
|
|
||||||
/// The parameter `code` of this provider.
|
/// the code returned by the server in exchange for the verifier
|
||||||
String get code;
|
|
||||||
|
|
||||||
/// The parameter `responseHandler` of this provider.
|
final class LoginInExchangeForCodeFamily extends $Family
|
||||||
ErrorResponseHandler? get responseHandler;
|
with
|
||||||
|
$FunctionalFamilyOverride<
|
||||||
|
FutureOr<String?>,
|
||||||
|
({State oauthState, Code code, ErrorResponseHandler? responseHandler})
|
||||||
|
> {
|
||||||
|
LoginInExchangeForCodeFamily._()
|
||||||
|
: super(
|
||||||
|
retry: null,
|
||||||
|
name: r'loginInExchangeForCodeProvider',
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
isAutoDispose: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// the code returned by the server in exchange for the verifier
|
||||||
|
|
||||||
|
LoginInExchangeForCodeProvider call({
|
||||||
|
required State oauthState,
|
||||||
|
required Code code,
|
||||||
|
ErrorResponseHandler? responseHandler,
|
||||||
|
}) => LoginInExchangeForCodeProvider._(
|
||||||
|
argument: (
|
||||||
|
oauthState: oauthState,
|
||||||
|
code: code,
|
||||||
|
responseHandler: responseHandler,
|
||||||
|
),
|
||||||
|
from: this,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => r'loginInExchangeForCodeProvider';
|
||||||
}
|
}
|
||||||
|
|
||||||
class _LoginInExchangeForCodeProviderElement
|
|
||||||
extends AutoDisposeFutureProviderElement<String?>
|
|
||||||
with LoginInExchangeForCodeRef {
|
|
||||||
_LoginInExchangeForCodeProviderElement(super.provider);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get oauthState =>
|
|
||||||
(origin as LoginInExchangeForCodeProvider).oauthState;
|
|
||||||
@override
|
|
||||||
String get code => (origin as LoginInExchangeForCodeProvider).code;
|
|
||||||
@override
|
|
||||||
ErrorResponseHandler? get responseHandler =>
|
|
||||||
(origin as LoginInExchangeForCodeProvider).responseHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
String _$oauthFlowsHash() => r'4e278baa0bf26f2a10694ca2caadb68dd5b6156f';
|
|
||||||
|
|
||||||
/// See also [OauthFlows].
|
|
||||||
@ProviderFor(OauthFlows)
|
|
||||||
final oauthFlowsProvider =
|
|
||||||
NotifierProvider<OauthFlows, Map<State, Flow>>.internal(
|
|
||||||
OauthFlows.new,
|
|
||||||
name: r'oauthFlowsProvider',
|
|
||||||
debugGetCreateSourceHash:
|
|
||||||
const bool.fromEnvironment('dart.vm.product') ? null : _$oauthFlowsHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef _$OauthFlows = Notifier<Map<State, Flow>>;
|
|
||||||
// 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
|
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,7 @@ class CallbackPage extends HookConsumerWidget {
|
||||||
|
|
||||||
// check if the state is in the flows
|
// check if the state is in the flows
|
||||||
if (!flows.containsKey(state)) {
|
if (!flows.containsKey(state)) {
|
||||||
return const _SomethingWentWrong(
|
return const _SomethingWentWrong(message: 'State not found');
|
||||||
message: 'State not found',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the token
|
// get the token
|
||||||
|
|
@ -45,26 +43,21 @@ class CallbackPage extends HookConsumerWidget {
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text('Contacting server...\nPlease wait\n\nGot:'
|
Text(
|
||||||
'\nState: $state\nCode: $code'),
|
'Contacting server...\nPlease wait\n\nGot:'
|
||||||
|
'\nState: $state\nCode: $code',
|
||||||
|
),
|
||||||
loginAuthToken.when(
|
loginAuthToken.when(
|
||||||
data: (authenticationToken) {
|
data: (authenticationToken) {
|
||||||
if (authenticationToken == null) {
|
if (authenticationToken == null) {
|
||||||
handleServerError(
|
handleServerError(context, serverErrorResponse);
|
||||||
context,
|
|
||||||
serverErrorResponse,
|
|
||||||
);
|
|
||||||
return const BackToLoginButton();
|
return const BackToLoginButton();
|
||||||
}
|
}
|
||||||
return Text('Token: $authenticationToken');
|
return Text('Token: $authenticationToken');
|
||||||
},
|
},
|
||||||
loading: () => const CircularProgressIndicator(),
|
loading: () => const CircularProgressIndicator(),
|
||||||
error: (error, _) {
|
error: (error, _) {
|
||||||
handleServerError(
|
handleServerError(context, serverErrorResponse, e: error);
|
||||||
context,
|
|
||||||
serverErrorResponse,
|
|
||||||
e: error,
|
|
||||||
);
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
Text('Error with OAuth flow: $error'),
|
Text('Error with OAuth flow: $error'),
|
||||||
|
|
@ -81,9 +74,7 @@ class CallbackPage extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class BackToLoginButton extends StatelessWidget {
|
class BackToLoginButton extends StatelessWidget {
|
||||||
const BackToLoginButton({
|
const BackToLoginButton({super.key});
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
@ -97,9 +88,7 @@ class BackToLoginButton extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SomethingWentWrong extends StatelessWidget {
|
class _SomethingWentWrong extends StatelessWidget {
|
||||||
const _SomethingWentWrong({
|
const _SomethingWentWrong({this.message = 'Error with OAuth flow'});
|
||||||
this.message = 'Error with OAuth flow',
|
|
||||||
});
|
|
||||||
|
|
||||||
final String message;
|
final String message;
|
||||||
|
|
||||||
|
|
@ -109,10 +98,7 @@ class _SomethingWentWrong extends StatelessWidget {
|
||||||
body: Center(
|
body: Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [Text(message), const BackToLoginButton()],
|
||||||
Text(message),
|
|
||||||
const BackToLoginButton(),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,7 @@ import 'package:vaani/shared/utils.dart';
|
||||||
import 'package:vaani/shared/widgets/add_new_server.dart';
|
import 'package:vaani/shared/widgets/add_new_server.dart';
|
||||||
|
|
||||||
class OnboardingSinglePage extends HookConsumerWidget {
|
class OnboardingSinglePage extends HookConsumerWidget {
|
||||||
const OnboardingSinglePage({
|
const OnboardingSinglePage({super.key});
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
|
@ -23,8 +21,9 @@ class OnboardingSinglePage extends HookConsumerWidget {
|
||||||
child: ConstrainedBox(
|
child: ConstrainedBox(
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxWidth: 600,
|
maxWidth: 600,
|
||||||
minWidth:
|
minWidth: constraints.maxWidth < 600
|
||||||
constraints.maxWidth < 600 ? constraints.maxWidth : 0,
|
? constraints.maxWidth
|
||||||
|
: 0,
|
||||||
),
|
),
|
||||||
child: const Padding(
|
child: const Padding(
|
||||||
padding: EdgeInsets.symmetric(vertical: 20.0),
|
padding: EdgeInsets.symmetric(vertical: 20.0),
|
||||||
|
|
@ -39,10 +38,7 @@ class OnboardingSinglePage extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget fadeSlideTransitionBuilder(
|
Widget fadeSlideTransitionBuilder(Widget child, Animation<double> animation) {
|
||||||
Widget child,
|
|
||||||
Animation<double> animation,
|
|
||||||
) {
|
|
||||||
return FadeTransition(
|
return FadeTransition(
|
||||||
opacity: animation,
|
opacity: animation,
|
||||||
child: SlideTransition(
|
child: SlideTransition(
|
||||||
|
|
@ -56,9 +52,7 @@ Widget fadeSlideTransitionBuilder(
|
||||||
}
|
}
|
||||||
|
|
||||||
class OnboardingBody extends HookConsumerWidget {
|
class OnboardingBody extends HookConsumerWidget {
|
||||||
const OnboardingBody({
|
const OnboardingBody({super.key});
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
|
@ -81,9 +75,7 @@ class OnboardingBody extends HookConsumerWidget {
|
||||||
style: Theme.of(context).textTheme.headlineSmall,
|
style: Theme.of(context).textTheme.headlineSmall,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox.square(
|
const SizedBox.square(dimension: 16.0),
|
||||||
dimension: 16.0,
|
|
||||||
),
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: AnimatedSwitcher(
|
child: AnimatedSwitcher(
|
||||||
|
|
@ -112,21 +104,17 @@ class OnboardingBody extends HookConsumerWidget {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox.square(
|
const SizedBox.square(dimension: 16.0),
|
||||||
dimension: 16.0,
|
|
||||||
),
|
|
||||||
AnimatedSwitcher(
|
AnimatedSwitcher(
|
||||||
duration: 500.ms,
|
duration: 500.ms,
|
||||||
transitionBuilder: fadeSlideTransitionBuilder,
|
transitionBuilder: fadeSlideTransitionBuilder,
|
||||||
child: canUserLogin.value
|
child: canUserLogin.value
|
||||||
? UserLoginWidget(
|
? UserLoginWidget(server: audiobookshelfUri)
|
||||||
server: audiobookshelfUri,
|
|
||||||
)
|
|
||||||
// ).animate().fade(duration: 600.ms).slideY(begin: 0.3, end: 0)
|
// ).animate().fade(duration: 600.ms).slideY(begin: 0.3, end: 0)
|
||||||
: const RedirectToABS().animate().fadeIn().slideY(
|
: const RedirectToABS().animate().fadeIn().slideY(
|
||||||
curve: Curves.easeInOut,
|
curve: Curves.easeInOut,
|
||||||
duration: 500.ms,
|
duration: 500.ms,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
@ -134,9 +122,7 @@ class OnboardingBody extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class RedirectToABS extends StatelessWidget {
|
class RedirectToABS extends StatelessWidget {
|
||||||
const RedirectToABS({
|
const RedirectToABS({super.key});
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
@ -152,18 +138,14 @@ class RedirectToABS extends StatelessWidget {
|
||||||
isSemanticButton: false,
|
isSemanticButton: false,
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
elevation: WidgetStateProperty.all(0),
|
elevation: WidgetStateProperty.all(0),
|
||||||
padding: WidgetStateProperty.all(
|
padding: WidgetStateProperty.all(const EdgeInsets.all(0)),
|
||||||
const EdgeInsets.all(0),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
// open the github page
|
// open the github page
|
||||||
// ignore: avoid_print
|
// ignore: avoid_print
|
||||||
print('Opening the github page');
|
print('Opening the github page');
|
||||||
await handleLaunchUrl(
|
await handleLaunchUrl(
|
||||||
Uri.parse(
|
Uri.parse('https://www.audiobookshelf.org'),
|
||||||
'https://www.audiobookshelf.org',
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: const Text('Click here'),
|
child: const Text('Click here'),
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,7 @@ import 'package:vaani/settings/api_settings_provider.dart'
|
||||||
import 'package:vaani/settings/models/models.dart' as model;
|
import 'package:vaani/settings/models/models.dart' as model;
|
||||||
|
|
||||||
class UserLoginWidget extends HookConsumerWidget {
|
class UserLoginWidget extends HookConsumerWidget {
|
||||||
const UserLoginWidget({
|
const UserLoginWidget({super.key, required this.server, this.onSuccess});
|
||||||
super.key,
|
|
||||||
required this.server,
|
|
||||||
this.onSuccess,
|
|
||||||
});
|
|
||||||
|
|
||||||
final Uri server;
|
final Uri server;
|
||||||
final Function(model.AuthenticatedUser)? onSuccess;
|
final Function(model.AuthenticatedUser)? onSuccess;
|
||||||
|
|
@ -34,8 +30,9 @@ class UserLoginWidget extends HookConsumerWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final serverStatusError = useMemoized(() => ErrorResponseHandler(), []);
|
final serverStatusError = useMemoized(() => ErrorResponseHandler(), []);
|
||||||
final serverStatus =
|
final serverStatus = ref.watch(
|
||||||
ref.watch(serverStatusProvider(server, serverStatusError.storeError));
|
serverStatusProvider(server, serverStatusError.storeError),
|
||||||
|
);
|
||||||
|
|
||||||
return serverStatus.when(
|
return serverStatus.when(
|
||||||
data: (value) {
|
data: (value) {
|
||||||
|
|
@ -55,9 +52,7 @@ class UserLoginWidget extends HookConsumerWidget {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
loading: () {
|
loading: () {
|
||||||
return const Center(
|
return const Center(child: CircularProgressIndicator());
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
error: (error, _) {
|
error: (error, _) {
|
||||||
return Center(
|
return Center(
|
||||||
|
|
@ -68,10 +63,7 @@ class UserLoginWidget extends HookConsumerWidget {
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
ref.invalidate(
|
ref.invalidate(
|
||||||
serverStatusProvider(
|
serverStatusProvider(server, serverStatusError.storeError),
|
||||||
server,
|
|
||||||
serverStatusError.storeError,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: const Text('Try again'),
|
child: const Text('Try again'),
|
||||||
|
|
@ -84,11 +76,7 @@ class UserLoginWidget extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum AuthMethodChoice {
|
enum AuthMethodChoice { local, openid, authToken }
|
||||||
local,
|
|
||||||
openid,
|
|
||||||
authToken,
|
|
||||||
}
|
|
||||||
|
|
||||||
class UserLoginMultipleAuth extends HookConsumerWidget {
|
class UserLoginMultipleAuth extends HookConsumerWidget {
|
||||||
const UserLoginMultipleAuth({
|
const UserLoginMultipleAuth({
|
||||||
|
|
@ -117,21 +105,17 @@ class UserLoginMultipleAuth extends HookConsumerWidget {
|
||||||
);
|
);
|
||||||
|
|
||||||
model.AudiobookShelfServer addServer() {
|
model.AudiobookShelfServer addServer() {
|
||||||
var newServer = model.AudiobookShelfServer(
|
var newServer = model.AudiobookShelfServer(serverUrl: server);
|
||||||
serverUrl: server,
|
|
||||||
);
|
|
||||||
try {
|
try {
|
||||||
// add the server to the list of servers
|
// add the server to the list of servers
|
||||||
ref.read(audiobookShelfServerProvider.notifier).addServer(
|
ref.read(audiobookShelfServerProvider.notifier).addServer(newServer);
|
||||||
newServer,
|
|
||||||
);
|
|
||||||
} on ServerAlreadyExistsException catch (e) {
|
} on ServerAlreadyExistsException catch (e) {
|
||||||
newServer = e.server;
|
newServer = e.server;
|
||||||
} finally {
|
} finally {
|
||||||
ref.read(apiSettingsProvider.notifier).updateState(
|
ref
|
||||||
ref.read(apiSettingsProvider).copyWith(
|
.read(apiSettingsProvider.notifier)
|
||||||
activeServer: newServer,
|
.updateState(
|
||||||
),
|
ref.read(apiSettingsProvider).copyWith(activeServer: newServer),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return newServer;
|
return newServer;
|
||||||
|
|
@ -150,42 +134,49 @@ class UserLoginMultipleAuth extends HookConsumerWidget {
|
||||||
runAlignment: WrapAlignment.center,
|
runAlignment: WrapAlignment.center,
|
||||||
runSpacing: 10,
|
runSpacing: 10,
|
||||||
alignment: WrapAlignment.center,
|
alignment: WrapAlignment.center,
|
||||||
children: [
|
children:
|
||||||
// a small label to show the user what to do
|
[
|
||||||
if (localAvailable)
|
// a small label to show the user what to do
|
||||||
ChoiceChip(
|
if (localAvailable)
|
||||||
label: const Text('Local'),
|
ChoiceChip(
|
||||||
selected: methodChoice.value == AuthMethodChoice.local,
|
label: const Text('Local'),
|
||||||
onSelected: (selected) {
|
selected:
|
||||||
if (selected) {
|
methodChoice.value ==
|
||||||
methodChoice.value = AuthMethodChoice.local;
|
AuthMethodChoice.local,
|
||||||
}
|
onSelected: (selected) {
|
||||||
},
|
if (selected) {
|
||||||
),
|
methodChoice.value = AuthMethodChoice.local;
|
||||||
if (openIDAvailable)
|
}
|
||||||
ChoiceChip(
|
},
|
||||||
label: const Text('OpenID'),
|
),
|
||||||
selected: methodChoice.value == AuthMethodChoice.openid,
|
if (openIDAvailable)
|
||||||
onSelected: (selected) {
|
ChoiceChip(
|
||||||
if (selected) {
|
label: const Text('OpenID'),
|
||||||
methodChoice.value = AuthMethodChoice.openid;
|
selected:
|
||||||
}
|
methodChoice.value ==
|
||||||
},
|
AuthMethodChoice.openid,
|
||||||
),
|
onSelected: (selected) {
|
||||||
ChoiceChip(
|
if (selected) {
|
||||||
label: const Text('Token'),
|
methodChoice.value =
|
||||||
selected:
|
AuthMethodChoice.openid;
|
||||||
methodChoice.value == AuthMethodChoice.authToken,
|
}
|
||||||
onSelected: (selected) {
|
},
|
||||||
if (selected) {
|
),
|
||||||
methodChoice.value = AuthMethodChoice.authToken;
|
ChoiceChip(
|
||||||
}
|
label: const Text('Token'),
|
||||||
},
|
selected:
|
||||||
),
|
methodChoice.value ==
|
||||||
].animate(interval: 100.ms).fadeIn(
|
AuthMethodChoice.authToken,
|
||||||
duration: 150.ms,
|
onSelected: (selected) {
|
||||||
curve: Curves.easeIn,
|
if (selected) {
|
||||||
),
|
methodChoice.value =
|
||||||
|
AuthMethodChoice.authToken;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
.animate(interval: 100.ms)
|
||||||
|
.fadeIn(duration: 150.ms, curve: Curves.easeIn),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
|
|
@ -195,21 +186,21 @@ class UserLoginMultipleAuth extends HookConsumerWidget {
|
||||||
transitionBuilder: fadeSlideTransitionBuilder,
|
transitionBuilder: fadeSlideTransitionBuilder,
|
||||||
child: switch (methodChoice.value) {
|
child: switch (methodChoice.value) {
|
||||||
AuthMethodChoice.authToken => UserLoginWithToken(
|
AuthMethodChoice.authToken => UserLoginWithToken(
|
||||||
server: server,
|
server: server,
|
||||||
addServer: addServer,
|
addServer: addServer,
|
||||||
onSuccess: onSuccess,
|
onSuccess: onSuccess,
|
||||||
),
|
),
|
||||||
AuthMethodChoice.local => UserLoginWithPassword(
|
AuthMethodChoice.local => UserLoginWithPassword(
|
||||||
server: server,
|
server: server,
|
||||||
addServer: addServer,
|
addServer: addServer,
|
||||||
onSuccess: onSuccess,
|
onSuccess: onSuccess,
|
||||||
),
|
),
|
||||||
AuthMethodChoice.openid => UserLoginWithOpenID(
|
AuthMethodChoice.openid => UserLoginWithOpenID(
|
||||||
server: server,
|
server: server,
|
||||||
addServer: addServer,
|
addServer: addServer,
|
||||||
openIDButtonText: openIDButtonText,
|
openIDButtonText: openIDButtonText,
|
||||||
onSuccess: onSuccess,
|
onSuccess: onSuccess,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,9 @@ class UserLoginWithOpenID extends HookConsumerWidget {
|
||||||
|
|
||||||
if (openIDLoginEndpoint == null) {
|
if (openIDLoginEndpoint == null) {
|
||||||
if (responseErrorHandler.response.statusCode == 400 &&
|
if (responseErrorHandler.response.statusCode == 400 &&
|
||||||
responseErrorHandler.response.body
|
responseErrorHandler.response.body.toLowerCase().contains(
|
||||||
.toLowerCase()
|
RegExp(r'invalid.*redirect.*uri'),
|
||||||
.contains(RegExp(r'invalid.*redirect.*uri'))) {
|
)) {
|
||||||
// show error
|
// show error
|
||||||
handleServerError(
|
handleServerError(
|
||||||
context,
|
context,
|
||||||
|
|
@ -97,16 +97,16 @@ class UserLoginWithOpenID extends HookConsumerWidget {
|
||||||
);
|
);
|
||||||
|
|
||||||
// add the flow to the provider
|
// add the flow to the provider
|
||||||
ref.read(oauthFlowsProvider.notifier).addFlow(
|
ref
|
||||||
|
.read(oauthFlowsProvider.notifier)
|
||||||
|
.addFlow(
|
||||||
oauthState,
|
oauthState,
|
||||||
verifier: verifier,
|
verifier: verifier,
|
||||||
serverUri: server,
|
serverUri: server,
|
||||||
cookie: Cookie.fromSetCookieValue(authCookie!),
|
cookie: Cookie.fromSetCookieValue(authCookie!),
|
||||||
);
|
);
|
||||||
|
|
||||||
await handleLaunchUrl(
|
await handleLaunchUrl(openIDLoginEndpoint);
|
||||||
openIDLoginEndpoint,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
|
|
|
||||||
|
|
@ -39,17 +39,14 @@ class UserLoginWithPassword extends HookConsumerWidget {
|
||||||
final api = ref.watch(audiobookshelfApiProvider(server));
|
final api = ref.watch(audiobookshelfApiProvider(server));
|
||||||
|
|
||||||
// forward animation when the password visibility changes
|
// forward animation when the password visibility changes
|
||||||
useEffect(
|
useEffect(() {
|
||||||
() {
|
if (isPasswordVisible.value) {
|
||||||
if (isPasswordVisible.value) {
|
isPasswordVisibleAnimationController.forward();
|
||||||
isPasswordVisibleAnimationController.forward();
|
} else {
|
||||||
} else {
|
isPasswordVisibleAnimationController.reverse();
|
||||||
isPasswordVisibleAnimationController.reverse();
|
}
|
||||||
}
|
return null;
|
||||||
return null;
|
}, [isPasswordVisible.value]);
|
||||||
},
|
|
||||||
[isPasswordVisible.value],
|
|
||||||
);
|
|
||||||
|
|
||||||
/// Login to the server and save the user
|
/// Login to the server and save the user
|
||||||
Future<void> loginAndSave() async {
|
Future<void> loginAndSave() async {
|
||||||
|
|
@ -109,10 +106,9 @@ class UserLoginWithPassword extends HookConsumerWidget {
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Username',
|
labelText: 'Username',
|
||||||
labelStyle: TextStyle(
|
labelStyle: TextStyle(
|
||||||
color: Theme.of(context)
|
color: Theme.of(
|
||||||
.colorScheme
|
context,
|
||||||
.onSurface
|
).colorScheme.onSurface.withValues(alpha: 0.8),
|
||||||
.withValues(alpha: 0.8),
|
|
||||||
),
|
),
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
),
|
),
|
||||||
|
|
@ -129,18 +125,16 @@ class UserLoginWithPassword extends HookConsumerWidget {
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Password',
|
labelText: 'Password',
|
||||||
labelStyle: TextStyle(
|
labelStyle: TextStyle(
|
||||||
color: Theme.of(context)
|
color: Theme.of(
|
||||||
.colorScheme
|
context,
|
||||||
.onSurface
|
).colorScheme.onSurface.withValues(alpha: 0.8),
|
||||||
.withValues(alpha: 0.8),
|
|
||||||
),
|
),
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
suffixIcon: ColorFiltered(
|
suffixIcon: ColorFiltered(
|
||||||
colorFilter: ColorFilter.mode(
|
colorFilter: ColorFilter.mode(
|
||||||
Theme.of(context)
|
Theme.of(
|
||||||
.colorScheme
|
context,
|
||||||
.primary
|
).colorScheme.primary.withValues(alpha: 0.8),
|
||||||
.withValues(alpha: 0.8),
|
|
||||||
BlendMode.srcIn,
|
BlendMode.srcIn,
|
||||||
),
|
),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
|
|
@ -157,9 +151,7 @@ class UserLoginWithPassword extends HookConsumerWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
suffixIconConstraints: const BoxConstraints(
|
suffixIconConstraints: const BoxConstraints(maxHeight: 45),
|
||||||
maxHeight: 45,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 30),
|
const SizedBox(height: 30),
|
||||||
|
|
@ -197,10 +189,12 @@ Future<void> handleServerError(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
title: const Text('Error'),
|
title: const Text('Error'),
|
||||||
content: SelectableText('$title\n'
|
content: SelectableText(
|
||||||
'Got response: ${responseErrorHandler.response.body} (${responseErrorHandler.response.statusCode})\n'
|
'$title\n'
|
||||||
'Stacktrace: $e\n\n'
|
'Got response: ${responseErrorHandler.response.body} (${responseErrorHandler.response.statusCode})\n'
|
||||||
'$body\n\n'),
|
'Stacktrace: $e\n\n'
|
||||||
|
'$body\n\n',
|
||||||
|
),
|
||||||
actions: [
|
actions: [
|
||||||
if (outLink != null)
|
if (outLink != null)
|
||||||
TextButton(
|
TextButton(
|
||||||
|
|
@ -214,8 +208,8 @@ Future<void> handleServerError(
|
||||||
// open an issue on the github page
|
// open an issue on the github page
|
||||||
handleLaunchUrl(
|
handleLaunchUrl(
|
||||||
AppMetadata.githubRepo
|
AppMetadata.githubRepo
|
||||||
// append the issue url
|
// append the issue url
|
||||||
.replace(
|
.replace(
|
||||||
path: '${AppMetadata.githubRepo.path}/issues/new',
|
path: '${AppMetadata.githubRepo.path}/issues/new',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -89,10 +89,9 @@ class UserLoginWithToken extends HookConsumerWidget {
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'API Token',
|
labelText: 'API Token',
|
||||||
labelStyle: TextStyle(
|
labelStyle: TextStyle(
|
||||||
color: Theme.of(context)
|
color: Theme.of(
|
||||||
.colorScheme
|
context,
|
||||||
.onSurface
|
).colorScheme.onSurface.withValues(alpha: 0.8),
|
||||||
.withValues(alpha: 0.8),
|
|
||||||
),
|
),
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
),
|
),
|
||||||
|
|
@ -107,10 +106,7 @@ class UserLoginWithToken extends HookConsumerWidget {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
ElevatedButton(
|
ElevatedButton(onPressed: loginAndSave, child: const Text('Login')),
|
||||||
onPressed: loginAndSave,
|
|
||||||
child: const Text('Login'),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ part 'book_settings.g.dart';
|
||||||
|
|
||||||
/// per book settings
|
/// per book settings
|
||||||
@freezed
|
@freezed
|
||||||
class BookSettings with _$BookSettings {
|
sealed class BookSettings with _$BookSettings {
|
||||||
const factory BookSettings({
|
const factory BookSettings({
|
||||||
required String bookId,
|
required String bookId,
|
||||||
@Default(NullablePlayerSettings()) NullablePlayerSettings playerSettings,
|
@Default(NullablePlayerSettings()) NullablePlayerSettings playerSettings,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// coverage:ignore-file
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// coverage:ignore-file
|
||||||
// ignore_for_file: type=lint
|
// 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
|
// 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
|
||||||
|
|
||||||
|
|
@ -9,195 +9,284 @@ part of 'book_settings.dart';
|
||||||
// FreezedGenerator
|
// FreezedGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
|
// dart format off
|
||||||
T _$identity<T>(T value) => value;
|
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#adding-getters-and-methods-to-our-models');
|
|
||||||
|
|
||||||
BookSettings _$BookSettingsFromJson(Map<String, dynamic> json) {
|
|
||||||
return _BookSettings.fromJson(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$BookSettings {
|
mixin _$BookSettings {
|
||||||
String get bookId => throw _privateConstructorUsedError;
|
|
||||||
NullablePlayerSettings get playerSettings =>
|
String get bookId; NullablePlayerSettings get playerSettings;
|
||||||
throw _privateConstructorUsedError;
|
/// Create a copy of BookSettings
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$BookSettingsCopyWith<BookSettings> get copyWith => _$BookSettingsCopyWithImpl<BookSettings>(this as BookSettings, _$identity);
|
||||||
|
|
||||||
/// Serializes this BookSettings to a JSON map.
|
/// Serializes this BookSettings to a JSON map.
|
||||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
Map<String, dynamic> toJson();
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is BookSettings&&(identical(other.bookId, bookId) || other.bookId == bookId)&&(identical(other.playerSettings, playerSettings) || other.playerSettings == playerSettings));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,bookId,playerSettings);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'BookSettings(bookId: $bookId, playerSettings: $playerSettings)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Create a copy of BookSettings
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
$BookSettingsCopyWith<BookSettings> get copyWith =>
|
|
||||||
throw _privateConstructorUsedError;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
abstract class $BookSettingsCopyWith<$Res> {
|
abstract mixin class $BookSettingsCopyWith<$Res> {
|
||||||
factory $BookSettingsCopyWith(
|
factory $BookSettingsCopyWith(BookSettings value, $Res Function(BookSettings) _then) = _$BookSettingsCopyWithImpl;
|
||||||
BookSettings value, $Res Function(BookSettings) then) =
|
@useResult
|
||||||
_$BookSettingsCopyWithImpl<$Res, BookSettings>;
|
$Res call({
|
||||||
@useResult
|
String bookId, NullablePlayerSettings playerSettings
|
||||||
$Res call({String bookId, NullablePlayerSettings playerSettings});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$NullablePlayerSettingsCopyWith<$Res> get playerSettings;
|
||||||
|
|
||||||
$NullablePlayerSettingsCopyWith<$Res> get playerSettings;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
class _$BookSettingsCopyWithImpl<$Res, $Val extends BookSettings>
|
class _$BookSettingsCopyWithImpl<$Res>
|
||||||
implements $BookSettingsCopyWith<$Res> {
|
implements $BookSettingsCopyWith<$Res> {
|
||||||
_$BookSettingsCopyWithImpl(this._value, this._then);
|
_$BookSettingsCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
// ignore: unused_field
|
final BookSettings _self;
|
||||||
final $Val _value;
|
final $Res Function(BookSettings) _then;
|
||||||
// ignore: unused_field
|
|
||||||
final $Res Function($Val) _then;
|
|
||||||
|
|
||||||
/// Create a copy of BookSettings
|
/// Create a copy of BookSettings
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline') @override $Res call({Object? bookId = null,Object? playerSettings = null,}) {
|
||||||
@override
|
return _then(_self.copyWith(
|
||||||
$Res call({
|
bookId: null == bookId ? _self.bookId : bookId // ignore: cast_nullable_to_non_nullable
|
||||||
Object? bookId = null,
|
as String,playerSettings: null == playerSettings ? _self.playerSettings : playerSettings // ignore: cast_nullable_to_non_nullable
|
||||||
Object? playerSettings = null,
|
as NullablePlayerSettings,
|
||||||
}) {
|
));
|
||||||
return _then(_value.copyWith(
|
}
|
||||||
bookId: null == bookId
|
/// Create a copy of BookSettings
|
||||||
? _value.bookId
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
: bookId // ignore: cast_nullable_to_non_nullable
|
@override
|
||||||
as String,
|
@pragma('vm:prefer-inline')
|
||||||
playerSettings: null == playerSettings
|
$NullablePlayerSettingsCopyWith<$Res> get playerSettings {
|
||||||
? _value.playerSettings
|
|
||||||
: playerSettings // ignore: cast_nullable_to_non_nullable
|
return $NullablePlayerSettingsCopyWith<$Res>(_self.playerSettings, (value) {
|
||||||
as NullablePlayerSettings,
|
return _then(_self.copyWith(playerSettings: value));
|
||||||
) as $Val);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a copy of BookSettings
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
$NullablePlayerSettingsCopyWith<$Res> get playerSettings {
|
|
||||||
return $NullablePlayerSettingsCopyWith<$Res>(_value.playerSettings,
|
|
||||||
(value) {
|
|
||||||
return _then(_value.copyWith(playerSettings: value) as $Val);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
abstract class _$$BookSettingsImplCopyWith<$Res>
|
|
||||||
implements $BookSettingsCopyWith<$Res> {
|
|
||||||
factory _$$BookSettingsImplCopyWith(
|
|
||||||
_$BookSettingsImpl value, $Res Function(_$BookSettingsImpl) then) =
|
|
||||||
__$$BookSettingsImplCopyWithImpl<$Res>;
|
|
||||||
@override
|
|
||||||
@useResult
|
|
||||||
$Res call({String bookId, NullablePlayerSettings playerSettings});
|
|
||||||
|
|
||||||
@override
|
/// Adds pattern-matching-related methods to [BookSettings].
|
||||||
$NullablePlayerSettingsCopyWith<$Res> get playerSettings;
|
extension BookSettingsPatterns on BookSettings {
|
||||||
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _BookSettings value)? $default,{required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _BookSettings() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// Callbacks receives the raw object, upcasted.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case final Subclass2 value:
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _BookSettings value) $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _BookSettings():
|
||||||
|
return $default(_that);}
|
||||||
|
}
|
||||||
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _BookSettings value)? $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _BookSettings() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to an `orElse` callback.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String bookId, NullablePlayerSettings playerSettings)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _BookSettings() when $default != null:
|
||||||
|
return $default(_that.bookId,_that.playerSettings);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// As opposed to `map`, this offers destructuring.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case Subclass2(:final field2):
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String bookId, NullablePlayerSettings playerSettings) $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _BookSettings():
|
||||||
|
return $default(_that.bookId,_that.playerSettings);}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to returning `null`
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String bookId, NullablePlayerSettings playerSettings)? $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _BookSettings() when $default != null:
|
||||||
|
return $default(_that.bookId,_that.playerSettings);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
class __$$BookSettingsImplCopyWithImpl<$Res>
|
|
||||||
extends _$BookSettingsCopyWithImpl<$Res, _$BookSettingsImpl>
|
|
||||||
implements _$$BookSettingsImplCopyWith<$Res> {
|
|
||||||
__$$BookSettingsImplCopyWithImpl(
|
|
||||||
_$BookSettingsImpl _value, $Res Function(_$BookSettingsImpl) _then)
|
|
||||||
: super(_value, _then);
|
|
||||||
|
|
||||||
/// Create a copy of BookSettings
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
@override
|
|
||||||
$Res call({
|
|
||||||
Object? bookId = null,
|
|
||||||
Object? playerSettings = null,
|
|
||||||
}) {
|
|
||||||
return _then(_$BookSettingsImpl(
|
|
||||||
bookId: null == bookId
|
|
||||||
? _value.bookId
|
|
||||||
: bookId // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
|
||||||
playerSettings: null == playerSettings
|
|
||||||
? _value.playerSettings
|
|
||||||
: playerSettings // ignore: cast_nullable_to_non_nullable
|
|
||||||
as NullablePlayerSettings,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
class _$BookSettingsImpl implements _BookSettings {
|
|
||||||
const _$BookSettingsImpl(
|
|
||||||
{required this.bookId,
|
|
||||||
this.playerSettings = const NullablePlayerSettings()});
|
|
||||||
|
|
||||||
factory _$BookSettingsImpl.fromJson(Map<String, dynamic> json) =>
|
class _BookSettings implements BookSettings {
|
||||||
_$$BookSettingsImplFromJson(json);
|
const _BookSettings({required this.bookId, this.playerSettings = const NullablePlayerSettings()});
|
||||||
|
factory _BookSettings.fromJson(Map<String, dynamic> json) => _$BookSettingsFromJson(json);
|
||||||
|
|
||||||
@override
|
@override final String bookId;
|
||||||
final String bookId;
|
@override@JsonKey() final NullablePlayerSettings playerSettings;
|
||||||
@override
|
|
||||||
@JsonKey()
|
|
||||||
final NullablePlayerSettings playerSettings;
|
|
||||||
|
|
||||||
@override
|
/// Create a copy of BookSettings
|
||||||
String toString() {
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
return 'BookSettings(bookId: $bookId, playerSettings: $playerSettings)';
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
}
|
@pragma('vm:prefer-inline')
|
||||||
|
_$BookSettingsCopyWith<_BookSettings> get copyWith => __$BookSettingsCopyWithImpl<_BookSettings>(this, _$identity);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
Map<String, dynamic> toJson() {
|
||||||
return identical(this, other) ||
|
return _$BookSettingsToJson(this, );
|
||||||
(other.runtimeType == runtimeType &&
|
|
||||||
other is _$BookSettingsImpl &&
|
|
||||||
(identical(other.bookId, bookId) || other.bookId == bookId) &&
|
|
||||||
(identical(other.playerSettings, playerSettings) ||
|
|
||||||
other.playerSettings == playerSettings));
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
|
||||||
int get hashCode => Object.hash(runtimeType, bookId, playerSettings);
|
|
||||||
|
|
||||||
/// Create a copy of BookSettings
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
_$$BookSettingsImplCopyWith<_$BookSettingsImpl> get copyWith =>
|
|
||||||
__$$BookSettingsImplCopyWithImpl<_$BookSettingsImpl>(this, _$identity);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Map<String, dynamic> toJson() {
|
|
||||||
return _$$BookSettingsImplToJson(
|
|
||||||
this,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class _BookSettings implements BookSettings {
|
@override
|
||||||
const factory _BookSettings(
|
bool operator ==(Object other) {
|
||||||
{required final String bookId,
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _BookSettings&&(identical(other.bookId, bookId) || other.bookId == bookId)&&(identical(other.playerSettings, playerSettings) || other.playerSettings == playerSettings));
|
||||||
final NullablePlayerSettings playerSettings}) = _$BookSettingsImpl;
|
|
||||||
|
|
||||||
factory _BookSettings.fromJson(Map<String, dynamic> json) =
|
|
||||||
_$BookSettingsImpl.fromJson;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bookId;
|
|
||||||
@override
|
|
||||||
NullablePlayerSettings get playerSettings;
|
|
||||||
|
|
||||||
/// Create a copy of BookSettings
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
_$$BookSettingsImplCopyWith<_$BookSettingsImpl> get copyWith =>
|
|
||||||
throw _privateConstructorUsedError;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,bookId,playerSettings);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'BookSettings(bookId: $bookId, playerSettings: $playerSettings)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$BookSettingsCopyWith<$Res> implements $BookSettingsCopyWith<$Res> {
|
||||||
|
factory _$BookSettingsCopyWith(_BookSettings value, $Res Function(_BookSettings) _then) = __$BookSettingsCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
String bookId, NullablePlayerSettings playerSettings
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@override $NullablePlayerSettingsCopyWith<$Res> get playerSettings;
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$BookSettingsCopyWithImpl<$Res>
|
||||||
|
implements _$BookSettingsCopyWith<$Res> {
|
||||||
|
__$BookSettingsCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _BookSettings _self;
|
||||||
|
final $Res Function(_BookSettings) _then;
|
||||||
|
|
||||||
|
/// Create a copy of BookSettings
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? bookId = null,Object? playerSettings = null,}) {
|
||||||
|
return _then(_BookSettings(
|
||||||
|
bookId: null == bookId ? _self.bookId : bookId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,playerSettings: null == playerSettings ? _self.playerSettings : playerSettings // ignore: cast_nullable_to_non_nullable
|
||||||
|
as NullablePlayerSettings,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a copy of BookSettings
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$NullablePlayerSettingsCopyWith<$Res> get playerSettings {
|
||||||
|
|
||||||
|
return $NullablePlayerSettingsCopyWith<$Res>(_self.playerSettings, (value) {
|
||||||
|
return _then(_self.copyWith(playerSettings: value));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// dart format on
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,17 @@ part of 'book_settings.dart';
|
||||||
// JsonSerializableGenerator
|
// JsonSerializableGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
_$BookSettingsImpl _$$BookSettingsImplFromJson(Map<String, dynamic> json) =>
|
_BookSettings _$BookSettingsFromJson(Map<String, dynamic> json) =>
|
||||||
_$BookSettingsImpl(
|
_BookSettings(
|
||||||
bookId: json['bookId'] as String,
|
bookId: json['bookId'] as String,
|
||||||
playerSettings: json['playerSettings'] == null
|
playerSettings: json['playerSettings'] == null
|
||||||
? const NullablePlayerSettings()
|
? const NullablePlayerSettings()
|
||||||
: NullablePlayerSettings.fromJson(
|
: NullablePlayerSettings.fromJson(
|
||||||
json['playerSettings'] as Map<String, dynamic>),
|
json['playerSettings'] as Map<String, dynamic>,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$$BookSettingsImplToJson(_$BookSettingsImpl instance) =>
|
Map<String, dynamic> _$BookSettingsToJson(_BookSettings instance) =>
|
||||||
<String, dynamic>{
|
<String, dynamic>{
|
||||||
'bookId': instance.bookId,
|
'bookId': instance.bookId,
|
||||||
'playerSettings': instance.playerSettings,
|
'playerSettings': instance.playerSettings,
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ part 'nullable_player_settings.freezed.dart';
|
||||||
part 'nullable_player_settings.g.dart';
|
part 'nullable_player_settings.g.dart';
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class NullablePlayerSettings with _$NullablePlayerSettings {
|
sealed class NullablePlayerSettings with _$NullablePlayerSettings {
|
||||||
const factory NullablePlayerSettings({
|
const factory NullablePlayerSettings({
|
||||||
MinimizedPlayerSettings? miniPlayerSettings,
|
MinimizedPlayerSettings? miniPlayerSettings,
|
||||||
ExpandedPlayerSettings? expandedPlayerSettings,
|
ExpandedPlayerSettings? expandedPlayerSettings,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// coverage:ignore-file
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// coverage:ignore-file
|
||||||
// ignore_for_file: type=lint
|
// 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
|
// 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
|
||||||
|
|
||||||
|
|
@ -9,369 +9,361 @@ part of 'nullable_player_settings.dart';
|
||||||
// FreezedGenerator
|
// FreezedGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
|
// dart format off
|
||||||
T _$identity<T>(T value) => value;
|
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#adding-getters-and-methods-to-our-models');
|
|
||||||
|
|
||||||
NullablePlayerSettings _$NullablePlayerSettingsFromJson(
|
|
||||||
Map<String, dynamic> json) {
|
|
||||||
return _NullablePlayerSettings.fromJson(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$NullablePlayerSettings {
|
mixin _$NullablePlayerSettings {
|
||||||
MinimizedPlayerSettings? get miniPlayerSettings =>
|
|
||||||
throw _privateConstructorUsedError;
|
MinimizedPlayerSettings? get miniPlayerSettings; ExpandedPlayerSettings? get expandedPlayerSettings; double? get preferredDefaultVolume; double? get preferredDefaultSpeed; List<double>? get speedOptions; SleepTimerSettings? get sleepTimerSettings; Duration? get playbackReportInterval;
|
||||||
ExpandedPlayerSettings? get expandedPlayerSettings =>
|
/// Create a copy of NullablePlayerSettings
|
||||||
throw _privateConstructorUsedError;
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
double? get preferredDefaultVolume => throw _privateConstructorUsedError;
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
double? get preferredDefaultSpeed => throw _privateConstructorUsedError;
|
@pragma('vm:prefer-inline')
|
||||||
List<double>? get speedOptions => throw _privateConstructorUsedError;
|
$NullablePlayerSettingsCopyWith<NullablePlayerSettings> get copyWith => _$NullablePlayerSettingsCopyWithImpl<NullablePlayerSettings>(this as NullablePlayerSettings, _$identity);
|
||||||
SleepTimerSettings? get sleepTimerSettings =>
|
|
||||||
throw _privateConstructorUsedError;
|
|
||||||
Duration? get playbackReportInterval => throw _privateConstructorUsedError;
|
|
||||||
|
|
||||||
/// Serializes this NullablePlayerSettings to a JSON map.
|
/// Serializes this NullablePlayerSettings to a JSON map.
|
||||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
Map<String, dynamic> toJson();
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is NullablePlayerSettings&&(identical(other.miniPlayerSettings, miniPlayerSettings) || other.miniPlayerSettings == miniPlayerSettings)&&(identical(other.expandedPlayerSettings, expandedPlayerSettings) || other.expandedPlayerSettings == expandedPlayerSettings)&&(identical(other.preferredDefaultVolume, preferredDefaultVolume) || other.preferredDefaultVolume == preferredDefaultVolume)&&(identical(other.preferredDefaultSpeed, preferredDefaultSpeed) || other.preferredDefaultSpeed == preferredDefaultSpeed)&&const DeepCollectionEquality().equals(other.speedOptions, speedOptions)&&(identical(other.sleepTimerSettings, sleepTimerSettings) || other.sleepTimerSettings == sleepTimerSettings)&&(identical(other.playbackReportInterval, playbackReportInterval) || other.playbackReportInterval == playbackReportInterval));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,miniPlayerSettings,expandedPlayerSettings,preferredDefaultVolume,preferredDefaultSpeed,const DeepCollectionEquality().hash(speedOptions),sleepTimerSettings,playbackReportInterval);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'NullablePlayerSettings(miniPlayerSettings: $miniPlayerSettings, expandedPlayerSettings: $expandedPlayerSettings, preferredDefaultVolume: $preferredDefaultVolume, preferredDefaultSpeed: $preferredDefaultSpeed, speedOptions: $speedOptions, sleepTimerSettings: $sleepTimerSettings, playbackReportInterval: $playbackReportInterval)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Create a copy of NullablePlayerSettings
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
$NullablePlayerSettingsCopyWith<NullablePlayerSettings> get copyWith =>
|
|
||||||
throw _privateConstructorUsedError;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
abstract class $NullablePlayerSettingsCopyWith<$Res> {
|
abstract mixin class $NullablePlayerSettingsCopyWith<$Res> {
|
||||||
factory $NullablePlayerSettingsCopyWith(NullablePlayerSettings value,
|
factory $NullablePlayerSettingsCopyWith(NullablePlayerSettings value, $Res Function(NullablePlayerSettings) _then) = _$NullablePlayerSettingsCopyWithImpl;
|
||||||
$Res Function(NullablePlayerSettings) then) =
|
@useResult
|
||||||
_$NullablePlayerSettingsCopyWithImpl<$Res, NullablePlayerSettings>;
|
$Res call({
|
||||||
@useResult
|
MinimizedPlayerSettings? miniPlayerSettings, ExpandedPlayerSettings? expandedPlayerSettings, double? preferredDefaultVolume, double? preferredDefaultSpeed, List<double>? speedOptions, SleepTimerSettings? sleepTimerSettings, Duration? playbackReportInterval
|
||||||
$Res call(
|
});
|
||||||
{MinimizedPlayerSettings? miniPlayerSettings,
|
|
||||||
ExpandedPlayerSettings? expandedPlayerSettings,
|
|
||||||
double? preferredDefaultVolume,
|
$MinimizedPlayerSettingsCopyWith<$Res>? get miniPlayerSettings;$ExpandedPlayerSettingsCopyWith<$Res>? get expandedPlayerSettings;$SleepTimerSettingsCopyWith<$Res>? get sleepTimerSettings;
|
||||||
double? preferredDefaultSpeed,
|
|
||||||
List<double>? speedOptions,
|
|
||||||
SleepTimerSettings? sleepTimerSettings,
|
|
||||||
Duration? playbackReportInterval});
|
|
||||||
|
|
||||||
$MinimizedPlayerSettingsCopyWith<$Res>? get miniPlayerSettings;
|
|
||||||
$ExpandedPlayerSettingsCopyWith<$Res>? get expandedPlayerSettings;
|
|
||||||
$SleepTimerSettingsCopyWith<$Res>? get sleepTimerSettings;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
class _$NullablePlayerSettingsCopyWithImpl<$Res,
|
class _$NullablePlayerSettingsCopyWithImpl<$Res>
|
||||||
$Val extends NullablePlayerSettings>
|
|
||||||
implements $NullablePlayerSettingsCopyWith<$Res> {
|
implements $NullablePlayerSettingsCopyWith<$Res> {
|
||||||
_$NullablePlayerSettingsCopyWithImpl(this._value, this._then);
|
_$NullablePlayerSettingsCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
// ignore: unused_field
|
final NullablePlayerSettings _self;
|
||||||
final $Val _value;
|
final $Res Function(NullablePlayerSettings) _then;
|
||||||
// ignore: unused_field
|
|
||||||
final $Res Function($Val) _then;
|
|
||||||
|
|
||||||
/// Create a copy of NullablePlayerSettings
|
/// Create a copy of NullablePlayerSettings
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline') @override $Res call({Object? miniPlayerSettings = freezed,Object? expandedPlayerSettings = freezed,Object? preferredDefaultVolume = freezed,Object? preferredDefaultSpeed = freezed,Object? speedOptions = freezed,Object? sleepTimerSettings = freezed,Object? playbackReportInterval = freezed,}) {
|
||||||
@override
|
return _then(_self.copyWith(
|
||||||
$Res call({
|
miniPlayerSettings: freezed == miniPlayerSettings ? _self.miniPlayerSettings : miniPlayerSettings // ignore: cast_nullable_to_non_nullable
|
||||||
Object? miniPlayerSettings = freezed,
|
as MinimizedPlayerSettings?,expandedPlayerSettings: freezed == expandedPlayerSettings ? _self.expandedPlayerSettings : expandedPlayerSettings // ignore: cast_nullable_to_non_nullable
|
||||||
Object? expandedPlayerSettings = freezed,
|
as ExpandedPlayerSettings?,preferredDefaultVolume: freezed == preferredDefaultVolume ? _self.preferredDefaultVolume : preferredDefaultVolume // ignore: cast_nullable_to_non_nullable
|
||||||
Object? preferredDefaultVolume = freezed,
|
as double?,preferredDefaultSpeed: freezed == preferredDefaultSpeed ? _self.preferredDefaultSpeed : preferredDefaultSpeed // ignore: cast_nullable_to_non_nullable
|
||||||
Object? preferredDefaultSpeed = freezed,
|
as double?,speedOptions: freezed == speedOptions ? _self.speedOptions : speedOptions // ignore: cast_nullable_to_non_nullable
|
||||||
Object? speedOptions = freezed,
|
as List<double>?,sleepTimerSettings: freezed == sleepTimerSettings ? _self.sleepTimerSettings : sleepTimerSettings // ignore: cast_nullable_to_non_nullable
|
||||||
Object? sleepTimerSettings = freezed,
|
as SleepTimerSettings?,playbackReportInterval: freezed == playbackReportInterval ? _self.playbackReportInterval : playbackReportInterval // ignore: cast_nullable_to_non_nullable
|
||||||
Object? playbackReportInterval = freezed,
|
as Duration?,
|
||||||
}) {
|
));
|
||||||
return _then(_value.copyWith(
|
}
|
||||||
miniPlayerSettings: freezed == miniPlayerSettings
|
/// Create a copy of NullablePlayerSettings
|
||||||
? _value.miniPlayerSettings
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
: miniPlayerSettings // ignore: cast_nullable_to_non_nullable
|
@override
|
||||||
as MinimizedPlayerSettings?,
|
@pragma('vm:prefer-inline')
|
||||||
expandedPlayerSettings: freezed == expandedPlayerSettings
|
$MinimizedPlayerSettingsCopyWith<$Res>? get miniPlayerSettings {
|
||||||
? _value.expandedPlayerSettings
|
if (_self.miniPlayerSettings == null) {
|
||||||
: expandedPlayerSettings // ignore: cast_nullable_to_non_nullable
|
return null;
|
||||||
as ExpandedPlayerSettings?,
|
|
||||||
preferredDefaultVolume: freezed == preferredDefaultVolume
|
|
||||||
? _value.preferredDefaultVolume
|
|
||||||
: preferredDefaultVolume // ignore: cast_nullable_to_non_nullable
|
|
||||||
as double?,
|
|
||||||
preferredDefaultSpeed: freezed == preferredDefaultSpeed
|
|
||||||
? _value.preferredDefaultSpeed
|
|
||||||
: preferredDefaultSpeed // ignore: cast_nullable_to_non_nullable
|
|
||||||
as double?,
|
|
||||||
speedOptions: freezed == speedOptions
|
|
||||||
? _value.speedOptions
|
|
||||||
: speedOptions // ignore: cast_nullable_to_non_nullable
|
|
||||||
as List<double>?,
|
|
||||||
sleepTimerSettings: freezed == sleepTimerSettings
|
|
||||||
? _value.sleepTimerSettings
|
|
||||||
: sleepTimerSettings // ignore: cast_nullable_to_non_nullable
|
|
||||||
as SleepTimerSettings?,
|
|
||||||
playbackReportInterval: freezed == playbackReportInterval
|
|
||||||
? _value.playbackReportInterval
|
|
||||||
: playbackReportInterval // ignore: cast_nullable_to_non_nullable
|
|
||||||
as Duration?,
|
|
||||||
) as $Val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a copy of NullablePlayerSettings
|
return $MinimizedPlayerSettingsCopyWith<$Res>(_self.miniPlayerSettings!, (value) {
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
return _then(_self.copyWith(miniPlayerSettings: value));
|
||||||
@override
|
});
|
||||||
@pragma('vm:prefer-inline')
|
}/// Create a copy of NullablePlayerSettings
|
||||||
$MinimizedPlayerSettingsCopyWith<$Res>? get miniPlayerSettings {
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
if (_value.miniPlayerSettings == null) {
|
@override
|
||||||
return null;
|
@pragma('vm:prefer-inline')
|
||||||
}
|
$ExpandedPlayerSettingsCopyWith<$Res>? get expandedPlayerSettings {
|
||||||
|
if (_self.expandedPlayerSettings == null) {
|
||||||
return $MinimizedPlayerSettingsCopyWith<$Res>(_value.miniPlayerSettings!,
|
return null;
|
||||||
(value) {
|
|
||||||
return _then(_value.copyWith(miniPlayerSettings: value) as $Val);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a copy of NullablePlayerSettings
|
return $ExpandedPlayerSettingsCopyWith<$Res>(_self.expandedPlayerSettings!, (value) {
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
return _then(_self.copyWith(expandedPlayerSettings: value));
|
||||||
@override
|
});
|
||||||
@pragma('vm:prefer-inline')
|
}/// Create a copy of NullablePlayerSettings
|
||||||
$ExpandedPlayerSettingsCopyWith<$Res>? get expandedPlayerSettings {
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
if (_value.expandedPlayerSettings == null) {
|
@override
|
||||||
return null;
|
@pragma('vm:prefer-inline')
|
||||||
}
|
$SleepTimerSettingsCopyWith<$Res>? get sleepTimerSettings {
|
||||||
|
if (_self.sleepTimerSettings == null) {
|
||||||
return $ExpandedPlayerSettingsCopyWith<$Res>(_value.expandedPlayerSettings!,
|
return null;
|
||||||
(value) {
|
|
||||||
return _then(_value.copyWith(expandedPlayerSettings: value) as $Val);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a copy of NullablePlayerSettings
|
return $SleepTimerSettingsCopyWith<$Res>(_self.sleepTimerSettings!, (value) {
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
return _then(_self.copyWith(sleepTimerSettings: value));
|
||||||
@override
|
});
|
||||||
@pragma('vm:prefer-inline')
|
}
|
||||||
$SleepTimerSettingsCopyWith<$Res>? get sleepTimerSettings {
|
|
||||||
if (_value.sleepTimerSettings == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $SleepTimerSettingsCopyWith<$Res>(_value.sleepTimerSettings!,
|
|
||||||
(value) {
|
|
||||||
return _then(_value.copyWith(sleepTimerSettings: value) as $Val);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
abstract class _$$NullablePlayerSettingsImplCopyWith<$Res>
|
|
||||||
implements $NullablePlayerSettingsCopyWith<$Res> {
|
|
||||||
factory _$$NullablePlayerSettingsImplCopyWith(
|
|
||||||
_$NullablePlayerSettingsImpl value,
|
|
||||||
$Res Function(_$NullablePlayerSettingsImpl) then) =
|
|
||||||
__$$NullablePlayerSettingsImplCopyWithImpl<$Res>;
|
|
||||||
@override
|
|
||||||
@useResult
|
|
||||||
$Res call(
|
|
||||||
{MinimizedPlayerSettings? miniPlayerSettings,
|
|
||||||
ExpandedPlayerSettings? expandedPlayerSettings,
|
|
||||||
double? preferredDefaultVolume,
|
|
||||||
double? preferredDefaultSpeed,
|
|
||||||
List<double>? speedOptions,
|
|
||||||
SleepTimerSettings? sleepTimerSettings,
|
|
||||||
Duration? playbackReportInterval});
|
|
||||||
|
|
||||||
@override
|
/// Adds pattern-matching-related methods to [NullablePlayerSettings].
|
||||||
$MinimizedPlayerSettingsCopyWith<$Res>? get miniPlayerSettings;
|
extension NullablePlayerSettingsPatterns on NullablePlayerSettings {
|
||||||
@override
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
$ExpandedPlayerSettingsCopyWith<$Res>? get expandedPlayerSettings;
|
///
|
||||||
@override
|
/// It is equivalent to doing:
|
||||||
$SleepTimerSettingsCopyWith<$Res>? get sleepTimerSettings;
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _NullablePlayerSettings value)? $default,{required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _NullablePlayerSettings() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// Callbacks receives the raw object, upcasted.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case final Subclass2 value:
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _NullablePlayerSettings value) $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _NullablePlayerSettings():
|
||||||
|
return $default(_that);}
|
||||||
|
}
|
||||||
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _NullablePlayerSettings value)? $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _NullablePlayerSettings() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to an `orElse` callback.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( MinimizedPlayerSettings? miniPlayerSettings, ExpandedPlayerSettings? expandedPlayerSettings, double? preferredDefaultVolume, double? preferredDefaultSpeed, List<double>? speedOptions, SleepTimerSettings? sleepTimerSettings, Duration? playbackReportInterval)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _NullablePlayerSettings() when $default != null:
|
||||||
|
return $default(_that.miniPlayerSettings,_that.expandedPlayerSettings,_that.preferredDefaultVolume,_that.preferredDefaultSpeed,_that.speedOptions,_that.sleepTimerSettings,_that.playbackReportInterval);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// As opposed to `map`, this offers destructuring.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case Subclass2(:final field2):
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( MinimizedPlayerSettings? miniPlayerSettings, ExpandedPlayerSettings? expandedPlayerSettings, double? preferredDefaultVolume, double? preferredDefaultSpeed, List<double>? speedOptions, SleepTimerSettings? sleepTimerSettings, Duration? playbackReportInterval) $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _NullablePlayerSettings():
|
||||||
|
return $default(_that.miniPlayerSettings,_that.expandedPlayerSettings,_that.preferredDefaultVolume,_that.preferredDefaultSpeed,_that.speedOptions,_that.sleepTimerSettings,_that.playbackReportInterval);}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to returning `null`
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( MinimizedPlayerSettings? miniPlayerSettings, ExpandedPlayerSettings? expandedPlayerSettings, double? preferredDefaultVolume, double? preferredDefaultSpeed, List<double>? speedOptions, SleepTimerSettings? sleepTimerSettings, Duration? playbackReportInterval)? $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _NullablePlayerSettings() when $default != null:
|
||||||
|
return $default(_that.miniPlayerSettings,_that.expandedPlayerSettings,_that.preferredDefaultVolume,_that.preferredDefaultSpeed,_that.speedOptions,_that.sleepTimerSettings,_that.playbackReportInterval);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
class __$$NullablePlayerSettingsImplCopyWithImpl<$Res>
|
|
||||||
extends _$NullablePlayerSettingsCopyWithImpl<$Res,
|
|
||||||
_$NullablePlayerSettingsImpl>
|
|
||||||
implements _$$NullablePlayerSettingsImplCopyWith<$Res> {
|
|
||||||
__$$NullablePlayerSettingsImplCopyWithImpl(
|
|
||||||
_$NullablePlayerSettingsImpl _value,
|
|
||||||
$Res Function(_$NullablePlayerSettingsImpl) _then)
|
|
||||||
: super(_value, _then);
|
|
||||||
|
|
||||||
/// Create a copy of NullablePlayerSettings
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
@override
|
|
||||||
$Res call({
|
|
||||||
Object? miniPlayerSettings = freezed,
|
|
||||||
Object? expandedPlayerSettings = freezed,
|
|
||||||
Object? preferredDefaultVolume = freezed,
|
|
||||||
Object? preferredDefaultSpeed = freezed,
|
|
||||||
Object? speedOptions = freezed,
|
|
||||||
Object? sleepTimerSettings = freezed,
|
|
||||||
Object? playbackReportInterval = freezed,
|
|
||||||
}) {
|
|
||||||
return _then(_$NullablePlayerSettingsImpl(
|
|
||||||
miniPlayerSettings: freezed == miniPlayerSettings
|
|
||||||
? _value.miniPlayerSettings
|
|
||||||
: miniPlayerSettings // ignore: cast_nullable_to_non_nullable
|
|
||||||
as MinimizedPlayerSettings?,
|
|
||||||
expandedPlayerSettings: freezed == expandedPlayerSettings
|
|
||||||
? _value.expandedPlayerSettings
|
|
||||||
: expandedPlayerSettings // ignore: cast_nullable_to_non_nullable
|
|
||||||
as ExpandedPlayerSettings?,
|
|
||||||
preferredDefaultVolume: freezed == preferredDefaultVolume
|
|
||||||
? _value.preferredDefaultVolume
|
|
||||||
: preferredDefaultVolume // ignore: cast_nullable_to_non_nullable
|
|
||||||
as double?,
|
|
||||||
preferredDefaultSpeed: freezed == preferredDefaultSpeed
|
|
||||||
? _value.preferredDefaultSpeed
|
|
||||||
: preferredDefaultSpeed // ignore: cast_nullable_to_non_nullable
|
|
||||||
as double?,
|
|
||||||
speedOptions: freezed == speedOptions
|
|
||||||
? _value._speedOptions
|
|
||||||
: speedOptions // ignore: cast_nullable_to_non_nullable
|
|
||||||
as List<double>?,
|
|
||||||
sleepTimerSettings: freezed == sleepTimerSettings
|
|
||||||
? _value.sleepTimerSettings
|
|
||||||
: sleepTimerSettings // ignore: cast_nullable_to_non_nullable
|
|
||||||
as SleepTimerSettings?,
|
|
||||||
playbackReportInterval: freezed == playbackReportInterval
|
|
||||||
? _value.playbackReportInterval
|
|
||||||
: playbackReportInterval // ignore: cast_nullable_to_non_nullable
|
|
||||||
as Duration?,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
class _$NullablePlayerSettingsImpl implements _NullablePlayerSettings {
|
|
||||||
const _$NullablePlayerSettingsImpl(
|
|
||||||
{this.miniPlayerSettings,
|
|
||||||
this.expandedPlayerSettings,
|
|
||||||
this.preferredDefaultVolume,
|
|
||||||
this.preferredDefaultSpeed,
|
|
||||||
final List<double>? speedOptions,
|
|
||||||
this.sleepTimerSettings,
|
|
||||||
this.playbackReportInterval})
|
|
||||||
: _speedOptions = speedOptions;
|
|
||||||
|
|
||||||
factory _$NullablePlayerSettingsImpl.fromJson(Map<String, dynamic> json) =>
|
class _NullablePlayerSettings implements NullablePlayerSettings {
|
||||||
_$$NullablePlayerSettingsImplFromJson(json);
|
const _NullablePlayerSettings({this.miniPlayerSettings, this.expandedPlayerSettings, this.preferredDefaultVolume, this.preferredDefaultSpeed, final List<double>? speedOptions, this.sleepTimerSettings, this.playbackReportInterval}): _speedOptions = speedOptions;
|
||||||
|
factory _NullablePlayerSettings.fromJson(Map<String, dynamic> json) => _$NullablePlayerSettingsFromJson(json);
|
||||||
|
|
||||||
@override
|
@override final MinimizedPlayerSettings? miniPlayerSettings;
|
||||||
final MinimizedPlayerSettings? miniPlayerSettings;
|
@override final ExpandedPlayerSettings? expandedPlayerSettings;
|
||||||
@override
|
@override final double? preferredDefaultVolume;
|
||||||
final ExpandedPlayerSettings? expandedPlayerSettings;
|
@override final double? preferredDefaultSpeed;
|
||||||
@override
|
final List<double>? _speedOptions;
|
||||||
final double? preferredDefaultVolume;
|
@override List<double>? get speedOptions {
|
||||||
@override
|
final value = _speedOptions;
|
||||||
final double? preferredDefaultSpeed;
|
if (value == null) return null;
|
||||||
final List<double>? _speedOptions;
|
if (_speedOptions is EqualUnmodifiableListView) return _speedOptions;
|
||||||
@override
|
// ignore: implicit_dynamic_type
|
||||||
List<double>? get speedOptions {
|
return EqualUnmodifiableListView(value);
|
||||||
final value = _speedOptions;
|
|
||||||
if (value == null) return null;
|
|
||||||
if (_speedOptions is EqualUnmodifiableListView) return _speedOptions;
|
|
||||||
// ignore: implicit_dynamic_type
|
|
||||||
return EqualUnmodifiableListView(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
final SleepTimerSettings? sleepTimerSettings;
|
|
||||||
@override
|
|
||||||
final Duration? playbackReportInterval;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return 'NullablePlayerSettings(miniPlayerSettings: $miniPlayerSettings, expandedPlayerSettings: $expandedPlayerSettings, preferredDefaultVolume: $preferredDefaultVolume, preferredDefaultSpeed: $preferredDefaultSpeed, speedOptions: $speedOptions, sleepTimerSettings: $sleepTimerSettings, playbackReportInterval: $playbackReportInterval)';
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) {
|
|
||||||
return identical(this, other) ||
|
|
||||||
(other.runtimeType == runtimeType &&
|
|
||||||
other is _$NullablePlayerSettingsImpl &&
|
|
||||||
(identical(other.miniPlayerSettings, miniPlayerSettings) ||
|
|
||||||
other.miniPlayerSettings == miniPlayerSettings) &&
|
|
||||||
(identical(other.expandedPlayerSettings, expandedPlayerSettings) ||
|
|
||||||
other.expandedPlayerSettings == expandedPlayerSettings) &&
|
|
||||||
(identical(other.preferredDefaultVolume, preferredDefaultVolume) ||
|
|
||||||
other.preferredDefaultVolume == preferredDefaultVolume) &&
|
|
||||||
(identical(other.preferredDefaultSpeed, preferredDefaultSpeed) ||
|
|
||||||
other.preferredDefaultSpeed == preferredDefaultSpeed) &&
|
|
||||||
const DeepCollectionEquality()
|
|
||||||
.equals(other._speedOptions, _speedOptions) &&
|
|
||||||
(identical(other.sleepTimerSettings, sleepTimerSettings) ||
|
|
||||||
other.sleepTimerSettings == sleepTimerSettings) &&
|
|
||||||
(identical(other.playbackReportInterval, playbackReportInterval) ||
|
|
||||||
other.playbackReportInterval == playbackReportInterval));
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
|
||||||
int get hashCode => Object.hash(
|
|
||||||
runtimeType,
|
|
||||||
miniPlayerSettings,
|
|
||||||
expandedPlayerSettings,
|
|
||||||
preferredDefaultVolume,
|
|
||||||
preferredDefaultSpeed,
|
|
||||||
const DeepCollectionEquality().hash(_speedOptions),
|
|
||||||
sleepTimerSettings,
|
|
||||||
playbackReportInterval);
|
|
||||||
|
|
||||||
/// Create a copy of NullablePlayerSettings
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
_$$NullablePlayerSettingsImplCopyWith<_$NullablePlayerSettingsImpl>
|
|
||||||
get copyWith => __$$NullablePlayerSettingsImplCopyWithImpl<
|
|
||||||
_$NullablePlayerSettingsImpl>(this, _$identity);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Map<String, dynamic> toJson() {
|
|
||||||
return _$$NullablePlayerSettingsImplToJson(
|
|
||||||
this,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class _NullablePlayerSettings implements NullablePlayerSettings {
|
@override final SleepTimerSettings? sleepTimerSettings;
|
||||||
const factory _NullablePlayerSettings(
|
@override final Duration? playbackReportInterval;
|
||||||
{final MinimizedPlayerSettings? miniPlayerSettings,
|
|
||||||
final ExpandedPlayerSettings? expandedPlayerSettings,
|
|
||||||
final double? preferredDefaultVolume,
|
|
||||||
final double? preferredDefaultSpeed,
|
|
||||||
final List<double>? speedOptions,
|
|
||||||
final SleepTimerSettings? sleepTimerSettings,
|
|
||||||
final Duration? playbackReportInterval}) = _$NullablePlayerSettingsImpl;
|
|
||||||
|
|
||||||
factory _NullablePlayerSettings.fromJson(Map<String, dynamic> json) =
|
/// Create a copy of NullablePlayerSettings
|
||||||
_$NullablePlayerSettingsImpl.fromJson;
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$NullablePlayerSettingsCopyWith<_NullablePlayerSettings> get copyWith => __$NullablePlayerSettingsCopyWithImpl<_NullablePlayerSettings>(this, _$identity);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
MinimizedPlayerSettings? get miniPlayerSettings;
|
Map<String, dynamic> toJson() {
|
||||||
@override
|
return _$NullablePlayerSettingsToJson(this, );
|
||||||
ExpandedPlayerSettings? get expandedPlayerSettings;
|
|
||||||
@override
|
|
||||||
double? get preferredDefaultVolume;
|
|
||||||
@override
|
|
||||||
double? get preferredDefaultSpeed;
|
|
||||||
@override
|
|
||||||
List<double>? get speedOptions;
|
|
||||||
@override
|
|
||||||
SleepTimerSettings? get sleepTimerSettings;
|
|
||||||
@override
|
|
||||||
Duration? get playbackReportInterval;
|
|
||||||
|
|
||||||
/// Create a copy of NullablePlayerSettings
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
_$$NullablePlayerSettingsImplCopyWith<_$NullablePlayerSettingsImpl>
|
|
||||||
get copyWith => throw _privateConstructorUsedError;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _NullablePlayerSettings&&(identical(other.miniPlayerSettings, miniPlayerSettings) || other.miniPlayerSettings == miniPlayerSettings)&&(identical(other.expandedPlayerSettings, expandedPlayerSettings) || other.expandedPlayerSettings == expandedPlayerSettings)&&(identical(other.preferredDefaultVolume, preferredDefaultVolume) || other.preferredDefaultVolume == preferredDefaultVolume)&&(identical(other.preferredDefaultSpeed, preferredDefaultSpeed) || other.preferredDefaultSpeed == preferredDefaultSpeed)&&const DeepCollectionEquality().equals(other._speedOptions, _speedOptions)&&(identical(other.sleepTimerSettings, sleepTimerSettings) || other.sleepTimerSettings == sleepTimerSettings)&&(identical(other.playbackReportInterval, playbackReportInterval) || other.playbackReportInterval == playbackReportInterval));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,miniPlayerSettings,expandedPlayerSettings,preferredDefaultVolume,preferredDefaultSpeed,const DeepCollectionEquality().hash(_speedOptions),sleepTimerSettings,playbackReportInterval);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'NullablePlayerSettings(miniPlayerSettings: $miniPlayerSettings, expandedPlayerSettings: $expandedPlayerSettings, preferredDefaultVolume: $preferredDefaultVolume, preferredDefaultSpeed: $preferredDefaultSpeed, speedOptions: $speedOptions, sleepTimerSettings: $sleepTimerSettings, playbackReportInterval: $playbackReportInterval)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$NullablePlayerSettingsCopyWith<$Res> implements $NullablePlayerSettingsCopyWith<$Res> {
|
||||||
|
factory _$NullablePlayerSettingsCopyWith(_NullablePlayerSettings value, $Res Function(_NullablePlayerSettings) _then) = __$NullablePlayerSettingsCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
MinimizedPlayerSettings? miniPlayerSettings, ExpandedPlayerSettings? expandedPlayerSettings, double? preferredDefaultVolume, double? preferredDefaultSpeed, List<double>? speedOptions, SleepTimerSettings? sleepTimerSettings, Duration? playbackReportInterval
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@override $MinimizedPlayerSettingsCopyWith<$Res>? get miniPlayerSettings;@override $ExpandedPlayerSettingsCopyWith<$Res>? get expandedPlayerSettings;@override $SleepTimerSettingsCopyWith<$Res>? get sleepTimerSettings;
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$NullablePlayerSettingsCopyWithImpl<$Res>
|
||||||
|
implements _$NullablePlayerSettingsCopyWith<$Res> {
|
||||||
|
__$NullablePlayerSettingsCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _NullablePlayerSettings _self;
|
||||||
|
final $Res Function(_NullablePlayerSettings) _then;
|
||||||
|
|
||||||
|
/// Create a copy of NullablePlayerSettings
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? miniPlayerSettings = freezed,Object? expandedPlayerSettings = freezed,Object? preferredDefaultVolume = freezed,Object? preferredDefaultSpeed = freezed,Object? speedOptions = freezed,Object? sleepTimerSettings = freezed,Object? playbackReportInterval = freezed,}) {
|
||||||
|
return _then(_NullablePlayerSettings(
|
||||||
|
miniPlayerSettings: freezed == miniPlayerSettings ? _self.miniPlayerSettings : miniPlayerSettings // ignore: cast_nullable_to_non_nullable
|
||||||
|
as MinimizedPlayerSettings?,expandedPlayerSettings: freezed == expandedPlayerSettings ? _self.expandedPlayerSettings : expandedPlayerSettings // ignore: cast_nullable_to_non_nullable
|
||||||
|
as ExpandedPlayerSettings?,preferredDefaultVolume: freezed == preferredDefaultVolume ? _self.preferredDefaultVolume : preferredDefaultVolume // ignore: cast_nullable_to_non_nullable
|
||||||
|
as double?,preferredDefaultSpeed: freezed == preferredDefaultSpeed ? _self.preferredDefaultSpeed : preferredDefaultSpeed // ignore: cast_nullable_to_non_nullable
|
||||||
|
as double?,speedOptions: freezed == speedOptions ? _self._speedOptions : speedOptions // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<double>?,sleepTimerSettings: freezed == sleepTimerSettings ? _self.sleepTimerSettings : sleepTimerSettings // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SleepTimerSettings?,playbackReportInterval: freezed == playbackReportInterval ? _self.playbackReportInterval : playbackReportInterval // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Duration?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a copy of NullablePlayerSettings
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$MinimizedPlayerSettingsCopyWith<$Res>? get miniPlayerSettings {
|
||||||
|
if (_self.miniPlayerSettings == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $MinimizedPlayerSettingsCopyWith<$Res>(_self.miniPlayerSettings!, (value) {
|
||||||
|
return _then(_self.copyWith(miniPlayerSettings: value));
|
||||||
|
});
|
||||||
|
}/// Create a copy of NullablePlayerSettings
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$ExpandedPlayerSettingsCopyWith<$Res>? get expandedPlayerSettings {
|
||||||
|
if (_self.expandedPlayerSettings == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ExpandedPlayerSettingsCopyWith<$Res>(_self.expandedPlayerSettings!, (value) {
|
||||||
|
return _then(_self.copyWith(expandedPlayerSettings: value));
|
||||||
|
});
|
||||||
|
}/// Create a copy of NullablePlayerSettings
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SleepTimerSettingsCopyWith<$Res>? get sleepTimerSettings {
|
||||||
|
if (_self.sleepTimerSettings == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SleepTimerSettingsCopyWith<$Res>(_self.sleepTimerSettings!, (value) {
|
||||||
|
return _then(_self.copyWith(sleepTimerSettings: value));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// dart format on
|
||||||
|
|
|
||||||
|
|
@ -6,42 +6,42 @@ part of 'nullable_player_settings.dart';
|
||||||
// JsonSerializableGenerator
|
// JsonSerializableGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
_$NullablePlayerSettingsImpl _$$NullablePlayerSettingsImplFromJson(
|
_NullablePlayerSettings _$NullablePlayerSettingsFromJson(
|
||||||
Map<String, dynamic> json) =>
|
Map<String, dynamic> json,
|
||||||
_$NullablePlayerSettingsImpl(
|
) => _NullablePlayerSettings(
|
||||||
miniPlayerSettings: json['miniPlayerSettings'] == null
|
miniPlayerSettings: json['miniPlayerSettings'] == null
|
||||||
? null
|
? null
|
||||||
: MinimizedPlayerSettings.fromJson(
|
: MinimizedPlayerSettings.fromJson(
|
||||||
json['miniPlayerSettings'] as Map<String, dynamic>),
|
json['miniPlayerSettings'] as Map<String, dynamic>,
|
||||||
expandedPlayerSettings: json['expandedPlayerSettings'] == null
|
),
|
||||||
? null
|
expandedPlayerSettings: json['expandedPlayerSettings'] == null
|
||||||
: ExpandedPlayerSettings.fromJson(
|
? null
|
||||||
json['expandedPlayerSettings'] as Map<String, dynamic>),
|
: ExpandedPlayerSettings.fromJson(
|
||||||
preferredDefaultVolume:
|
json['expandedPlayerSettings'] as Map<String, dynamic>,
|
||||||
(json['preferredDefaultVolume'] as num?)?.toDouble(),
|
),
|
||||||
preferredDefaultSpeed:
|
preferredDefaultVolume: (json['preferredDefaultVolume'] as num?)?.toDouble(),
|
||||||
(json['preferredDefaultSpeed'] as num?)?.toDouble(),
|
preferredDefaultSpeed: (json['preferredDefaultSpeed'] as num?)?.toDouble(),
|
||||||
speedOptions: (json['speedOptions'] as List<dynamic>?)
|
speedOptions: (json['speedOptions'] as List<dynamic>?)
|
||||||
?.map((e) => (e as num).toDouble())
|
?.map((e) => (e as num).toDouble())
|
||||||
.toList(),
|
.toList(),
|
||||||
sleepTimerSettings: json['sleepTimerSettings'] == null
|
sleepTimerSettings: json['sleepTimerSettings'] == null
|
||||||
? null
|
? null
|
||||||
: SleepTimerSettings.fromJson(
|
: SleepTimerSettings.fromJson(
|
||||||
json['sleepTimerSettings'] as Map<String, dynamic>),
|
json['sleepTimerSettings'] as Map<String, dynamic>,
|
||||||
playbackReportInterval: json['playbackReportInterval'] == null
|
),
|
||||||
? null
|
playbackReportInterval: json['playbackReportInterval'] == null
|
||||||
: Duration(
|
? null
|
||||||
microseconds: (json['playbackReportInterval'] as num).toInt()),
|
: Duration(microseconds: (json['playbackReportInterval'] as num).toInt()),
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$$NullablePlayerSettingsImplToJson(
|
Map<String, dynamic> _$NullablePlayerSettingsToJson(
|
||||||
_$NullablePlayerSettingsImpl instance) =>
|
_NullablePlayerSettings instance,
|
||||||
<String, dynamic>{
|
) => <String, dynamic>{
|
||||||
'miniPlayerSettings': instance.miniPlayerSettings,
|
'miniPlayerSettings': instance.miniPlayerSettings,
|
||||||
'expandedPlayerSettings': instance.expandedPlayerSettings,
|
'expandedPlayerSettings': instance.expandedPlayerSettings,
|
||||||
'preferredDefaultVolume': instance.preferredDefaultVolume,
|
'preferredDefaultVolume': instance.preferredDefaultVolume,
|
||||||
'preferredDefaultSpeed': instance.preferredDefaultSpeed,
|
'preferredDefaultSpeed': instance.preferredDefaultSpeed,
|
||||||
'speedOptions': instance.speedOptions,
|
'speedOptions': instance.speedOptions,
|
||||||
'sleepTimerSettings': instance.sleepTimerSettings,
|
'sleepTimerSettings': instance.sleepTimerSettings,
|
||||||
'playbackReportInterval': instance.playbackReportInterval?.inMicroseconds,
|
'playbackReportInterval': instance.playbackReportInterval?.inMicroseconds,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -6,171 +6,102 @@ part of 'book_settings_provider.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$bookSettingsHash() => r'b976df954edf98ec6ccb3eb41e9d07dd4a9193eb';
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint, type=warning
|
||||||
|
|
||||||
/// 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class _$BookSettings
|
|
||||||
extends BuildlessAutoDisposeNotifier<model.BookSettings> {
|
|
||||||
late final String bookId;
|
|
||||||
|
|
||||||
model.BookSettings build(
|
|
||||||
String bookId,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See also [BookSettings].
|
|
||||||
@ProviderFor(BookSettings)
|
@ProviderFor(BookSettings)
|
||||||
const bookSettingsProvider = BookSettingsFamily();
|
final bookSettingsProvider = BookSettingsFamily._();
|
||||||
|
|
||||||
/// See also [BookSettings].
|
final class BookSettingsProvider
|
||||||
class BookSettingsFamily extends Family<model.BookSettings> {
|
extends $NotifierProvider<BookSettings, model.BookSettings> {
|
||||||
/// See also [BookSettings].
|
BookSettingsProvider._({
|
||||||
const BookSettingsFamily();
|
required BookSettingsFamily super.from,
|
||||||
|
required String super.argument,
|
||||||
|
}) : super(
|
||||||
|
retry: null,
|
||||||
|
name: r'bookSettingsProvider',
|
||||||
|
isAutoDispose: true,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
/// See also [BookSettings].
|
@override
|
||||||
BookSettingsProvider call(
|
String debugGetCreateSourceHash() => _$bookSettingsHash();
|
||||||
String bookId,
|
|
||||||
) {
|
@override
|
||||||
return BookSettingsProvider(
|
String toString() {
|
||||||
bookId,
|
return r'bookSettingsProvider'
|
||||||
);
|
''
|
||||||
|
'($argument)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@$internal
|
||||||
@override
|
@override
|
||||||
BookSettingsProvider getProviderOverride(
|
BookSettings create() => BookSettings();
|
||||||
covariant BookSettingsProvider provider,
|
|
||||||
) {
|
|
||||||
return call(
|
|
||||||
provider.bookId,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
/// {@macro riverpod.override_with_value}
|
||||||
|
Override overrideWithValue(model.BookSettings value) {
|
||||||
@override
|
return $ProviderOverride(
|
||||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
|
||||||
|
|
||||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
|
||||||
_allTransitiveDependencies;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String? get name => r'bookSettingsProvider';
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See also [BookSettings].
|
|
||||||
class BookSettingsProvider
|
|
||||||
extends AutoDisposeNotifierProviderImpl<BookSettings, model.BookSettings> {
|
|
||||||
/// See also [BookSettings].
|
|
||||||
BookSettingsProvider(
|
|
||||||
String bookId,
|
|
||||||
) : this._internal(
|
|
||||||
() => BookSettings()..bookId = bookId,
|
|
||||||
from: bookSettingsProvider,
|
|
||||||
name: r'bookSettingsProvider',
|
|
||||||
debugGetCreateSourceHash:
|
|
||||||
const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$bookSettingsHash,
|
|
||||||
dependencies: BookSettingsFamily._dependencies,
|
|
||||||
allTransitiveDependencies:
|
|
||||||
BookSettingsFamily._allTransitiveDependencies,
|
|
||||||
bookId: bookId,
|
|
||||||
);
|
|
||||||
|
|
||||||
BookSettingsProvider._internal(
|
|
||||||
super._createNotifier, {
|
|
||||||
required super.name,
|
|
||||||
required super.dependencies,
|
|
||||||
required super.allTransitiveDependencies,
|
|
||||||
required super.debugGetCreateSourceHash,
|
|
||||||
required super.from,
|
|
||||||
required this.bookId,
|
|
||||||
}) : super.internal();
|
|
||||||
|
|
||||||
final String bookId;
|
|
||||||
|
|
||||||
@override
|
|
||||||
model.BookSettings runNotifierBuild(
|
|
||||||
covariant BookSettings notifier,
|
|
||||||
) {
|
|
||||||
return notifier.build(
|
|
||||||
bookId,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Override overrideWith(BookSettings Function() create) {
|
|
||||||
return ProviderOverride(
|
|
||||||
origin: this,
|
origin: this,
|
||||||
override: BookSettingsProvider._internal(
|
providerOverride: $SyncValueProvider<model.BookSettings>(value),
|
||||||
() => create()..bookId = bookId,
|
|
||||||
from: from,
|
|
||||||
name: null,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
debugGetCreateSourceHash: null,
|
|
||||||
bookId: bookId,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
AutoDisposeNotifierProviderElement<BookSettings, model.BookSettings>
|
|
||||||
createElement() {
|
|
||||||
return _BookSettingsProviderElement(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return other is BookSettingsProvider && other.bookId == bookId;
|
return other is BookSettingsProvider && other.argument == argument;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode {
|
int get hashCode {
|
||||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
return argument.hashCode;
|
||||||
hash = _SystemHash.combine(hash, bookId.hashCode);
|
|
||||||
|
|
||||||
return _SystemHash.finish(hash);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
String _$bookSettingsHash() => r'b976df954edf98ec6ccb3eb41e9d07dd4a9193eb';
|
||||||
// ignore: unused_element
|
|
||||||
mixin BookSettingsRef on AutoDisposeNotifierProviderRef<model.BookSettings> {
|
|
||||||
/// The parameter `bookId` of this provider.
|
|
||||||
String get bookId;
|
|
||||||
}
|
|
||||||
|
|
||||||
class _BookSettingsProviderElement
|
final class BookSettingsFamily extends $Family
|
||||||
extends AutoDisposeNotifierProviderElement<BookSettings, model.BookSettings>
|
with
|
||||||
with BookSettingsRef {
|
$ClassFamilyOverride<
|
||||||
_BookSettingsProviderElement(super.provider);
|
BookSettings,
|
||||||
|
model.BookSettings,
|
||||||
|
model.BookSettings,
|
||||||
|
model.BookSettings,
|
||||||
|
String
|
||||||
|
> {
|
||||||
|
BookSettingsFamily._()
|
||||||
|
: super(
|
||||||
|
retry: null,
|
||||||
|
name: r'bookSettingsProvider',
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
isAutoDispose: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
BookSettingsProvider call(String bookId) =>
|
||||||
|
BookSettingsProvider._(argument: bookId, from: this);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get bookId => (origin as BookSettingsProvider).bookId;
|
String toString() => r'bookSettingsProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _$BookSettings extends $Notifier<model.BookSettings> {
|
||||||
|
late final _$args = ref.$arg as String;
|
||||||
|
String get bookId => _$args;
|
||||||
|
|
||||||
|
model.BookSettings build(String bookId);
|
||||||
|
@$mustCallSuper
|
||||||
|
@override
|
||||||
|
void runBuild() {
|
||||||
|
final ref = this.ref as $Ref<model.BookSettings, model.BookSettings>;
|
||||||
|
final element =
|
||||||
|
ref.element
|
||||||
|
as $ClassProviderElement<
|
||||||
|
AnyNotifier<model.BookSettings, model.BookSettings>,
|
||||||
|
model.BookSettings,
|
||||||
|
Object?,
|
||||||
|
Object?
|
||||||
|
>;
|
||||||
|
element.handleCreate(ref, () => build(_$args));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 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
|
|
||||||
|
|
|
||||||
|
|
@ -126,9 +126,7 @@ class PlaybackReporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> tryReportPlayback(_) async {
|
Future<void> tryReportPlayback(_) async {
|
||||||
_logger.fine(
|
_logger.fine('callback called when elapsed ${_stopwatch.elapsed}');
|
||||||
'callback called when elapsed ${_stopwatch.elapsed}',
|
|
||||||
);
|
|
||||||
if (player.book != null &&
|
if (player.book != null &&
|
||||||
player.positionInBook >=
|
player.positionInBook >=
|
||||||
player.book!.duration - markCompleteWhenTimeLeft) {
|
player.book!.duration - markCompleteWhenTimeLeft) {
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,9 @@ class PlaybackReporter extends _$PlaybackReporter {
|
||||||
final deviceName = await ref.watch(deviceNameProvider.future);
|
final deviceName = await ref.watch(deviceNameProvider.future);
|
||||||
final deviceModel = await ref.watch(deviceModelProvider.future);
|
final deviceModel = await ref.watch(deviceModelProvider.future);
|
||||||
final deviceSdkVersion = await ref.watch(deviceSdkVersionProvider.future);
|
final deviceSdkVersion = await ref.watch(deviceSdkVersionProvider.future);
|
||||||
final deviceManufacturer =
|
final deviceManufacturer = await ref.watch(
|
||||||
await ref.watch(deviceManufacturerProvider.future);
|
deviceManufacturerProvider.future,
|
||||||
|
);
|
||||||
|
|
||||||
final reporter = core.PlaybackReporter(
|
final reporter = core.PlaybackReporter(
|
||||||
player,
|
player,
|
||||||
|
|
|
||||||
|
|
@ -6,21 +6,55 @@ part of 'playback_reporter_provider.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint, type=warning
|
||||||
|
|
||||||
|
@ProviderFor(PlaybackReporter)
|
||||||
|
final playbackReporterProvider = PlaybackReporterProvider._();
|
||||||
|
|
||||||
|
final class PlaybackReporterProvider
|
||||||
|
extends $AsyncNotifierProvider<PlaybackReporter, core.PlaybackReporter> {
|
||||||
|
PlaybackReporterProvider._()
|
||||||
|
: super(
|
||||||
|
from: null,
|
||||||
|
argument: null,
|
||||||
|
retry: null,
|
||||||
|
name: r'playbackReporterProvider',
|
||||||
|
isAutoDispose: false,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$playbackReporterHash();
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
PlaybackReporter create() => PlaybackReporter();
|
||||||
|
}
|
||||||
|
|
||||||
String _$playbackReporterHash() => r'f5436d652e51c37bcc684acdaec94e17a97e68e5';
|
String _$playbackReporterHash() => r'f5436d652e51c37bcc684acdaec94e17a97e68e5';
|
||||||
|
|
||||||
/// See also [PlaybackReporter].
|
abstract class _$PlaybackReporter
|
||||||
@ProviderFor(PlaybackReporter)
|
extends $AsyncNotifier<core.PlaybackReporter> {
|
||||||
final playbackReporterProvider =
|
FutureOr<core.PlaybackReporter> build();
|
||||||
AsyncNotifierProvider<PlaybackReporter, core.PlaybackReporter>.internal(
|
@$mustCallSuper
|
||||||
PlaybackReporter.new,
|
@override
|
||||||
name: r'playbackReporterProvider',
|
void runBuild() {
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
final ref =
|
||||||
? null
|
this.ref
|
||||||
: _$playbackReporterHash,
|
as $Ref<AsyncValue<core.PlaybackReporter>, core.PlaybackReporter>;
|
||||||
dependencies: null,
|
final element =
|
||||||
allTransitiveDependencies: null,
|
ref.element
|
||||||
);
|
as $ClassProviderElement<
|
||||||
|
AnyNotifier<
|
||||||
typedef _$PlaybackReporter = AsyncNotifier<core.PlaybackReporter>;
|
AsyncValue<core.PlaybackReporter>,
|
||||||
// ignore_for_file: type=lint
|
core.PlaybackReporter
|
||||||
// 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
|
>,
|
||||||
|
AsyncValue<core.PlaybackReporter>,
|
||||||
|
Object?,
|
||||||
|
Object?
|
||||||
|
>;
|
||||||
|
element.handleCreate(ref, build);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@ Duration sumOfTracks(BookExpanded book, int? index) {
|
||||||
_logger.warning('Index is null or less than 0, returning 0');
|
_logger.warning('Index is null or less than 0, returning 0');
|
||||||
return Duration.zero;
|
return Duration.zero;
|
||||||
}
|
}
|
||||||
final total = book.tracks.sublist(0, index).fold<Duration>(
|
final total = book.tracks
|
||||||
|
.sublist(0, index)
|
||||||
|
.fold<Duration>(
|
||||||
Duration.zero,
|
Duration.zero,
|
||||||
(previousValue, element) => previousValue + element.duration,
|
(previousValue, element) => previousValue + element.duration,
|
||||||
);
|
);
|
||||||
|
|
@ -34,13 +36,10 @@ Duration sumOfTracks(BookExpanded book, int? index) {
|
||||||
/// returns the [AudioTrack] to play based on the [position] in the [book]
|
/// returns the [AudioTrack] to play based on the [position] in the [book]
|
||||||
AudioTrack getTrackToPlay(BookExpanded book, Duration position) {
|
AudioTrack getTrackToPlay(BookExpanded book, Duration position) {
|
||||||
_logger.fine('Getting track to play for position: $position');
|
_logger.fine('Getting track to play for position: $position');
|
||||||
final track = book.tracks.firstWhere(
|
final track = book.tracks.firstWhere((element) {
|
||||||
(element) {
|
return element.startOffset <= position &&
|
||||||
return element.startOffset <= position &&
|
(element.startOffset + element.duration) >= position;
|
||||||
(element.startOffset + element.duration) >= position;
|
}, orElse: () => book.tracks.last);
|
||||||
},
|
|
||||||
orElse: () => book.tracks.last,
|
|
||||||
);
|
|
||||||
_logger.fine('Track to play for position: $position is $track');
|
_logger.fine('Track to play for position: $position is $track');
|
||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
|
|
@ -126,8 +125,12 @@ class AudiobookPlayer extends AudioPlayer {
|
||||||
ConcatenatingAudioSource(
|
ConcatenatingAudioSource(
|
||||||
useLazyPreparation: true,
|
useLazyPreparation: true,
|
||||||
children: book.tracks.map((track) {
|
children: book.tracks.map((track) {
|
||||||
final retrievedUri =
|
final retrievedUri = _getUri(
|
||||||
_getUri(track, downloadedUris, baseUrl: baseUrl, token: token);
|
track,
|
||||||
|
downloadedUris,
|
||||||
|
baseUrl: baseUrl,
|
||||||
|
token: token,
|
||||||
|
);
|
||||||
_logger.fine(
|
_logger.fine(
|
||||||
'Setting source for track: ${track.title}, URI: ${retrievedUri.obfuscate()}',
|
'Setting source for track: ${track.title}, URI: ${retrievedUri.obfuscate()}',
|
||||||
);
|
);
|
||||||
|
|
@ -141,7 +144,8 @@ class AudiobookPlayer extends AudioPlayer {
|
||||||
.formatNotificationTitle(book),
|
.formatNotificationTitle(book),
|
||||||
album: appSettings.notificationSettings.secondaryTitle
|
album: appSettings.notificationSettings.secondaryTitle
|
||||||
.formatNotificationTitle(book),
|
.formatNotificationTitle(book),
|
||||||
artUri: artworkUri ??
|
artUri:
|
||||||
|
artworkUri ??
|
||||||
Uri.parse(
|
Uri.parse(
|
||||||
'$baseUrl/api/items/${book.libraryItemId}/cover?token=$token&width=800',
|
'$baseUrl/api/items/${book.libraryItemId}/cover?token=$token&width=800',
|
||||||
),
|
),
|
||||||
|
|
@ -255,12 +259,9 @@ class AudiobookPlayer extends AudioPlayer {
|
||||||
if (_book!.chapters.isEmpty) {
|
if (_book!.chapters.isEmpty) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return _book!.chapters.firstWhere(
|
return _book!.chapters.firstWhere((element) {
|
||||||
(element) {
|
return element.start <= positionInBook && element.end >= positionInBook;
|
||||||
return element.start <= positionInBook && element.end >= positionInBook;
|
}, orElse: () => _book!.chapters.first);
|
||||||
},
|
|
||||||
orElse: () => _book!.chapters.first,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -271,11 +272,9 @@ Uri _getUri(
|
||||||
required String token,
|
required String token,
|
||||||
}) {
|
}) {
|
||||||
// check if the track is in the downloadedUris
|
// check if the track is in the downloadedUris
|
||||||
final uri = downloadedUris?.firstWhereOrNull(
|
final uri = downloadedUris?.firstWhereOrNull((element) {
|
||||||
(element) {
|
return element.pathSegments.last == track.metadata?.filename;
|
||||||
return element.pathSegments.last == track.metadata?.filename;
|
});
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
return uri ??
|
return uri ??
|
||||||
Uri.parse('${baseUrl.toString()}${track.contentUrl}?token=$token');
|
Uri.parse('${baseUrl.toString()}${track.contentUrl}?token=$token');
|
||||||
|
|
@ -283,17 +282,14 @@ Uri _getUri(
|
||||||
|
|
||||||
extension FormatNotificationTitle on String {
|
extension FormatNotificationTitle on String {
|
||||||
String formatNotificationTitle(BookExpanded book) {
|
String formatNotificationTitle(BookExpanded book) {
|
||||||
return replaceAllMapped(
|
return replaceAllMapped(RegExp(r'\$(\w+)'), (match) {
|
||||||
RegExp(r'\$(\w+)'),
|
final type = match.group(1);
|
||||||
(match) {
|
return NotificationTitleType.values
|
||||||
final type = match.group(1);
|
.firstWhere((element) => element.name == type)
|
||||||
return NotificationTitleType.values
|
.extractFrom(book) ??
|
||||||
.firstWhere((element) => element.name == type)
|
match.group(0) ??
|
||||||
.extractFrom(book) ??
|
'';
|
||||||
match.group(0) ??
|
});
|
||||||
'';
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,23 +30,28 @@ Future<void> configurePlayer() async {
|
||||||
androidShowNotificationBadge: false,
|
androidShowNotificationBadge: false,
|
||||||
notificationConfigBuilder: (state) {
|
notificationConfigBuilder: (state) {
|
||||||
final controls = [
|
final controls = [
|
||||||
if (appSettings.notificationSettings.mediaControls
|
if (appSettings.notificationSettings.mediaControls.contains(
|
||||||
.contains(NotificationMediaControl.skipToPreviousChapter) &&
|
NotificationMediaControl.skipToPreviousChapter,
|
||||||
|
) &&
|
||||||
state.hasPrevious)
|
state.hasPrevious)
|
||||||
MediaControl.skipToPrevious,
|
MediaControl.skipToPrevious,
|
||||||
if (appSettings.notificationSettings.mediaControls
|
if (appSettings.notificationSettings.mediaControls.contains(
|
||||||
.contains(NotificationMediaControl.rewind))
|
NotificationMediaControl.rewind,
|
||||||
|
))
|
||||||
MediaControl.rewind,
|
MediaControl.rewind,
|
||||||
if (state.playing) MediaControl.pause else MediaControl.play,
|
if (state.playing) MediaControl.pause else MediaControl.play,
|
||||||
if (appSettings.notificationSettings.mediaControls
|
if (appSettings.notificationSettings.mediaControls.contains(
|
||||||
.contains(NotificationMediaControl.fastForward))
|
NotificationMediaControl.fastForward,
|
||||||
|
))
|
||||||
MediaControl.fastForward,
|
MediaControl.fastForward,
|
||||||
if (appSettings.notificationSettings.mediaControls
|
if (appSettings.notificationSettings.mediaControls.contains(
|
||||||
.contains(NotificationMediaControl.skipToNextChapter) &&
|
NotificationMediaControl.skipToNextChapter,
|
||||||
|
) &&
|
||||||
state.hasNext)
|
state.hasNext)
|
||||||
MediaControl.skipToNext,
|
MediaControl.skipToNext,
|
||||||
if (appSettings.notificationSettings.mediaControls
|
if (appSettings.notificationSettings.mediaControls.contains(
|
||||||
.contains(NotificationMediaControl.stop))
|
NotificationMediaControl.stop,
|
||||||
|
))
|
||||||
MediaControl.stop,
|
MediaControl.stop,
|
||||||
];
|
];
|
||||||
return NotificationConfig(
|
return NotificationConfig(
|
||||||
|
|
|
||||||
|
|
@ -62,8 +62,8 @@ class AudiobookPlaylist {
|
||||||
this.books = const [],
|
this.books = const [],
|
||||||
currentIndex = 0,
|
currentIndex = 0,
|
||||||
subCurrentIndex = 0,
|
subCurrentIndex = 0,
|
||||||
}) : _currentIndex = currentIndex,
|
}) : _currentIndex = currentIndex,
|
||||||
_subCurrentIndex = subCurrentIndex;
|
_subCurrentIndex = subCurrentIndex;
|
||||||
|
|
||||||
// most important method, gets the audio file to play
|
// most important method, gets the audio file to play
|
||||||
// this is needed as a library item is a list of audio files
|
// this is needed as a library item is a list of audio files
|
||||||
|
|
|
||||||
|
|
@ -6,20 +6,57 @@ part of 'playlist_provider.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint, type=warning
|
||||||
|
|
||||||
|
@ProviderFor(Playlist)
|
||||||
|
final playlistProvider = PlaylistProvider._();
|
||||||
|
|
||||||
|
final class PlaylistProvider
|
||||||
|
extends $NotifierProvider<Playlist, AudiobookPlaylist> {
|
||||||
|
PlaylistProvider._()
|
||||||
|
: super(
|
||||||
|
from: null,
|
||||||
|
argument: null,
|
||||||
|
retry: null,
|
||||||
|
name: r'playlistProvider',
|
||||||
|
isAutoDispose: true,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$playlistHash();
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
Playlist create() => Playlist();
|
||||||
|
|
||||||
|
/// {@macro riverpod.override_with_value}
|
||||||
|
Override overrideWithValue(AudiobookPlaylist value) {
|
||||||
|
return $ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
providerOverride: $SyncValueProvider<AudiobookPlaylist>(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String _$playlistHash() => r'bed4642e4c2de829e4d0630cb5bf92bffeeb1f60';
|
String _$playlistHash() => r'bed4642e4c2de829e4d0630cb5bf92bffeeb1f60';
|
||||||
|
|
||||||
/// See also [Playlist].
|
abstract class _$Playlist extends $Notifier<AudiobookPlaylist> {
|
||||||
@ProviderFor(Playlist)
|
AudiobookPlaylist build();
|
||||||
final playlistProvider =
|
@$mustCallSuper
|
||||||
AutoDisposeNotifierProvider<Playlist, AudiobookPlaylist>.internal(
|
@override
|
||||||
Playlist.new,
|
void runBuild() {
|
||||||
name: r'playlistProvider',
|
final ref = this.ref as $Ref<AudiobookPlaylist, AudiobookPlaylist>;
|
||||||
debugGetCreateSourceHash:
|
final element =
|
||||||
const bool.fromEnvironment('dart.vm.product') ? null : _$playlistHash,
|
ref.element
|
||||||
dependencies: null,
|
as $ClassProviderElement<
|
||||||
allTransitiveDependencies: null,
|
AnyNotifier<AudiobookPlaylist, AudiobookPlaylist>,
|
||||||
);
|
AudiobookPlaylist,
|
||||||
|
Object?,
|
||||||
typedef _$Playlist = AutoDisposeNotifier<AudiobookPlaylist>;
|
Object?
|
||||||
// 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
|
element.handleCreate(ref, build);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,7 @@ class SimpleAudiobookPlayer extends _$SimpleAudiobookPlayer {
|
||||||
@override
|
@override
|
||||||
core.AudiobookPlayer build() {
|
core.AudiobookPlayer build() {
|
||||||
final api = ref.watch(authenticatedApiProvider);
|
final api = ref.watch(authenticatedApiProvider);
|
||||||
final player = core.AudiobookPlayer(
|
final player = core.AudiobookPlayer(api.token!, api.baseUrl);
|
||||||
api.token!,
|
|
||||||
api.baseUrl,
|
|
||||||
);
|
|
||||||
|
|
||||||
ref.onDispose(player.dispose);
|
ref.onDispose(player.dispose);
|
||||||
_logger.finer('created simple player');
|
_logger.finer('created simple player');
|
||||||
|
|
|
||||||
|
|
@ -6,41 +6,119 @@ part of 'audiobook_player.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint, type=warning
|
||||||
|
/// Simple because it doesn't rebuild when the player state changes
|
||||||
|
/// it only rebuilds when the token changes
|
||||||
|
|
||||||
|
@ProviderFor(SimpleAudiobookPlayer)
|
||||||
|
final simpleAudiobookPlayerProvider = SimpleAudiobookPlayerProvider._();
|
||||||
|
|
||||||
|
/// Simple because it doesn't rebuild when the player state changes
|
||||||
|
/// it only rebuilds when the token changes
|
||||||
|
final class SimpleAudiobookPlayerProvider
|
||||||
|
extends $NotifierProvider<SimpleAudiobookPlayer, core.AudiobookPlayer> {
|
||||||
|
/// Simple because it doesn't rebuild when the player state changes
|
||||||
|
/// it only rebuilds when the token changes
|
||||||
|
SimpleAudiobookPlayerProvider._()
|
||||||
|
: super(
|
||||||
|
from: null,
|
||||||
|
argument: null,
|
||||||
|
retry: null,
|
||||||
|
name: r'simpleAudiobookPlayerProvider',
|
||||||
|
isAutoDispose: false,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$simpleAudiobookPlayerHash();
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
SimpleAudiobookPlayer create() => SimpleAudiobookPlayer();
|
||||||
|
|
||||||
|
/// {@macro riverpod.override_with_value}
|
||||||
|
Override overrideWithValue(core.AudiobookPlayer value) {
|
||||||
|
return $ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
providerOverride: $SyncValueProvider<core.AudiobookPlayer>(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String _$simpleAudiobookPlayerHash() =>
|
String _$simpleAudiobookPlayerHash() =>
|
||||||
r'5e94bbff4314adceb5affa704fc4d079d4016afa';
|
r'5e94bbff4314adceb5affa704fc4d079d4016afa';
|
||||||
|
|
||||||
/// Simple because it doesn't rebuild when the player state changes
|
/// Simple because it doesn't rebuild when the player state changes
|
||||||
/// it only rebuilds when the token changes
|
/// it only rebuilds when the token changes
|
||||||
///
|
|
||||||
/// Copied from [SimpleAudiobookPlayer].
|
|
||||||
@ProviderFor(SimpleAudiobookPlayer)
|
|
||||||
final simpleAudiobookPlayerProvider =
|
|
||||||
NotifierProvider<SimpleAudiobookPlayer, core.AudiobookPlayer>.internal(
|
|
||||||
SimpleAudiobookPlayer.new,
|
|
||||||
name: r'simpleAudiobookPlayerProvider',
|
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$simpleAudiobookPlayerHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef _$SimpleAudiobookPlayer = Notifier<core.AudiobookPlayer>;
|
abstract class _$SimpleAudiobookPlayer extends $Notifier<core.AudiobookPlayer> {
|
||||||
|
core.AudiobookPlayer build();
|
||||||
|
@$mustCallSuper
|
||||||
|
@override
|
||||||
|
void runBuild() {
|
||||||
|
final ref = this.ref as $Ref<core.AudiobookPlayer, core.AudiobookPlayer>;
|
||||||
|
final element =
|
||||||
|
ref.element
|
||||||
|
as $ClassProviderElement<
|
||||||
|
AnyNotifier<core.AudiobookPlayer, core.AudiobookPlayer>,
|
||||||
|
core.AudiobookPlayer,
|
||||||
|
Object?,
|
||||||
|
Object?
|
||||||
|
>;
|
||||||
|
element.handleCreate(ref, build);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProviderFor(AudiobookPlayer)
|
||||||
|
final audiobookPlayerProvider = AudiobookPlayerProvider._();
|
||||||
|
|
||||||
|
final class AudiobookPlayerProvider
|
||||||
|
extends $NotifierProvider<AudiobookPlayer, core.AudiobookPlayer> {
|
||||||
|
AudiobookPlayerProvider._()
|
||||||
|
: super(
|
||||||
|
from: null,
|
||||||
|
argument: null,
|
||||||
|
retry: null,
|
||||||
|
name: r'audiobookPlayerProvider',
|
||||||
|
isAutoDispose: false,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$audiobookPlayerHash();
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
AudiobookPlayer create() => AudiobookPlayer();
|
||||||
|
|
||||||
|
/// {@macro riverpod.override_with_value}
|
||||||
|
Override overrideWithValue(core.AudiobookPlayer value) {
|
||||||
|
return $ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
providerOverride: $SyncValueProvider<core.AudiobookPlayer>(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String _$audiobookPlayerHash() => r'0f180308067486896fec6a65a6afb0e6686ac4a0';
|
String _$audiobookPlayerHash() => r'0f180308067486896fec6a65a6afb0e6686ac4a0';
|
||||||
|
|
||||||
/// See also [AudiobookPlayer].
|
abstract class _$AudiobookPlayer extends $Notifier<core.AudiobookPlayer> {
|
||||||
@ProviderFor(AudiobookPlayer)
|
core.AudiobookPlayer build();
|
||||||
final audiobookPlayerProvider =
|
@$mustCallSuper
|
||||||
NotifierProvider<AudiobookPlayer, core.AudiobookPlayer>.internal(
|
@override
|
||||||
AudiobookPlayer.new,
|
void runBuild() {
|
||||||
name: r'audiobookPlayerProvider',
|
final ref = this.ref as $Ref<core.AudiobookPlayer, core.AudiobookPlayer>;
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
final element =
|
||||||
? null
|
ref.element
|
||||||
: _$audiobookPlayerHash,
|
as $ClassProviderElement<
|
||||||
dependencies: null,
|
AnyNotifier<core.AudiobookPlayer, core.AudiobookPlayer>,
|
||||||
allTransitiveDependencies: null,
|
core.AudiobookPlayer,
|
||||||
);
|
Object?,
|
||||||
|
Object?
|
||||||
typedef _$AudiobookPlayer = Notifier<core.AudiobookPlayer>;
|
>;
|
||||||
// ignore_for_file: type=lint
|
element.handleCreate(ref, build);
|
||||||
// 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
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,66 +6,147 @@ part of 'currently_playing_provider.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint, type=warning
|
||||||
|
|
||||||
|
@ProviderFor(currentlyPlayingBook)
|
||||||
|
final currentlyPlayingBookProvider = CurrentlyPlayingBookProvider._();
|
||||||
|
|
||||||
|
final class CurrentlyPlayingBookProvider
|
||||||
|
extends $FunctionalProvider<BookExpanded?, BookExpanded?, BookExpanded?>
|
||||||
|
with $Provider<BookExpanded?> {
|
||||||
|
CurrentlyPlayingBookProvider._()
|
||||||
|
: super(
|
||||||
|
from: null,
|
||||||
|
argument: null,
|
||||||
|
retry: null,
|
||||||
|
name: r'currentlyPlayingBookProvider',
|
||||||
|
isAutoDispose: true,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$currentlyPlayingBookHash();
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
$ProviderElement<BookExpanded?> $createElement($ProviderPointer pointer) =>
|
||||||
|
$ProviderElement(pointer);
|
||||||
|
|
||||||
|
@override
|
||||||
|
BookExpanded? create(Ref ref) {
|
||||||
|
return currentlyPlayingBook(ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// {@macro riverpod.override_with_value}
|
||||||
|
Override overrideWithValue(BookExpanded? value) {
|
||||||
|
return $ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
providerOverride: $SyncValueProvider<BookExpanded?>(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String _$currentlyPlayingBookHash() =>
|
String _$currentlyPlayingBookHash() =>
|
||||||
r'e4258694c8f0d1e89651b330fae0f672ca13a484';
|
r'e4258694c8f0d1e89651b330fae0f672ca13a484';
|
||||||
|
|
||||||
/// See also [currentlyPlayingBook].
|
/// provided the current chapter of the book being played
|
||||||
@ProviderFor(currentlyPlayingBook)
|
|
||||||
final currentlyPlayingBookProvider =
|
@ProviderFor(currentPlayingChapter)
|
||||||
AutoDisposeProvider<BookExpanded?>.internal(
|
final currentPlayingChapterProvider = CurrentPlayingChapterProvider._();
|
||||||
currentlyPlayingBook,
|
|
||||||
name: r'currentlyPlayingBookProvider',
|
/// provided the current chapter of the book being played
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
final class CurrentPlayingChapterProvider
|
||||||
: _$currentlyPlayingBookHash,
|
extends $FunctionalProvider<BookChapter?, BookChapter?, BookChapter?>
|
||||||
dependencies: null,
|
with $Provider<BookChapter?> {
|
||||||
allTransitiveDependencies: null,
|
/// provided the current chapter of the book being played
|
||||||
);
|
CurrentPlayingChapterProvider._()
|
||||||
|
: super(
|
||||||
|
from: null,
|
||||||
|
argument: null,
|
||||||
|
retry: null,
|
||||||
|
name: r'currentPlayingChapterProvider',
|
||||||
|
isAutoDispose: true,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$currentPlayingChapterHash();
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
$ProviderElement<BookChapter?> $createElement($ProviderPointer pointer) =>
|
||||||
|
$ProviderElement(pointer);
|
||||||
|
|
||||||
|
@override
|
||||||
|
BookChapter? create(Ref ref) {
|
||||||
|
return currentPlayingChapter(ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// {@macro riverpod.override_with_value}
|
||||||
|
Override overrideWithValue(BookChapter? value) {
|
||||||
|
return $ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
providerOverride: $SyncValueProvider<BookChapter?>(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
|
||||||
// ignore: unused_element
|
|
||||||
typedef CurrentlyPlayingBookRef = AutoDisposeProviderRef<BookExpanded?>;
|
|
||||||
String _$currentPlayingChapterHash() =>
|
String _$currentPlayingChapterHash() =>
|
||||||
r'73db8b8a9058573bb0c68ec5d5f8aba9306f3d24';
|
r'73db8b8a9058573bb0c68ec5d5f8aba9306f3d24';
|
||||||
|
|
||||||
/// provided the current chapter of the book being played
|
/// provides the book metadata of the currently playing book
|
||||||
///
|
|
||||||
/// Copied from [currentPlayingChapter].
|
|
||||||
@ProviderFor(currentPlayingChapter)
|
|
||||||
final currentPlayingChapterProvider =
|
|
||||||
AutoDisposeProvider<BookChapter?>.internal(
|
|
||||||
currentPlayingChapter,
|
|
||||||
name: r'currentPlayingChapterProvider',
|
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$currentPlayingChapterHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
@ProviderFor(currentBookMetadata)
|
||||||
// ignore: unused_element
|
final currentBookMetadataProvider = CurrentBookMetadataProvider._();
|
||||||
typedef CurrentPlayingChapterRef = AutoDisposeProviderRef<BookChapter?>;
|
|
||||||
String _$currentBookMetadataHash() =>
|
|
||||||
r'f537ef4ef19280bc952de658ecf6520c535ae344';
|
|
||||||
|
|
||||||
/// provides the book metadata of the currently playing book
|
/// provides the book metadata of the currently playing book
|
||||||
///
|
|
||||||
/// Copied from [currentBookMetadata].
|
|
||||||
@ProviderFor(currentBookMetadata)
|
|
||||||
final currentBookMetadataProvider =
|
|
||||||
AutoDisposeProvider<BookMetadataExpanded?>.internal(
|
|
||||||
currentBookMetadata,
|
|
||||||
name: r'currentBookMetadataProvider',
|
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$currentBookMetadataHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
final class CurrentBookMetadataProvider
|
||||||
// ignore: unused_element
|
extends
|
||||||
typedef CurrentBookMetadataRef = AutoDisposeProviderRef<BookMetadataExpanded?>;
|
$FunctionalProvider<
|
||||||
// ignore_for_file: type=lint
|
BookMetadataExpanded?,
|
||||||
// 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
|
BookMetadataExpanded?,
|
||||||
|
BookMetadataExpanded?
|
||||||
|
>
|
||||||
|
with $Provider<BookMetadataExpanded?> {
|
||||||
|
/// provides the book metadata of the currently playing book
|
||||||
|
CurrentBookMetadataProvider._()
|
||||||
|
: super(
|
||||||
|
from: null,
|
||||||
|
argument: null,
|
||||||
|
retry: null,
|
||||||
|
name: r'currentBookMetadataProvider',
|
||||||
|
isAutoDispose: true,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$currentBookMetadataHash();
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
$ProviderElement<BookMetadataExpanded?> $createElement(
|
||||||
|
$ProviderPointer pointer,
|
||||||
|
) => $ProviderElement(pointer);
|
||||||
|
|
||||||
|
@override
|
||||||
|
BookMetadataExpanded? create(Ref ref) {
|
||||||
|
return currentBookMetadata(ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// {@macro riverpod.override_with_value}
|
||||||
|
Override overrideWithValue(BookMetadataExpanded? value) {
|
||||||
|
return $ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
providerOverride: $SyncValueProvider<BookMetadataExpanded?>(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String _$currentBookMetadataHash() =>
|
||||||
|
r'f537ef4ef19280bc952de658ecf6520c535ae344';
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,10 @@ extension on Ref {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Riverpod(keepAlive: true)
|
@Riverpod(keepAlive: true)
|
||||||
Raw<ValueNotifier<double>> playerExpandProgressNotifier(
|
Raw<ValueNotifier<double>> playerExpandProgressNotifier(Ref ref) {
|
||||||
Ref ref,
|
final ValueNotifier<double> playerExpandProgress = ValueNotifier(
|
||||||
) {
|
playerMinHeight,
|
||||||
final ValueNotifier<double> playerExpandProgress =
|
);
|
||||||
ValueNotifier(playerMinHeight);
|
|
||||||
|
|
||||||
return ref.disposeAndListenChangeNotifier(playerExpandProgress);
|
return ref.disposeAndListenChangeNotifier(playerExpandProgress);
|
||||||
}
|
}
|
||||||
|
|
@ -46,10 +45,8 @@ Raw<ValueNotifier<double>> playerExpandProgressNotifier(
|
||||||
|
|
||||||
// a provider that will listen to the playerExpandProgressNotifier and return the percentage of the player expanded
|
// a provider that will listen to the playerExpandProgressNotifier and return the percentage of the player expanded
|
||||||
@Riverpod(keepAlive: true)
|
@Riverpod(keepAlive: true)
|
||||||
double playerHeight(
|
double playerHeight(Ref ref) {
|
||||||
Ref ref,
|
final playerExpandProgress = ref.watch(playerExpandProgressProvider);
|
||||||
) {
|
|
||||||
final playerExpandProgress = ref.watch(playerExpandProgressNotifierProvider);
|
|
||||||
|
|
||||||
// on change of the playerExpandProgress invalidate
|
// on change of the playerExpandProgress invalidate
|
||||||
playerExpandProgress.addListener(() {
|
playerExpandProgress.addListener(() {
|
||||||
|
|
@ -63,9 +60,7 @@ double playerHeight(
|
||||||
final audioBookMiniplayerController = MiniplayerController();
|
final audioBookMiniplayerController = MiniplayerController();
|
||||||
|
|
||||||
@Riverpod(keepAlive: true)
|
@Riverpod(keepAlive: true)
|
||||||
bool isPlayerActive(
|
bool isPlayerActive(Ref ref) {
|
||||||
Ref ref,
|
|
||||||
) {
|
|
||||||
try {
|
try {
|
||||||
final player = ref.watch(audiobookPlayerProvider);
|
final player = ref.watch(audiobookPlayerProvider);
|
||||||
if (player.book != null) {
|
if (player.book != null) {
|
||||||
|
|
|
||||||
|
|
@ -6,58 +6,134 @@ part of 'player_form.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint, type=warning
|
||||||
|
|
||||||
|
@ProviderFor(playerExpandProgressNotifier)
|
||||||
|
final playerExpandProgressProvider = PlayerExpandProgressNotifierProvider._();
|
||||||
|
|
||||||
|
final class PlayerExpandProgressNotifierProvider
|
||||||
|
extends
|
||||||
|
$FunctionalProvider<
|
||||||
|
Raw<ValueNotifier<double>>,
|
||||||
|
Raw<ValueNotifier<double>>,
|
||||||
|
Raw<ValueNotifier<double>>
|
||||||
|
>
|
||||||
|
with $Provider<Raw<ValueNotifier<double>>> {
|
||||||
|
PlayerExpandProgressNotifierProvider._()
|
||||||
|
: super(
|
||||||
|
from: null,
|
||||||
|
argument: null,
|
||||||
|
retry: null,
|
||||||
|
name: r'playerExpandProgressProvider',
|
||||||
|
isAutoDispose: false,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$playerExpandProgressNotifierHash();
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
$ProviderElement<Raw<ValueNotifier<double>>> $createElement(
|
||||||
|
$ProviderPointer pointer,
|
||||||
|
) => $ProviderElement(pointer);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Raw<ValueNotifier<double>> create(Ref ref) {
|
||||||
|
return playerExpandProgressNotifier(ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// {@macro riverpod.override_with_value}
|
||||||
|
Override overrideWithValue(Raw<ValueNotifier<double>> value) {
|
||||||
|
return $ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
providerOverride: $SyncValueProvider<Raw<ValueNotifier<double>>>(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String _$playerExpandProgressNotifierHash() =>
|
String _$playerExpandProgressNotifierHash() =>
|
||||||
r'1ac7172d90a070f96222286edd1a176be197f378';
|
r'1ac7172d90a070f96222286edd1a176be197f378';
|
||||||
|
|
||||||
/// See also [playerExpandProgressNotifier].
|
|
||||||
@ProviderFor(playerExpandProgressNotifier)
|
|
||||||
final playerExpandProgressNotifierProvider =
|
|
||||||
Provider<Raw<ValueNotifier<double>>>.internal(
|
|
||||||
playerExpandProgressNotifier,
|
|
||||||
name: r'playerExpandProgressNotifierProvider',
|
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$playerExpandProgressNotifierHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
|
||||||
// ignore: unused_element
|
|
||||||
typedef PlayerExpandProgressNotifierRef
|
|
||||||
= ProviderRef<Raw<ValueNotifier<double>>>;
|
|
||||||
String _$playerHeightHash() => r'3f031eaffdffbb2c6ddf7eb1aba31bf1619260fc';
|
|
||||||
|
|
||||||
/// See also [playerHeight].
|
|
||||||
@ProviderFor(playerHeight)
|
@ProviderFor(playerHeight)
|
||||||
final playerHeightProvider = Provider<double>.internal(
|
final playerHeightProvider = PlayerHeightProvider._();
|
||||||
playerHeight,
|
|
||||||
name: r'playerHeightProvider',
|
|
||||||
debugGetCreateSourceHash:
|
|
||||||
const bool.fromEnvironment('dart.vm.product') ? null : _$playerHeightHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
final class PlayerHeightProvider
|
||||||
// ignore: unused_element
|
extends $FunctionalProvider<double, double, double>
|
||||||
typedef PlayerHeightRef = ProviderRef<double>;
|
with $Provider<double> {
|
||||||
String _$isPlayerActiveHash() => r'2c7ca125423126fb5f0ef218d37bc8fe0ca9ec98';
|
PlayerHeightProvider._()
|
||||||
|
: super(
|
||||||
|
from: null,
|
||||||
|
argument: null,
|
||||||
|
retry: null,
|
||||||
|
name: r'playerHeightProvider',
|
||||||
|
isAutoDispose: false,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$playerHeightHash();
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
$ProviderElement<double> $createElement($ProviderPointer pointer) =>
|
||||||
|
$ProviderElement(pointer);
|
||||||
|
|
||||||
|
@override
|
||||||
|
double create(Ref ref) {
|
||||||
|
return playerHeight(ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// {@macro riverpod.override_with_value}
|
||||||
|
Override overrideWithValue(double value) {
|
||||||
|
return $ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
providerOverride: $SyncValueProvider<double>(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String _$playerHeightHash() => r'41144a733b5ffd1c872a237ed7c9ea5f450dd0d4';
|
||||||
|
|
||||||
/// See also [isPlayerActive].
|
|
||||||
@ProviderFor(isPlayerActive)
|
@ProviderFor(isPlayerActive)
|
||||||
final isPlayerActiveProvider = Provider<bool>.internal(
|
final isPlayerActiveProvider = IsPlayerActiveProvider._();
|
||||||
isPlayerActive,
|
|
||||||
name: r'isPlayerActiveProvider',
|
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$isPlayerActiveHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
final class IsPlayerActiveProvider extends $FunctionalProvider<bool, bool, bool>
|
||||||
// ignore: unused_element
|
with $Provider<bool> {
|
||||||
typedef IsPlayerActiveRef = ProviderRef<bool>;
|
IsPlayerActiveProvider._()
|
||||||
// ignore_for_file: type=lint
|
: super(
|
||||||
// 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
|
from: null,
|
||||||
|
argument: null,
|
||||||
|
retry: null,
|
||||||
|
name: r'isPlayerActiveProvider',
|
||||||
|
isAutoDispose: false,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$isPlayerActiveHash();
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
$ProviderElement<bool> $createElement($ProviderPointer pointer) =>
|
||||||
|
$ProviderElement(pointer);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool create(Ref ref) {
|
||||||
|
return isPlayerActive(ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// {@macro riverpod.override_with_value}
|
||||||
|
Override overrideWithValue(bool value) {
|
||||||
|
return $ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
providerOverride: $SyncValueProvider<bool>(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String _$isPlayerActiveHash() => r'2c7ca125423126fb5f0ef218d37bc8fe0ca9ec98';
|
||||||
|
|
|
||||||
|
|
@ -31,19 +31,15 @@ class AudiobookPlayer extends HookConsumerWidget {
|
||||||
if (currentBook == null) {
|
if (currentBook == null) {
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
final itemBeingPlayed =
|
final itemBeingPlayed = ref.watch(
|
||||||
ref.watch(libraryItemProvider(currentBook.libraryItemId));
|
libraryItemProvider(currentBook.libraryItemId),
|
||||||
|
);
|
||||||
final player = ref.watch(audiobookPlayerProvider);
|
final player = ref.watch(audiobookPlayerProvider);
|
||||||
final imageOfItemBeingPlayed = itemBeingPlayed.valueOrNull != null
|
final imageOfItemBeingPlayed = itemBeingPlayed.value != null
|
||||||
? ref.watch(
|
? ref.watch(coverImageProvider(itemBeingPlayed.value!.id))
|
||||||
coverImageProvider(itemBeingPlayed.valueOrNull!.id),
|
|
||||||
)
|
|
||||||
: null;
|
: null;
|
||||||
final imgWidget = imageOfItemBeingPlayed?.valueOrNull != null
|
final imgWidget = imageOfItemBeingPlayed?.value != null
|
||||||
? Image.memory(
|
? Image.memory(imageOfItemBeingPlayed!.value!, fit: BoxFit.cover)
|
||||||
imageOfItemBeingPlayed!.valueOrNull!,
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
)
|
|
||||||
: const BookCoverSkeleton();
|
: const BookCoverSkeleton();
|
||||||
|
|
||||||
final playPauseController = useAnimationController(
|
final playPauseController = useAnimationController(
|
||||||
|
|
@ -63,9 +59,10 @@ class AudiobookPlayer extends HookConsumerWidget {
|
||||||
// theme from image
|
// theme from image
|
||||||
final imageTheme = ref.watch(
|
final imageTheme = ref.watch(
|
||||||
themeOfLibraryItemProvider(
|
themeOfLibraryItemProvider(
|
||||||
itemBeingPlayed.valueOrNull?.id,
|
itemBeingPlayed.value?.id,
|
||||||
brightness: Theme.of(context).brightness,
|
brightness: Theme.of(context).brightness,
|
||||||
highContrast: appSettings.themeSettings.highContrast ||
|
highContrast:
|
||||||
|
appSettings.themeSettings.highContrast ||
|
||||||
MediaQuery.of(context).highContrast,
|
MediaQuery.of(context).highContrast,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
@ -81,15 +78,16 @@ class AudiobookPlayer extends HookConsumerWidget {
|
||||||
final preferredVolume = appSettings.playerSettings.preferredDefaultVolume;
|
final preferredVolume = appSettings.playerSettings.preferredDefaultVolume;
|
||||||
return Theme(
|
return Theme(
|
||||||
data: ThemeData(
|
data: ThemeData(
|
||||||
colorScheme: imageTheme.valueOrNull ?? Theme.of(context).colorScheme,
|
colorScheme: imageTheme.value ?? Theme.of(context).colorScheme,
|
||||||
),
|
),
|
||||||
child: Miniplayer(
|
child: Miniplayer(
|
||||||
valueNotifier: ref.watch(playerExpandProgressNotifierProvider),
|
valueNotifier: ref.watch(playerExpandProgressProvider),
|
||||||
onDragDown: (percentage) async {
|
onDragDown: (percentage) async {
|
||||||
// preferred volume
|
// preferred volume
|
||||||
// set volume to 0 when dragging down
|
// set volume to 0 when dragging down
|
||||||
await player
|
await player.setVolume(
|
||||||
.setVolume(preferredVolume * (1 - percentage.clamp(0, .75)));
|
preferredVolume * (1 - percentage.clamp(0, .75)),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
minHeight: playerMinHeight,
|
minHeight: playerMinHeight,
|
||||||
// subtract the height of notches and other system UI
|
// subtract the height of notches and other system UI
|
||||||
|
|
@ -109,17 +107,14 @@ class AudiobookPlayer extends HookConsumerWidget {
|
||||||
// also at this point the image should be at its max size and in the center of the player
|
// also at this point the image should be at its max size and in the center of the player
|
||||||
final miniplayerPercentageDeclaration =
|
final miniplayerPercentageDeclaration =
|
||||||
(maxImgSize - playerMinHeight) /
|
(maxImgSize - playerMinHeight) /
|
||||||
(playerMaxHeight - playerMinHeight);
|
(playerMaxHeight - playerMinHeight);
|
||||||
final bool isFormMiniplayer =
|
final bool isFormMiniplayer =
|
||||||
percentage < miniplayerPercentageDeclaration;
|
percentage < miniplayerPercentageDeclaration;
|
||||||
|
|
||||||
if (!isFormMiniplayer) {
|
if (!isFormMiniplayer) {
|
||||||
// this calculation needs a refactor
|
// this calculation needs a refactor
|
||||||
var percentageExpandedPlayer = percentage
|
var percentageExpandedPlayer = percentage
|
||||||
.inverseLerp(
|
.inverseLerp(miniplayerPercentageDeclaration, 1)
|
||||||
miniplayerPercentageDeclaration,
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
.clamp(0.0, 1.0);
|
.clamp(0.0, 1.0);
|
||||||
|
|
||||||
return PlayerWhenExpanded(
|
return PlayerWhenExpanded(
|
||||||
|
|
@ -164,37 +159,33 @@ class AudiobookPlayerPlayPauseButton extends HookConsumerWidget {
|
||||||
|
|
||||||
return switch (player.processingState) {
|
return switch (player.processingState) {
|
||||||
ProcessingState.loading || ProcessingState.buffering => const Padding(
|
ProcessingState.loading || ProcessingState.buffering => const Padding(
|
||||||
padding: EdgeInsets.all(8.0),
|
padding: EdgeInsets.all(8.0),
|
||||||
child: CircularProgressIndicator(),
|
child: CircularProgressIndicator(),
|
||||||
),
|
),
|
||||||
ProcessingState.completed => IconButton(
|
ProcessingState.completed => IconButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await player.seek(const Duration(seconds: 0));
|
await player.seek(const Duration(seconds: 0));
|
||||||
await player.play();
|
await player.play();
|
||||||
},
|
},
|
||||||
icon: const Icon(
|
icon: const Icon(Icons.replay),
|
||||||
Icons.replay,
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
ProcessingState.ready => IconButton(
|
ProcessingState.ready => IconButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await player.togglePlayPause();
|
await player.togglePlayPause();
|
||||||
},
|
},
|
||||||
iconSize: iconSize,
|
iconSize: iconSize,
|
||||||
icon: AnimatedIcon(
|
icon: AnimatedIcon(
|
||||||
icon: AnimatedIcons.play_pause,
|
icon: AnimatedIcons.play_pause,
|
||||||
progress: playPauseController,
|
progress: playPauseController,
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
),
|
||||||
ProcessingState.idle => const SizedBox.shrink(),
|
ProcessingState.idle => const SizedBox.shrink(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AudiobookChapterProgressBar extends HookConsumerWidget {
|
class AudiobookChapterProgressBar extends HookConsumerWidget {
|
||||||
const AudiobookChapterProgressBar({
|
const AudiobookChapterProgressBar({super.key});
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
|
|
||||||
|
|
@ -38,10 +38,7 @@ class PlayerWhenExpanded extends HookConsumerWidget {
|
||||||
const lateStart = 0.4;
|
const lateStart = 0.4;
|
||||||
const earlyEnd = 1;
|
const earlyEnd = 1;
|
||||||
final earlyPercentage = percentageExpandedPlayer
|
final earlyPercentage = percentageExpandedPlayer
|
||||||
.inverseLerp(
|
.inverseLerp(lateStart, earlyEnd)
|
||||||
lateStart,
|
|
||||||
earlyEnd,
|
|
||||||
)
|
|
||||||
.clamp(0.0, 1.0);
|
.clamp(0.0, 1.0);
|
||||||
final currentChapter = ref.watch(currentPlayingChapterProvider);
|
final currentChapter = ref.watch(currentPlayingChapterProvider);
|
||||||
final currentBookMetadata = ref.watch(currentBookMetadataProvider);
|
final currentBookMetadata = ref.watch(currentBookMetadataProvider);
|
||||||
|
|
@ -49,15 +46,11 @@ class PlayerWhenExpanded extends HookConsumerWidget {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
// sized box for system status bar; not needed as not full screen
|
// sized box for system status bar; not needed as not full screen
|
||||||
SizedBox(
|
SizedBox(height: MediaQuery.of(context).padding.top * earlyPercentage),
|
||||||
height: MediaQuery.of(context).padding.top * earlyPercentage,
|
|
||||||
),
|
|
||||||
|
|
||||||
// a row with a down arrow to minimize the player, a pill shaped container to drag the player, and a cast button
|
// a row with a down arrow to minimize the player, a pill shaped container to drag the player, and a cast button
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(maxHeight: 100 * earlyPercentage),
|
||||||
maxHeight: 100 * earlyPercentage,
|
|
||||||
),
|
|
||||||
child: Opacity(
|
child: Opacity(
|
||||||
opacity: earlyPercentage,
|
opacity: earlyPercentage,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
|
|
@ -104,10 +97,9 @@ class PlayerWhenExpanded extends HookConsumerWidget {
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: Theme.of(context)
|
color: Theme.of(
|
||||||
.colorScheme
|
context,
|
||||||
.primary
|
).colorScheme.primary.withValues(alpha: 0.1),
|
||||||
.withValues(alpha: 0.1),
|
|
||||||
blurRadius: 32 * earlyPercentage,
|
blurRadius: 32 * earlyPercentage,
|
||||||
spreadRadius: 8 * earlyPercentage,
|
spreadRadius: 8 * earlyPercentage,
|
||||||
// offset: Offset(0, 16 * earlyPercentage),
|
// offset: Offset(0, 16 * earlyPercentage),
|
||||||
|
|
@ -170,11 +162,10 @@ class PlayerWhenExpanded extends HookConsumerWidget {
|
||||||
currentBookMetadata?.authorName ?? '',
|
currentBookMetadata?.authorName ?? '',
|
||||||
].join(' - '),
|
].join(' - '),
|
||||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||||
color: Theme.of(context)
|
color: Theme.of(
|
||||||
.colorScheme
|
context,
|
||||||
.onSurface
|
).colorScheme.onSurface.withValues(alpha: 0.7),
|
||||||
.withValues(alpha: 0.7),
|
),
|
||||||
),
|
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,10 @@ class PlayerWhenMinimized extends HookConsumerWidget {
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final player = ref.watch(audiobookPlayerProvider);
|
final player = ref.watch(audiobookPlayerProvider);
|
||||||
final vanishingPercentage = 1 - percentageMiniplayer;
|
final vanishingPercentage = 1 - percentageMiniplayer;
|
||||||
final progress =
|
final progress = useStream(
|
||||||
useStream(player.slowPositionStream, initialData: Duration.zero);
|
player.slowPositionStream,
|
||||||
|
initialData: Duration.zero,
|
||||||
|
);
|
||||||
|
|
||||||
final bookMetaExpanded = ref.watch(currentBookMetadataProvider);
|
final bookMetaExpanded = ref.watch(currentBookMetadataProvider);
|
||||||
|
|
||||||
|
|
@ -61,9 +63,7 @@ class PlayerWhenMinimized extends HookConsumerWidget {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: ConstrainedBox(
|
child: ConstrainedBox(
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(maxWidth: maxImgSize),
|
||||||
maxWidth: maxImgSize,
|
|
||||||
),
|
|
||||||
child: imgWidget,
|
child: imgWidget,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -80,7 +80,8 @@ class PlayerWhenMinimized extends HookConsumerWidget {
|
||||||
// AutoScrollText(
|
// AutoScrollText(
|
||||||
Text(
|
Text(
|
||||||
bookMetaExpanded?.title ?? '',
|
bookMetaExpanded?.title ?? '',
|
||||||
maxLines: 1, overflow: TextOverflow.ellipsis,
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
// velocity:
|
// velocity:
|
||||||
// const Velocity(pixelsPerSecond: Offset(16, 0)),
|
// const Velocity(pixelsPerSecond: Offset(16, 0)),
|
||||||
style: Theme.of(context).textTheme.bodyLarge,
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
|
|
@ -90,11 +91,10 @@ class PlayerWhenMinimized extends HookConsumerWidget {
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||||
color: Theme.of(context)
|
color: Theme.of(
|
||||||
.colorScheme
|
context,
|
||||||
.onSurface
|
).colorScheme.onSurface.withValues(alpha: 0.7),
|
||||||
.withValues(alpha: 0.7),
|
),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -135,7 +135,8 @@ class PlayerWhenMinimized extends HookConsumerWidget {
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: barHeight,
|
height: barHeight,
|
||||||
child: LinearProgressIndicator(
|
child: LinearProgressIndicator(
|
||||||
value: (progress.data ?? Duration.zero).inSeconds /
|
value:
|
||||||
|
(progress.data ?? Duration.zero).inSeconds /
|
||||||
player.book!.duration.inSeconds,
|
player.book!.duration.inSeconds,
|
||||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||||
backgroundColor: Theme.of(context).colorScheme.primaryContainer,
|
backgroundColor: Theme.of(context).colorScheme.primaryContainer,
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,7 @@ import 'package:vaani/constants/sizes.dart';
|
||||||
import 'package:vaani/features/player/providers/audiobook_player.dart';
|
import 'package:vaani/features/player/providers/audiobook_player.dart';
|
||||||
|
|
||||||
class AudiobookPlayerSeekButton extends HookConsumerWidget {
|
class AudiobookPlayerSeekButton extends HookConsumerWidget {
|
||||||
const AudiobookPlayerSeekButton({
|
const AudiobookPlayerSeekButton({super.key, required this.isForward});
|
||||||
super.key,
|
|
||||||
required this.isForward,
|
|
||||||
});
|
|
||||||
|
|
||||||
/// if true, the button seeks forward, else it seeks backwards
|
/// if true, the button seeks forward, else it seeks backwards
|
||||||
final bool isForward;
|
final bool isForward;
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,7 @@ import 'package:vaani/constants/sizes.dart';
|
||||||
import 'package:vaani/features/player/providers/audiobook_player.dart';
|
import 'package:vaani/features/player/providers/audiobook_player.dart';
|
||||||
|
|
||||||
class AudiobookPlayerSeekChapterButton extends HookConsumerWidget {
|
class AudiobookPlayerSeekChapterButton extends HookConsumerWidget {
|
||||||
const AudiobookPlayerSeekChapterButton({
|
const AudiobookPlayerSeekChapterButton({super.key, required this.isForward});
|
||||||
super.key,
|
|
||||||
required this.isForward,
|
|
||||||
});
|
|
||||||
|
|
||||||
/// if true, the button seeks forward, else it seeks backwards
|
/// if true, the button seeks forward, else it seeks backwards
|
||||||
final bool isForward;
|
final bool isForward;
|
||||||
|
|
@ -27,9 +24,7 @@ class AudiobookPlayerSeekChapterButton extends HookConsumerWidget {
|
||||||
void seekForward() {
|
void seekForward() {
|
||||||
final index = player.book!.chapters.indexOf(player.currentChapter!);
|
final index = player.book!.chapters.indexOf(player.currentChapter!);
|
||||||
if (index < player.book!.chapters.length - 1) {
|
if (index < player.book!.chapters.length - 1) {
|
||||||
player.seek(
|
player.seek(player.book!.chapters[index + 1].start + offset);
|
||||||
player.book!.chapters[index + 1].start + offset,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
player.seek(player.currentChapter!.end);
|
player.seek(player.currentChapter!.end);
|
||||||
}
|
}
|
||||||
|
|
@ -37,8 +32,9 @@ class AudiobookPlayerSeekChapterButton extends HookConsumerWidget {
|
||||||
|
|
||||||
/// seek backward to the previous chapter or the start of the current chapter
|
/// seek backward to the previous chapter or the start of the current chapter
|
||||||
void seekBackward() {
|
void seekBackward() {
|
||||||
final currentPlayingChapterIndex =
|
final currentPlayingChapterIndex = player.book!.chapters.indexOf(
|
||||||
player.book!.chapters.indexOf(player.currentChapter!);
|
player.currentChapter!,
|
||||||
|
);
|
||||||
final chapterPosition =
|
final chapterPosition =
|
||||||
player.positionInBook - player.currentChapter!.start;
|
player.positionInBook - player.currentChapter!.start;
|
||||||
BookChapter chapterToSeekTo;
|
BookChapter chapterToSeekTo;
|
||||||
|
|
@ -49,9 +45,7 @@ class AudiobookPlayerSeekChapterButton extends HookConsumerWidget {
|
||||||
} else {
|
} else {
|
||||||
chapterToSeekTo = player.currentChapter!;
|
chapterToSeekTo = player.currentChapter!;
|
||||||
}
|
}
|
||||||
player.seek(
|
player.seek(chapterToSeekTo.start + offset);
|
||||||
chapterToSeekTo.start + offset,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return IconButton(
|
return IconButton(
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,7 @@ import 'package:vaani/shared/extensions/duration_format.dart'
|
||||||
import 'package:vaani/shared/hooks.dart' show useTimer;
|
import 'package:vaani/shared/hooks.dart' show useTimer;
|
||||||
|
|
||||||
class ChapterSelectionButton extends HookConsumerWidget {
|
class ChapterSelectionButton extends HookConsumerWidget {
|
||||||
const ChapterSelectionButton({
|
const ChapterSelectionButton({super.key});
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
|
@ -49,9 +47,7 @@ class ChapterSelectionButton extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChapterSelectionModal extends HookConsumerWidget {
|
class ChapterSelectionModal extends HookConsumerWidget {
|
||||||
const ChapterSelectionModal({
|
const ChapterSelectionModal({super.key});
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
|
@ -87,41 +83,40 @@ class ChapterSelectionModal extends HookConsumerWidget {
|
||||||
child: currentBook?.chapters == null
|
child: currentBook?.chapters == null
|
||||||
? const Text('No chapters found')
|
? const Text('No chapters found')
|
||||||
: Column(
|
: Column(
|
||||||
children: currentBook!.chapters.map(
|
children: currentBook!.chapters.map((chapter) {
|
||||||
(chapter) {
|
final isCurrent = currentChapterIndex == chapter.id;
|
||||||
final isCurrent = currentChapterIndex == chapter.id;
|
final isPlayed =
|
||||||
final isPlayed = currentChapterIndex != null &&
|
currentChapterIndex != null &&
|
||||||
chapter.id < currentChapterIndex;
|
chapter.id < currentChapterIndex;
|
||||||
return ListTile(
|
return ListTile(
|
||||||
autofocus: isCurrent,
|
autofocus: isCurrent,
|
||||||
iconColor: isPlayed && !isCurrent
|
iconColor: isPlayed && !isCurrent
|
||||||
? theme.disabledColor
|
? theme.disabledColor
|
||||||
|
: null,
|
||||||
|
title: Text(
|
||||||
|
chapter.title,
|
||||||
|
style: isPlayed && !isCurrent
|
||||||
|
? TextStyle(color: theme.disabledColor)
|
||||||
: null,
|
: null,
|
||||||
title: Text(
|
),
|
||||||
chapter.title,
|
subtitle: Text(
|
||||||
style: isPlayed && !isCurrent
|
'(${chapter.duration.smartBinaryFormat})',
|
||||||
? TextStyle(color: theme.disabledColor)
|
style: isPlayed && !isCurrent
|
||||||
: null,
|
? TextStyle(color: theme.disabledColor)
|
||||||
),
|
: null,
|
||||||
subtitle: Text(
|
),
|
||||||
'(${chapter.duration.smartBinaryFormat})',
|
trailing: isCurrent
|
||||||
style: isPlayed && !isCurrent
|
? const PlayingIndicatorIcon()
|
||||||
? TextStyle(color: theme.disabledColor)
|
: const Icon(Icons.play_arrow),
|
||||||
: null,
|
selected: isCurrent,
|
||||||
),
|
key: isCurrent ? chapterKey : null,
|
||||||
trailing: isCurrent
|
onTap: () {
|
||||||
? const PlayingIndicatorIcon()
|
Navigator.of(context).pop();
|
||||||
: const Icon(Icons.play_arrow),
|
notifier.seek(chapter.start + 90.ms);
|
||||||
selected: isCurrent,
|
notifier.play();
|
||||||
key: isCurrent ? chapterKey : null,
|
},
|
||||||
onTap: () {
|
);
|
||||||
Navigator.of(context).pop();
|
}).toList(),
|
||||||
notifier.seek(chapter.start + 90.ms);
|
|
||||||
notifier.play();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
).toList(),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,7 @@ import 'package:vaani/settings/app_settings_provider.dart';
|
||||||
final _logger = Logger('PlayerSpeedAdjustButton');
|
final _logger = Logger('PlayerSpeedAdjustButton');
|
||||||
|
|
||||||
class PlayerSpeedAdjustButton extends HookConsumerWidget {
|
class PlayerSpeedAdjustButton extends HookConsumerWidget {
|
||||||
const PlayerSpeedAdjustButton({
|
const PlayerSpeedAdjustButton({super.key});
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
|
@ -35,21 +33,19 @@ class PlayerSpeedAdjustButton extends HookConsumerWidget {
|
||||||
notifier.setSpeed(speed);
|
notifier.setSpeed(speed);
|
||||||
if (appSettings.playerSettings.configurePlayerForEveryBook) {
|
if (appSettings.playerSettings.configurePlayerForEveryBook) {
|
||||||
ref
|
ref
|
||||||
.read(
|
.read(bookSettingsProvider(bookId).notifier)
|
||||||
bookSettingsProvider(bookId).notifier,
|
|
||||||
)
|
|
||||||
.update(
|
.update(
|
||||||
bookSettings.copyWith
|
bookSettings.copyWith.playerSettings(
|
||||||
.playerSettings(preferredDefaultSpeed: speed),
|
preferredDefaultSpeed: speed,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
ref
|
ref
|
||||||
.read(
|
.read(appSettingsProvider.notifier)
|
||||||
appSettingsProvider.notifier,
|
|
||||||
)
|
|
||||||
.update(
|
.update(
|
||||||
appSettings.copyWith
|
appSettings.copyWith.playerSettings(
|
||||||
.playerSettings(preferredDefaultSpeed: speed),
|
preferredDefaultSpeed: speed,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,11 @@ class _PlayingIndicatorIconState extends State<PlayingIndicatorIcon> {
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_animationParams =
|
_animationParams = List.generate(
|
||||||
List.generate(widget.barCount, _createRandomParams, growable: false);
|
widget.barCount,
|
||||||
|
_createRandomParams,
|
||||||
|
growable: false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper to generate random parameters for one bar's animation cycle
|
// Helper to generate random parameters for one bar's animation cycle
|
||||||
|
|
@ -72,10 +75,12 @@ class _PlayingIndicatorIconState extends State<PlayingIndicatorIcon> {
|
||||||
|
|
||||||
// Note: These factors represent the scale relative to the *half-height*
|
// Note: These factors represent the scale relative to the *half-height*
|
||||||
// if centerSymmetric is true, controlled by the alignment in scaleY.
|
// if centerSymmetric is true, controlled by the alignment in scaleY.
|
||||||
final targetHeightFactor1 = widget.minHeightFactor +
|
final targetHeightFactor1 =
|
||||||
|
widget.minHeightFactor +
|
||||||
_random.nextDouble() *
|
_random.nextDouble() *
|
||||||
(widget.maxHeightFactor - widget.minHeightFactor);
|
(widget.maxHeightFactor - widget.minHeightFactor);
|
||||||
final targetHeightFactor2 = widget.minHeightFactor +
|
final targetHeightFactor2 =
|
||||||
|
widget.minHeightFactor +
|
||||||
_random.nextDouble() *
|
_random.nextDouble() *
|
||||||
(widget.maxHeightFactor - widget.minHeightFactor);
|
(widget.maxHeightFactor - widget.minHeightFactor);
|
||||||
|
|
||||||
|
|
@ -95,7 +100,8 @@ class _PlayingIndicatorIconState extends State<PlayingIndicatorIcon> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final color = widget.color ??
|
final color =
|
||||||
|
widget.color ??
|
||||||
IconTheme.of(context).color ??
|
IconTheme.of(context).color ??
|
||||||
Theme.of(context).colorScheme.primary;
|
Theme.of(context).colorScheme.primary;
|
||||||
|
|
||||||
|
|
@ -110,8 +116,9 @@ class _PlayingIndicatorIconState extends State<PlayingIndicatorIcon> {
|
||||||
final double maxHeight = widget.size;
|
final double maxHeight = widget.size;
|
||||||
|
|
||||||
// Determine the alignment for scaling based on the symmetric flag
|
// Determine the alignment for scaling based on the symmetric flag
|
||||||
final Alignment scaleAlignment =
|
final Alignment scaleAlignment = widget.centerSymmetric
|
||||||
widget.centerSymmetric ? Alignment.center : Alignment.bottomCenter;
|
? Alignment.center
|
||||||
|
: Alignment.bottomCenter;
|
||||||
|
|
||||||
// Determine the cross axis alignment for the Row
|
// Determine the cross axis alignment for the Row
|
||||||
final CrossAxisAlignment rowAlignment = widget.centerSymmetric
|
final CrossAxisAlignment rowAlignment = widget.centerSymmetric
|
||||||
|
|
@ -129,47 +136,40 @@ class _PlayingIndicatorIconState extends State<PlayingIndicatorIcon> {
|
||||||
crossAxisAlignment: rowAlignment,
|
crossAxisAlignment: rowAlignment,
|
||||||
// Use spaceEvenly for better distribution, especially with center alignment
|
// Use spaceEvenly for better distribution, especially with center alignment
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
children: List.generate(
|
children: List.generate(widget.barCount, (index) {
|
||||||
widget.barCount,
|
final params = _animationParams[index];
|
||||||
(index) {
|
// The actual bar widget that will be animated
|
||||||
final params = _animationParams[index];
|
return Container(
|
||||||
// The actual bar widget that will be animated
|
width: barWidth,
|
||||||
return Container(
|
// Set initial height to the max potential height
|
||||||
width: barWidth,
|
// The scaleY animation will control the visible height
|
||||||
// Set initial height to the max potential height
|
height: maxHeight,
|
||||||
// The scaleY animation will control the visible height
|
decoration: BoxDecoration(
|
||||||
height: maxHeight,
|
color: color,
|
||||||
decoration: BoxDecoration(
|
borderRadius: BorderRadius.circular(barWidth / 2),
|
||||||
color: color,
|
),
|
||||||
borderRadius: BorderRadius.circular(barWidth / 2),
|
)
|
||||||
),
|
.animate(
|
||||||
)
|
delay: params.initialDelay,
|
||||||
.animate(
|
onPlay: (controller) => controller.repeat(reverse: true),
|
||||||
delay: params.initialDelay,
|
)
|
||||||
onPlay: (controller) => controller.repeat(
|
// 1. Scale to targetHeightFactor1
|
||||||
reverse: true,
|
.scaleY(
|
||||||
),
|
begin: widget.minHeightFactor, // Scale factor starts near min
|
||||||
)
|
end: params.targetHeightFactor1,
|
||||||
// 1. Scale to targetHeightFactor1
|
duration: params.duration1,
|
||||||
.scaleY(
|
curve: Curves.easeInOutCirc,
|
||||||
begin:
|
alignment: scaleAlignment, // Apply chosen alignment
|
||||||
widget.minHeightFactor, // Scale factor starts near min
|
)
|
||||||
end: params.targetHeightFactor1,
|
// 2. Then scale to targetHeightFactor2
|
||||||
duration: params.duration1,
|
.then()
|
||||||
curve: Curves.easeInOutCirc,
|
.scaleY(
|
||||||
alignment: scaleAlignment, // Apply chosen alignment
|
end: params.targetHeightFactor2,
|
||||||
)
|
duration: params.duration2,
|
||||||
// 2. Then scale to targetHeightFactor2
|
curve: Curves.easeInOutCirc,
|
||||||
.then()
|
alignment: scaleAlignment, // Apply chosen alignment
|
||||||
.scaleY(
|
);
|
||||||
end: params.targetHeightFactor2,
|
}, growable: false),
|
||||||
duration: params.duration2,
|
|
||||||
curve: Curves.easeInOutCirc,
|
|
||||||
alignment: scaleAlignment, // Apply chosen alignment
|
|
||||||
);
|
|
||||||
},
|
|
||||||
growable: false,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,7 @@ import 'package:vaani/settings/app_settings_provider.dart';
|
||||||
const double itemExtent = 25;
|
const double itemExtent = 25;
|
||||||
|
|
||||||
class SpeedSelector extends HookConsumerWidget {
|
class SpeedSelector extends HookConsumerWidget {
|
||||||
const SpeedSelector({
|
const SpeedSelector({super.key, required this.onSpeedSelected});
|
||||||
super.key,
|
|
||||||
required this.onSpeedSelected,
|
|
||||||
});
|
|
||||||
|
|
||||||
final void Function(double speed) onSpeedSelected;
|
final void Function(double speed) onSpeedSelected;
|
||||||
|
|
||||||
|
|
@ -26,34 +23,22 @@ class SpeedSelector extends HookConsumerWidget {
|
||||||
final speedState = useState(currentSpeed);
|
final speedState = useState(currentSpeed);
|
||||||
|
|
||||||
// hook the onSpeedSelected function to the state
|
// hook the onSpeedSelected function to the state
|
||||||
useEffect(
|
useEffect(() {
|
||||||
() {
|
onSpeedSelected(speedState.value);
|
||||||
onSpeedSelected(speedState.value);
|
return null;
|
||||||
return null;
|
}, [speedState.value]);
|
||||||
},
|
|
||||||
[speedState.value],
|
|
||||||
);
|
|
||||||
|
|
||||||
// the speed options
|
// the speed options
|
||||||
final minSpeed = min(
|
final minSpeed = min(speeds.reduce(min), playerSettings.minSpeed);
|
||||||
speeds.reduce(min),
|
final maxSpeed = max(speeds.reduce(max), playerSettings.maxSpeed);
|
||||||
playerSettings.minSpeed,
|
|
||||||
);
|
|
||||||
final maxSpeed = max(
|
|
||||||
speeds.reduce(max),
|
|
||||||
playerSettings.maxSpeed,
|
|
||||||
);
|
|
||||||
final speedIncrement = playerSettings.speedIncrement;
|
final speedIncrement = playerSettings.speedIncrement;
|
||||||
final availableSpeeds = ((maxSpeed - minSpeed) / speedIncrement).ceil() + 1;
|
final availableSpeeds = ((maxSpeed - minSpeed) / speedIncrement).ceil() + 1;
|
||||||
final availableSpeedsList = List.generate(
|
final availableSpeedsList = List.generate(availableSpeeds, (index) {
|
||||||
availableSpeeds,
|
// need to round to 2 decimal place to avoid floating point errors
|
||||||
(index) {
|
return double.parse(
|
||||||
// need to round to 2 decimal place to avoid floating point errors
|
(minSpeed + index * speedIncrement).toStringAsFixed(2),
|
||||||
return double.parse(
|
);
|
||||||
(minSpeed + index * speedIncrement).toStringAsFixed(2),
|
});
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
final scrollController = useFixedExtentScrollController(
|
final scrollController = useFixedExtentScrollController(
|
||||||
initialItem: availableSpeedsList.indexOf(currentSpeed),
|
initialItem: availableSpeedsList.indexOf(currentSpeed),
|
||||||
|
|
@ -107,18 +92,19 @@ class SpeedSelector extends HookConsumerWidget {
|
||||||
(speed) => TextButton(
|
(speed) => TextButton(
|
||||||
style: speed == speedState.value
|
style: speed == speedState.value
|
||||||
? TextButton.styleFrom(
|
? TextButton.styleFrom(
|
||||||
backgroundColor:
|
backgroundColor: Theme.of(
|
||||||
Theme.of(context).colorScheme.primaryContainer,
|
context,
|
||||||
foregroundColor: Theme.of(context)
|
).colorScheme.primaryContainer,
|
||||||
.colorScheme
|
foregroundColor: Theme.of(
|
||||||
.onPrimaryContainer,
|
context,
|
||||||
|
).colorScheme.onPrimaryContainer,
|
||||||
)
|
)
|
||||||
// border if not selected
|
// border if not selected
|
||||||
: TextButton.styleFrom(
|
: TextButton.styleFrom(
|
||||||
side: BorderSide(
|
side: BorderSide(
|
||||||
color: Theme.of(context)
|
color: Theme.of(
|
||||||
.colorScheme
|
context,
|
||||||
.primaryContainer,
|
).colorScheme.primaryContainer,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
|
|
@ -195,14 +181,13 @@ class SpeedWheel extends StatelessWidget {
|
||||||
controller: scrollController,
|
controller: scrollController,
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
itemExtent: itemExtent,
|
itemExtent: itemExtent,
|
||||||
diameterRatio: 1.5, squeeze: 1.2,
|
diameterRatio: 1.5,
|
||||||
|
squeeze: 1.2,
|
||||||
// useMagnifier: true,
|
// useMagnifier: true,
|
||||||
// magnification: 1.5,
|
// magnification: 1.5,
|
||||||
physics: const FixedExtentScrollPhysics(),
|
physics: const FixedExtentScrollPhysics(),
|
||||||
children: availableSpeedsList
|
children: availableSpeedsList
|
||||||
.map(
|
.map((speed) => SpeedLine(speed: speed))
|
||||||
(speed) => SpeedLine(speed: speed),
|
|
||||||
)
|
|
||||||
.toList(),
|
.toList(),
|
||||||
onSelectedItemChanged: (index) {
|
onSelectedItemChanged: (index) {
|
||||||
speedState.value = availableSpeedsList[index];
|
speedState.value = availableSpeedsList[index];
|
||||||
|
|
@ -232,10 +217,7 @@ class SpeedWheel extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class SpeedLine extends StatelessWidget {
|
class SpeedLine extends StatelessWidget {
|
||||||
const SpeedLine({
|
const SpeedLine({super.key, required this.speed});
|
||||||
super.key,
|
|
||||||
required this.speed,
|
|
||||||
});
|
|
||||||
|
|
||||||
final double speed;
|
final double speed;
|
||||||
|
|
||||||
|
|
@ -250,8 +232,8 @@ class SpeedLine extends StatelessWidget {
|
||||||
width: speed % 0.5 == 0
|
width: speed % 0.5 == 0
|
||||||
? 3
|
? 3
|
||||||
: speed % 0.25 == 0
|
: speed % 0.25 == 0
|
||||||
? 2
|
? 2
|
||||||
: 0.5,
|
: 0.5,
|
||||||
color: Theme.of(context).colorScheme.onSurface,
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ class ShakeDetector {
|
||||||
DateTime _lastShakeTime = DateTime.now();
|
DateTime _lastShakeTime = DateTime.now();
|
||||||
|
|
||||||
final StreamController<UserAccelerometerEvent>
|
final StreamController<UserAccelerometerEvent>
|
||||||
_detectedShakeStreamController = StreamController.broadcast();
|
_detectedShakeStreamController = StreamController.broadcast();
|
||||||
|
|
||||||
void start() {
|
void start() {
|
||||||
if (_accelerometerSubscription != null) {
|
if (_accelerometerSubscription != null) {
|
||||||
|
|
@ -37,26 +37,27 @@ class ShakeDetector {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_accelerometerSubscription =
|
_accelerometerSubscription =
|
||||||
userAccelerometerEventStream(samplingPeriod: _settings.samplingPeriod)
|
userAccelerometerEventStream(
|
||||||
.listen((event) {
|
samplingPeriod: _settings.samplingPeriod,
|
||||||
_logger.finest('RMS: ${event.rms}');
|
).listen((event) {
|
||||||
if (event.rms > _settings.threshold) {
|
_logger.finest('RMS: ${event.rms}');
|
||||||
_currentShakeCount++;
|
if (event.rms > _settings.threshold) {
|
||||||
|
_currentShakeCount++;
|
||||||
|
|
||||||
if (_currentShakeCount >= _settings.shakeTriggerCount &&
|
if (_currentShakeCount >= _settings.shakeTriggerCount &&
|
||||||
!isCoolDownNeeded()) {
|
!isCoolDownNeeded()) {
|
||||||
_logger.fine('Shake detected $_currentShakeCount times');
|
_logger.fine('Shake detected $_currentShakeCount times');
|
||||||
|
|
||||||
onShakeDetected?.call();
|
onShakeDetected?.call();
|
||||||
_detectedShakeStreamController.add(event);
|
_detectedShakeStreamController.add(event);
|
||||||
|
|
||||||
_lastShakeTime = DateTime.now();
|
_lastShakeTime = DateTime.now();
|
||||||
_currentShakeCount = 0;
|
_currentShakeCount = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_currentShakeCount = 0;
|
_currentShakeCount = 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
_logger.fine('ShakeDetector started');
|
_logger.fine('ShakeDetector started');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,34 +59,29 @@ class ShakeDetector extends _$ShakeDetector {
|
||||||
final sleepTimer = ref.watch(sleepTimerProvider);
|
final sleepTimer = ref.watch(sleepTimerProvider);
|
||||||
if (!shakeDetectionSettings.shakeAction.isPlaybackManagementEnabled &&
|
if (!shakeDetectionSettings.shakeAction.isPlaybackManagementEnabled &&
|
||||||
sleepTimer == null) {
|
sleepTimer == null) {
|
||||||
_logger
|
_logger.config(
|
||||||
.config('No playback management is enabled and sleep timer is off, '
|
'No playback management is enabled and sleep timer is off, '
|
||||||
'so shake detection is disabled');
|
'so shake detection is disabled',
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.config('Creating shake detector');
|
_logger.config('Creating shake detector');
|
||||||
final detector = core.ShakeDetector(
|
final detector = core.ShakeDetector(shakeDetectionSettings, () {
|
||||||
shakeDetectionSettings,
|
final wasActionComplete = doShakeAction(
|
||||||
() {
|
shakeDetectionSettings.shakeAction,
|
||||||
final wasActionComplete = doShakeAction(
|
ref: ref,
|
||||||
shakeDetectionSettings.shakeAction,
|
);
|
||||||
ref: ref,
|
if (wasActionComplete) {
|
||||||
);
|
shakeDetectionSettings.feedback.forEach(postShakeFeedback);
|
||||||
if (wasActionComplete) {
|
}
|
||||||
shakeDetectionSettings.feedback.forEach(postShakeFeedback);
|
});
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
ref.onDispose(detector.dispose);
|
ref.onDispose(detector.dispose);
|
||||||
return detector;
|
return detector;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform the shake action and return whether the action was successful
|
/// Perform the shake action and return whether the action was successful
|
||||||
bool doShakeAction(
|
bool doShakeAction(ShakeAction shakeAction, {required Ref ref}) {
|
||||||
ShakeAction shakeAction, {
|
|
||||||
required Ref ref,
|
|
||||||
}) {
|
|
||||||
final player = ref.read(simpleAudiobookPlayerProvider);
|
final player = ref.read(simpleAudiobookPlayerProvider);
|
||||||
if (player.book == null && shakeAction.isPlaybackManagementEnabled) {
|
if (player.book == null && shakeAction.isPlaybackManagementEnabled) {
|
||||||
_logger.warning('No book is loaded');
|
_logger.warning('No book is loaded');
|
||||||
|
|
@ -166,8 +161,11 @@ extension on ShakeAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get isPlaybackManagementEnabled {
|
bool get isPlaybackManagementEnabled {
|
||||||
return {ShakeAction.playPause, ShakeAction.fastForward, ShakeAction.rewind}
|
return {
|
||||||
.contains(this);
|
ShakeAction.playPause,
|
||||||
|
ShakeAction.fastForward,
|
||||||
|
ShakeAction.rewind,
|
||||||
|
}.contains(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get shouldActOnSleepTimer {
|
bool get shouldActOnSleepTimer {
|
||||||
|
|
|
||||||
|
|
@ -6,21 +6,57 @@ part of 'shake_detector.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint, type=warning
|
||||||
|
|
||||||
|
@ProviderFor(ShakeDetector)
|
||||||
|
final shakeDetectorProvider = ShakeDetectorProvider._();
|
||||||
|
|
||||||
|
final class ShakeDetectorProvider
|
||||||
|
extends $NotifierProvider<ShakeDetector, core.ShakeDetector?> {
|
||||||
|
ShakeDetectorProvider._()
|
||||||
|
: super(
|
||||||
|
from: null,
|
||||||
|
argument: null,
|
||||||
|
retry: null,
|
||||||
|
name: r'shakeDetectorProvider',
|
||||||
|
isAutoDispose: true,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$shakeDetectorHash();
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
ShakeDetector create() => ShakeDetector();
|
||||||
|
|
||||||
|
/// {@macro riverpod.override_with_value}
|
||||||
|
Override overrideWithValue(core.ShakeDetector? value) {
|
||||||
|
return $ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
providerOverride: $SyncValueProvider<core.ShakeDetector?>(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String _$shakeDetectorHash() => r'2a380bab1d4021d05d2ae40fec964a5f33d3730c';
|
String _$shakeDetectorHash() => r'2a380bab1d4021d05d2ae40fec964a5f33d3730c';
|
||||||
|
|
||||||
/// See also [ShakeDetector].
|
abstract class _$ShakeDetector extends $Notifier<core.ShakeDetector?> {
|
||||||
@ProviderFor(ShakeDetector)
|
core.ShakeDetector? build();
|
||||||
final shakeDetectorProvider =
|
@$mustCallSuper
|
||||||
AutoDisposeNotifierProvider<ShakeDetector, core.ShakeDetector?>.internal(
|
@override
|
||||||
ShakeDetector.new,
|
void runBuild() {
|
||||||
name: r'shakeDetectorProvider',
|
final ref = this.ref as $Ref<core.ShakeDetector?, core.ShakeDetector?>;
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
final element =
|
||||||
? null
|
ref.element
|
||||||
: _$shakeDetectorHash,
|
as $ClassProviderElement<
|
||||||
dependencies: null,
|
AnyNotifier<core.ShakeDetector?, core.ShakeDetector?>,
|
||||||
allTransitiveDependencies: null,
|
core.ShakeDetector?,
|
||||||
);
|
Object?,
|
||||||
|
Object?
|
||||||
typedef _$ShakeDetector = AutoDisposeNotifier<core.ShakeDetector?>;
|
>;
|
||||||
// ignore_for_file: type=lint
|
element.handleCreate(ref, build);
|
||||||
// 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
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,9 +94,7 @@ class SleepTimer {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// starts the timer with the given duration or the default duration
|
/// starts the timer with the given duration or the default duration
|
||||||
void startCountDown([
|
void startCountDown([Duration? forDuration]) {
|
||||||
Duration? forDuration,
|
|
||||||
]) {
|
|
||||||
clearCountDownTimer();
|
clearCountDownTimer();
|
||||||
duration = forDuration ?? duration;
|
duration = forDuration ?? duration;
|
||||||
timer = Timer(duration, () {
|
timer = Timer(duration, () {
|
||||||
|
|
|
||||||
|
|
@ -6,20 +6,57 @@ part of 'sleep_timer_provider.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint, type=warning
|
||||||
|
|
||||||
|
@ProviderFor(SleepTimer)
|
||||||
|
final sleepTimerProvider = SleepTimerProvider._();
|
||||||
|
|
||||||
|
final class SleepTimerProvider
|
||||||
|
extends $NotifierProvider<SleepTimer, core.SleepTimer?> {
|
||||||
|
SleepTimerProvider._()
|
||||||
|
: super(
|
||||||
|
from: null,
|
||||||
|
argument: null,
|
||||||
|
retry: null,
|
||||||
|
name: r'sleepTimerProvider',
|
||||||
|
isAutoDispose: false,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$sleepTimerHash();
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
SleepTimer create() => SleepTimer();
|
||||||
|
|
||||||
|
/// {@macro riverpod.override_with_value}
|
||||||
|
Override overrideWithValue(core.SleepTimer? value) {
|
||||||
|
return $ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
providerOverride: $SyncValueProvider<core.SleepTimer?>(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String _$sleepTimerHash() => r'2679454a217d0630a833d730557ab4e4feac2e56';
|
String _$sleepTimerHash() => r'2679454a217d0630a833d730557ab4e4feac2e56';
|
||||||
|
|
||||||
/// See also [SleepTimer].
|
abstract class _$SleepTimer extends $Notifier<core.SleepTimer?> {
|
||||||
@ProviderFor(SleepTimer)
|
core.SleepTimer? build();
|
||||||
final sleepTimerProvider =
|
@$mustCallSuper
|
||||||
NotifierProvider<SleepTimer, core.SleepTimer?>.internal(
|
@override
|
||||||
SleepTimer.new,
|
void runBuild() {
|
||||||
name: r'sleepTimerProvider',
|
final ref = this.ref as $Ref<core.SleepTimer?, core.SleepTimer?>;
|
||||||
debugGetCreateSourceHash:
|
final element =
|
||||||
const bool.fromEnvironment('dart.vm.product') ? null : _$sleepTimerHash,
|
ref.element
|
||||||
dependencies: null,
|
as $ClassProviderElement<
|
||||||
allTransitiveDependencies: null,
|
AnyNotifier<core.SleepTimer?, core.SleepTimer?>,
|
||||||
);
|
core.SleepTimer?,
|
||||||
|
Object?,
|
||||||
typedef _$SleepTimer = Notifier<core.SleepTimer?>;
|
Object?
|
||||||
// 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
|
element.handleCreate(ref, build);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,7 @@ import 'package:vaani/settings/app_settings_provider.dart';
|
||||||
import 'package:vaani/shared/extensions/duration_format.dart';
|
import 'package:vaani/shared/extensions/duration_format.dart';
|
||||||
|
|
||||||
class SleepTimerButton extends HookConsumerWidget {
|
class SleepTimerButton extends HookConsumerWidget {
|
||||||
const SleepTimerButton({
|
const SleepTimerButton({super.key});
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
|
@ -47,8 +45,9 @@ class SleepTimerButton extends HookConsumerWidget {
|
||||||
);
|
);
|
||||||
pendingPlayerModals--;
|
pendingPlayerModals--;
|
||||||
ref.read(sleepTimerProvider.notifier).setTimer(durationState.value);
|
ref.read(sleepTimerProvider.notifier).setTimer(durationState.value);
|
||||||
appLogger
|
appLogger.fine(
|
||||||
.fine('Sleep Timer dialog closed with ${durationState.value}');
|
'Sleep Timer dialog closed with ${durationState.value}',
|
||||||
|
);
|
||||||
},
|
},
|
||||||
child: AnimatedSwitcher(
|
child: AnimatedSwitcher(
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
|
|
@ -57,9 +56,7 @@ class SleepTimerButton extends HookConsumerWidget {
|
||||||
Symbols.bedtime,
|
Symbols.bedtime,
|
||||||
color: Theme.of(context).colorScheme.onSurface,
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
)
|
)
|
||||||
: RemainingSleepTimeDisplay(
|
: RemainingSleepTimeDisplay(timer: sleepTimer),
|
||||||
timer: sleepTimer,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
@ -67,10 +64,7 @@ class SleepTimerButton extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class SleepTimerBottomSheet extends HookConsumerWidget {
|
class SleepTimerBottomSheet extends HookConsumerWidget {
|
||||||
const SleepTimerBottomSheet({
|
const SleepTimerBottomSheet({super.key, this.onDurationSelected});
|
||||||
super.key,
|
|
||||||
this.onDurationSelected,
|
|
||||||
});
|
|
||||||
|
|
||||||
final void Function(Duration?)? onDurationSelected;
|
final void Function(Duration?)? onDurationSelected;
|
||||||
|
|
||||||
|
|
@ -91,8 +85,9 @@ class SleepTimerBottomSheet extends HookConsumerWidget {
|
||||||
];
|
];
|
||||||
|
|
||||||
final scrollController = useFixedExtentScrollController(
|
final scrollController = useFixedExtentScrollController(
|
||||||
initialItem:
|
initialItem: allPossibleDurations.indexOf(
|
||||||
allPossibleDurations.indexOf(sleepTimer?.duration ?? minDuration),
|
sleepTimer?.duration ?? minDuration,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
final durationState = useState<Duration>(
|
final durationState = useState<Duration>(
|
||||||
|
|
@ -100,13 +95,10 @@ class SleepTimerBottomSheet extends HookConsumerWidget {
|
||||||
);
|
);
|
||||||
|
|
||||||
// useEffect to rebuild the sleep timer when the duration changes
|
// useEffect to rebuild the sleep timer when the duration changes
|
||||||
useEffect(
|
useEffect(() {
|
||||||
() {
|
onDurationSelected?.call(durationState.value);
|
||||||
onDurationSelected?.call(durationState.value);
|
return null;
|
||||||
return null;
|
}, [durationState.value]);
|
||||||
},
|
|
||||||
[durationState.value],
|
|
||||||
);
|
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
|
@ -171,18 +163,19 @@ class SleepTimerBottomSheet extends HookConsumerWidget {
|
||||||
(timerDuration) => TextButton(
|
(timerDuration) => TextButton(
|
||||||
style: timerDuration == durationState.value
|
style: timerDuration == durationState.value
|
||||||
? TextButton.styleFrom(
|
? TextButton.styleFrom(
|
||||||
backgroundColor:
|
backgroundColor: Theme.of(
|
||||||
Theme.of(context).colorScheme.primaryContainer,
|
context,
|
||||||
foregroundColor: Theme.of(context)
|
).colorScheme.primaryContainer,
|
||||||
.colorScheme
|
foregroundColor: Theme.of(
|
||||||
.onPrimaryContainer,
|
context,
|
||||||
|
).colorScheme.onPrimaryContainer,
|
||||||
)
|
)
|
||||||
// border if not selected
|
// border if not selected
|
||||||
: TextButton.styleFrom(
|
: TextButton.styleFrom(
|
||||||
side: BorderSide(
|
side: BorderSide(
|
||||||
color: Theme.of(context)
|
color: Theme.of(
|
||||||
.colorScheme
|
context,
|
||||||
.primaryContainer,
|
).colorScheme.primaryContainer,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
|
|
@ -215,10 +208,7 @@ class SleepTimerBottomSheet extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class RemainingSleepTimeDisplay extends HookConsumerWidget {
|
class RemainingSleepTimeDisplay extends HookConsumerWidget {
|
||||||
const RemainingSleepTimeDisplay({
|
const RemainingSleepTimeDisplay({super.key, required this.timer});
|
||||||
super.key,
|
|
||||||
required this.timer,
|
|
||||||
});
|
|
||||||
|
|
||||||
final SleepTimer timer;
|
final SleepTimer timer;
|
||||||
|
|
||||||
|
|
@ -230,17 +220,14 @@ class RemainingSleepTimeDisplay extends HookConsumerWidget {
|
||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
),
|
),
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
horizontal: 8,
|
|
||||||
vertical: 4,
|
|
||||||
),
|
|
||||||
child: Text(
|
child: Text(
|
||||||
timer.timer == null
|
timer.timer == null
|
||||||
? timer.duration.smartBinaryFormat
|
? timer.duration.smartBinaryFormat
|
||||||
: remainingTime?.smartBinaryFormat ?? '',
|
: remainingTime?.smartBinaryFormat ?? '',
|
||||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
color: Theme.of(context).colorScheme.onPrimary,
|
color: Theme.of(context).colorScheme.onPrimary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -272,8 +259,9 @@ class SleepTimerWheel extends StatelessWidget {
|
||||||
icon: const Icon(Icons.remove),
|
icon: const Icon(Icons.remove),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// animate to index - 1
|
// animate to index - 1
|
||||||
final index = availableDurations
|
final index = availableDurations.indexOf(
|
||||||
.indexOf(durationState.value ?? Duration.zero);
|
durationState.value ?? Duration.zero,
|
||||||
|
);
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
scrollController.animateToItem(
|
scrollController.animateToItem(
|
||||||
index - 1,
|
index - 1,
|
||||||
|
|
@ -289,14 +277,13 @@ class SleepTimerWheel extends StatelessWidget {
|
||||||
controller: scrollController,
|
controller: scrollController,
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
itemExtent: itemExtent,
|
itemExtent: itemExtent,
|
||||||
diameterRatio: 1.5, squeeze: 1.2,
|
diameterRatio: 1.5,
|
||||||
|
squeeze: 1.2,
|
||||||
// useMagnifier: true,
|
// useMagnifier: true,
|
||||||
// magnification: 1.5,
|
// magnification: 1.5,
|
||||||
physics: const FixedExtentScrollPhysics(),
|
physics: const FixedExtentScrollPhysics(),
|
||||||
children: availableDurations
|
children: availableDurations
|
||||||
.map(
|
.map((duration) => DurationLine(duration: duration))
|
||||||
(duration) => DurationLine(duration: duration),
|
|
||||||
)
|
|
||||||
.toList(),
|
.toList(),
|
||||||
onSelectedItemChanged: (index) {
|
onSelectedItemChanged: (index) {
|
||||||
durationState.value = availableDurations[index];
|
durationState.value = availableDurations[index];
|
||||||
|
|
@ -310,8 +297,9 @@ class SleepTimerWheel extends StatelessWidget {
|
||||||
icon: const Icon(Icons.add),
|
icon: const Icon(Icons.add),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// animate to index + 1
|
// animate to index + 1
|
||||||
final index = availableDurations
|
final index = availableDurations.indexOf(
|
||||||
.indexOf(durationState.value ?? Duration.zero);
|
durationState.value ?? Duration.zero,
|
||||||
|
);
|
||||||
if (index < availableDurations.length - 1) {
|
if (index < availableDurations.length - 1) {
|
||||||
scrollController.animateToItem(
|
scrollController.animateToItem(
|
||||||
index + 1,
|
index + 1,
|
||||||
|
|
@ -327,10 +315,7 @@ class SleepTimerWheel extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class DurationLine extends StatelessWidget {
|
class DurationLine extends StatelessWidget {
|
||||||
const DurationLine({
|
const DurationLine({super.key, required this.duration});
|
||||||
super.key,
|
|
||||||
required this.duration,
|
|
||||||
});
|
|
||||||
|
|
||||||
final Duration duration;
|
final Duration duration;
|
||||||
|
|
||||||
|
|
@ -345,8 +330,8 @@ class DurationLine extends StatelessWidget {
|
||||||
width: duration.inMinutes % 5 == 0
|
width: duration.inMinutes % 5 == 0
|
||||||
? 3
|
? 3
|
||||||
: duration.inMinutes % 2.5 == 0
|
: duration.inMinutes % 2.5 == 0
|
||||||
? 2
|
? 2
|
||||||
: 0.5,
|
: 0.5,
|
||||||
color: Theme.of(context).colorScheme.onSurface,
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -20,16 +20,12 @@ import 'package:vaani/shared/extensions/obfuscation.dart' show ObfuscateSet;
|
||||||
import 'package:vaani/shared/widgets/add_new_server.dart' show AddNewServer;
|
import 'package:vaani/shared/widgets/add_new_server.dart' show AddNewServer;
|
||||||
|
|
||||||
class ServerManagerPage extends HookConsumerWidget {
|
class ServerManagerPage extends HookConsumerWidget {
|
||||||
const ServerManagerPage({
|
const ServerManagerPage({super.key});
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(title: const Text('Manage Accounts')),
|
||||||
title: const Text('Manage Accounts'),
|
|
||||||
),
|
|
||||||
body: Center(
|
body: Center(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
|
@ -41,9 +37,7 @@ class ServerManagerPage extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class ServerManagerBody extends HookConsumerWidget {
|
class ServerManagerBody extends HookConsumerWidget {
|
||||||
const ServerManagerBody({
|
const ServerManagerBody({super.key});
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
|
@ -61,9 +55,7 @@ class ServerManagerBody extends HookConsumerWidget {
|
||||||
// crossAxisAlignment: CrossAxisAlignment.center,
|
// crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
const Text(
|
const Text('Registered Servers'),
|
||||||
'Registered Servers',
|
|
||||||
),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
itemCount: registeredServers.length,
|
itemCount: registeredServers.length,
|
||||||
|
|
@ -76,21 +68,17 @@ class ServerManagerBody extends HookConsumerWidget {
|
||||||
'Users: ${availableUsers.where((element) => element.server == registeredServer).length}',
|
'Users: ${availableUsers.where((element) => element.server == registeredServer).length}',
|
||||||
),
|
),
|
||||||
// children are list of users of this server
|
// children are list of users of this server
|
||||||
children: availableUsers
|
children:
|
||||||
.where(
|
availableUsers
|
||||||
(element) => element.server == registeredServer,
|
.where((element) => element.server == registeredServer)
|
||||||
)
|
.map<Widget>((e) => AvailableUserTile(user: e))
|
||||||
.map<Widget>(
|
.nonNulls
|
||||||
(e) => AvailableUserTile(user: e),
|
.toList()
|
||||||
)
|
// add buttons of delete server and add user to server at the end
|
||||||
.nonNulls
|
..addAll([
|
||||||
.toList()
|
AddUserTile(server: registeredServer),
|
||||||
|
DeleteServerTile(server: registeredServer),
|
||||||
// add buttons of delete server and add user to server at the end
|
]),
|
||||||
..addAll([
|
|
||||||
AddUserTile(server: registeredServer),
|
|
||||||
DeleteServerTile(server: registeredServer),
|
|
||||||
]),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
@ -111,28 +99,24 @@ class ServerManagerBody extends HookConsumerWidget {
|
||||||
final newServer = model.AudiobookShelfServer(
|
final newServer = model.AudiobookShelfServer(
|
||||||
serverUrl: makeBaseUrl(serverURIController.text),
|
serverUrl: makeBaseUrl(serverURIController.text),
|
||||||
);
|
);
|
||||||
ref.read(audiobookShelfServerProvider.notifier).addServer(
|
ref
|
||||||
newServer,
|
.read(audiobookShelfServerProvider.notifier)
|
||||||
);
|
.addServer(newServer);
|
||||||
ref.read(apiSettingsProvider.notifier).updateState(
|
ref
|
||||||
apiSettings.copyWith(
|
.read(apiSettingsProvider.notifier)
|
||||||
activeServer: newServer,
|
.updateState(
|
||||||
),
|
apiSettings.copyWith(activeServer: newServer),
|
||||||
);
|
);
|
||||||
serverURIController.clear();
|
serverURIController.clear();
|
||||||
} on ServerAlreadyExistsException catch (e) {
|
} on ServerAlreadyExistsException catch (e) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(e.toString()),
|
).showSnackBar(SnackBar(content: Text(e.toString())));
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(
|
||||||
const SnackBar(
|
context,
|
||||||
content: Text('Invalid URL'),
|
).showSnackBar(const SnackBar(content: Text('Invalid URL')));
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
@ -144,10 +128,7 @@ class ServerManagerBody extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class DeleteServerTile extends HookConsumerWidget {
|
class DeleteServerTile extends HookConsumerWidget {
|
||||||
const DeleteServerTile({
|
const DeleteServerTile({super.key, required this.server});
|
||||||
super.key,
|
|
||||||
required this.server,
|
|
||||||
});
|
|
||||||
|
|
||||||
final model.AudiobookShelfServer server;
|
final model.AudiobookShelfServer server;
|
||||||
|
|
||||||
|
|
@ -167,9 +148,7 @@ class DeleteServerTile extends HookConsumerWidget {
|
||||||
child: Text.rich(
|
child: Text.rich(
|
||||||
TextSpan(
|
TextSpan(
|
||||||
children: [
|
children: [
|
||||||
const TextSpan(
|
const TextSpan(text: 'This will remove the server '),
|
||||||
text: 'This will remove the server ',
|
|
||||||
),
|
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: server.serverUrl.host,
|
text: server.serverUrl.host,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
|
@ -194,13 +173,8 @@ class DeleteServerTile extends HookConsumerWidget {
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
ref
|
ref
|
||||||
.read(
|
.read(audiobookShelfServerProvider.notifier)
|
||||||
audiobookShelfServerProvider.notifier,
|
.removeServer(server, removeUsers: true);
|
||||||
)
|
|
||||||
.removeServer(
|
|
||||||
server,
|
|
||||||
removeUsers: true,
|
|
||||||
);
|
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
child: const Text('Delete'),
|
child: const Text('Delete'),
|
||||||
|
|
@ -215,10 +189,7 @@ class DeleteServerTile extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class AddUserTile extends HookConsumerWidget {
|
class AddUserTile extends HookConsumerWidget {
|
||||||
const AddUserTile({
|
const AddUserTile({super.key, required this.server});
|
||||||
super.key,
|
|
||||||
required this.server,
|
|
||||||
});
|
|
||||||
|
|
||||||
final model.AudiobookShelfServer server;
|
final model.AudiobookShelfServer server;
|
||||||
|
|
||||||
|
|
@ -252,10 +223,12 @@ class AddUserTile extends HookConsumerWidget {
|
||||||
label: 'Switch',
|
label: 'Switch',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// Switch to the new user
|
// Switch to the new user
|
||||||
ref.read(apiSettingsProvider.notifier).updateState(
|
ref
|
||||||
ref.read(apiSettingsProvider).copyWith(
|
.read(apiSettingsProvider.notifier)
|
||||||
activeUser: user,
|
.updateState(
|
||||||
),
|
ref
|
||||||
|
.read(apiSettingsProvider)
|
||||||
|
.copyWith(activeUser: user),
|
||||||
);
|
);
|
||||||
context.goNamed(Routes.home.name);
|
context.goNamed(Routes.home.name);
|
||||||
},
|
},
|
||||||
|
|
@ -283,10 +256,7 @@ class AddUserTile extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class AvailableUserTile extends HookConsumerWidget {
|
class AvailableUserTile extends HookConsumerWidget {
|
||||||
const AvailableUserTile({
|
const AvailableUserTile({super.key, required this.user});
|
||||||
super.key,
|
|
||||||
required this.user,
|
|
||||||
});
|
|
||||||
|
|
||||||
final model.AuthenticatedUser user;
|
final model.AuthenticatedUser user;
|
||||||
|
|
||||||
|
|
@ -303,18 +273,14 @@ class AvailableUserTile extends HookConsumerWidget {
|
||||||
onTap: apiSettings.activeUser == user
|
onTap: apiSettings.activeUser == user
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
ref.read(apiSettingsProvider.notifier).updateState(
|
ref
|
||||||
apiSettings.copyWith(
|
.read(apiSettingsProvider.notifier)
|
||||||
activeUser: user,
|
.updateState(apiSettings.copyWith(activeUser: user));
|
||||||
),
|
|
||||||
);
|
|
||||||
// pop all routes and go to the home page
|
// pop all routes and go to the home page
|
||||||
// while (context.canPop()) {
|
// while (context.canPop()) {
|
||||||
// context.pop();
|
// context.pop();
|
||||||
// }
|
// }
|
||||||
context.goNamed(
|
context.goNamed(Routes.home.name);
|
||||||
Routes.home.name,
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
trailing: IconButton(
|
trailing: IconButton(
|
||||||
icon: const Icon(Icons.delete),
|
icon: const Icon(Icons.delete),
|
||||||
|
|
@ -337,9 +303,7 @@ class AvailableUserTile extends HookConsumerWidget {
|
||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const TextSpan(
|
const TextSpan(text: ' from this app.'),
|
||||||
text: ' from this app.',
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -353,9 +317,7 @@ class AvailableUserTile extends HookConsumerWidget {
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
ref
|
ref
|
||||||
.read(
|
.read(authenticatedUsersProvider.notifier)
|
||||||
authenticatedUsersProvider.notifier,
|
|
||||||
)
|
|
||||||
.removeUser(user);
|
.removeUser(user);
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,7 @@ import 'package:flutter/foundation.dart';
|
||||||
import 'package:vaani/main.dart' show appLogger;
|
import 'package:vaani/main.dart' show appLogger;
|
||||||
|
|
||||||
class LibrarySwitchChip extends HookConsumerWidget {
|
class LibrarySwitchChip extends HookConsumerWidget {
|
||||||
const LibrarySwitchChip({
|
const LibrarySwitchChip({super.key, required this.libraries});
|
||||||
super.key,
|
|
||||||
required this.libraries,
|
|
||||||
});
|
|
||||||
final List<Library> libraries;
|
final List<Library> libraries;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -26,30 +23,22 @@ class LibrarySwitchChip extends HookConsumerWidget {
|
||||||
AbsIcons.getIconByName(
|
AbsIcons.getIconByName(
|
||||||
apiSettings.activeLibraryId != null
|
apiSettings.activeLibraryId != null
|
||||||
? libraries
|
? libraries
|
||||||
.firstWhere(
|
.firstWhere((lib) => lib.id == apiSettings.activeLibraryId)
|
||||||
(lib) => lib.id == apiSettings.activeLibraryId,
|
.icon
|
||||||
)
|
|
||||||
.icon
|
|
||||||
: libraries.first.icon,
|
: libraries.first.icon,
|
||||||
),
|
),
|
||||||
), // Replace with your icon
|
), // Replace with your icon
|
||||||
label: const Text('Change Library'),
|
label: const Text('Change Library'),
|
||||||
// Enable only if libraries are loaded and not empty
|
// Enable only if libraries are loaded and not empty
|
||||||
onPressed: libraries.isNotEmpty
|
onPressed: libraries.isNotEmpty
|
||||||
? () => showLibrarySwitcher(
|
? () => showLibrarySwitcher(context, ref)
|
||||||
context,
|
|
||||||
ref,
|
|
||||||
)
|
|
||||||
: null, // Disable if no libraries
|
: null, // Disable if no libraries
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Helper Function to Show the Switcher ---
|
// --- Helper Function to Show the Switcher ---
|
||||||
void showLibrarySwitcher(
|
void showLibrarySwitcher(BuildContext context, WidgetRef ref) {
|
||||||
BuildContext context,
|
|
||||||
WidgetRef ref,
|
|
||||||
) {
|
|
||||||
final content = _LibrarySelectionContent();
|
final content = _LibrarySelectionContent();
|
||||||
|
|
||||||
// --- Platform-Specific UI ---
|
// --- Platform-Specific UI ---
|
||||||
|
|
@ -209,7 +198,9 @@ class _LibrarySelectionContent extends ConsumerWidget {
|
||||||
// Get current settings state
|
// Get current settings state
|
||||||
final currentSettings = ref.read(apiSettingsProvider);
|
final currentSettings = ref.read(apiSettingsProvider);
|
||||||
// Update the active library ID
|
// Update the active library ID
|
||||||
ref.read(apiSettingsProvider.notifier).updateState(
|
ref
|
||||||
|
.read(apiSettingsProvider.notifier)
|
||||||
|
.updateState(
|
||||||
currentSettings.copyWith(activeLibraryId: library.id),
|
currentSettings.copyWith(activeLibraryId: library.id),
|
||||||
);
|
);
|
||||||
// Close the dialog/bottom sheet
|
// Close the dialog/bottom sheet
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,7 @@ import 'package:vaani/shared/widgets/not_implemented.dart';
|
||||||
import 'package:vaani/shared/widgets/vaani_logo.dart';
|
import 'package:vaani/shared/widgets/vaani_logo.dart';
|
||||||
|
|
||||||
class YouPage extends HookConsumerWidget {
|
class YouPage extends HookConsumerWidget {
|
||||||
const YouPage({
|
const YouPage({super.key});
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
|
@ -88,8 +86,9 @@ class YouPage extends HookConsumerWidget {
|
||||||
// Maybe show error details or allow retry
|
// Maybe show error details or allow retry
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content:
|
content: Text(
|
||||||
Text('Failed to load libraries: $error'),
|
'Failed to load libraries: $error',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
@ -159,9 +158,7 @@ class YouPage extends HookConsumerWidget {
|
||||||
Theme.of(context).colorScheme.primary,
|
Theme.of(context).colorScheme.primary,
|
||||||
BlendMode.srcIn,
|
BlendMode.srcIn,
|
||||||
),
|
),
|
||||||
child: const VaaniLogo(
|
child: const VaaniLogo(size: 48),
|
||||||
size: 48,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -176,9 +173,7 @@ class YouPage extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserBar extends HookConsumerWidget {
|
class UserBar extends HookConsumerWidget {
|
||||||
const UserBar({
|
const UserBar({super.key});
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
|
@ -217,8 +212,9 @@ class UserBar extends HookConsumerWidget {
|
||||||
Text(
|
Text(
|
||||||
api.baseUrl.toString(),
|
api.baseUrl.toString(),
|
||||||
style: textTheme.bodyMedium?.copyWith(
|
style: textTheme.bodyMedium?.copyWith(
|
||||||
color:
|
color: themeData.colorScheme.onSurface.withValues(
|
||||||
themeData.colorScheme.onSurface.withValues(alpha: 0.6),
|
alpha: 0.6,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,7 @@ import 'package:flutter/material.dart';
|
||||||
class InactiveFocusScopeObserver extends StatefulWidget {
|
class InactiveFocusScopeObserver extends StatefulWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
const InactiveFocusScopeObserver({
|
const InactiveFocusScopeObserver({super.key, required this.child});
|
||||||
super.key,
|
|
||||||
required this.child,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<InactiveFocusScopeObserver> createState() =>
|
State<InactiveFocusScopeObserver> createState() =>
|
||||||
|
|
@ -39,10 +36,8 @@ class _InactiveFocusScopeObserverState
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => FocusScope(
|
Widget build(BuildContext context) =>
|
||||||
node: _focusScope,
|
FocusScope(node: _focusScope, child: widget.child);
|
||||||
child: widget.child,
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
|
|
||||||
|
|
@ -33,11 +33,7 @@ void main() async {
|
||||||
await configurePlayer();
|
await configurePlayer();
|
||||||
|
|
||||||
// run the app
|
// run the app
|
||||||
runApp(
|
runApp(const ProviderScope(child: _EagerInitialization(child: MyApp())));
|
||||||
const ProviderScope(
|
|
||||||
child: _EagerInitialization(child: MyApp()),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var routerConfig = const MyAppRouter().config;
|
var routerConfig = const MyAppRouter().config;
|
||||||
|
|
@ -65,20 +61,17 @@ class MyApp extends ConsumerWidget {
|
||||||
themeSettings.highContrast || MediaQuery.of(context).highContrast;
|
themeSettings.highContrast || MediaQuery.of(context).highContrast;
|
||||||
|
|
||||||
if (shouldUseHighContrast) {
|
if (shouldUseHighContrast) {
|
||||||
lightColorScheme = lightColorScheme.copyWith(
|
lightColorScheme = lightColorScheme.copyWith(surface: Colors.white);
|
||||||
surface: Colors.white,
|
darkColorScheme = darkColorScheme.copyWith(surface: Colors.black);
|
||||||
);
|
|
||||||
darkColorScheme = darkColorScheme.copyWith(
|
|
||||||
surface: Colors.black,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (themeSettings.useMaterialThemeFromSystem) {
|
if (themeSettings.useMaterialThemeFromSystem) {
|
||||||
var themes =
|
var themes = ref.watch(
|
||||||
ref.watch(systemThemeProvider(highContrast: shouldUseHighContrast));
|
systemThemeProvider(highContrast: shouldUseHighContrast),
|
||||||
if (themes.valueOrNull != null) {
|
);
|
||||||
lightColorScheme = themes.valueOrNull!.$1;
|
if (themes.value != null) {
|
||||||
darkColorScheme = themes.valueOrNull!.$2;
|
lightColorScheme = themes.value!.$1;
|
||||||
|
darkColorScheme = themes.value!.$2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,9 +93,9 @@ class MyApp extends ConsumerWidget {
|
||||||
brightness: Brightness.dark,
|
brightness: Brightness.dark,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (themeLight.valueOrNull != null && themeDark.valueOrNull != null) {
|
if (themeLight.value != null && themeDark.value != null) {
|
||||||
lightColorScheme = themeLight.valueOrNull!;
|
lightColorScheme = themeLight.value!;
|
||||||
darkColorScheme = themeDark.valueOrNull!;
|
darkColorScheme = themeDark.value!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,9 @@ class HomePage extends HookConsumerWidget {
|
||||||
// try again button
|
// try again button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
ref.read(apiSettingsProvider.notifier).updateState(
|
ref
|
||||||
|
.read(apiSettingsProvider.notifier)
|
||||||
|
.updateState(
|
||||||
apiSettings.copyWith(activeLibraryId: null),
|
apiSettings.copyWith(activeLibraryId: null),
|
||||||
);
|
);
|
||||||
ref.invalidate(personalizedViewProvider);
|
ref.invalidate(personalizedViewProvider);
|
||||||
|
|
@ -66,24 +68,25 @@ class HomePage extends HookConsumerWidget {
|
||||||
final shelvesToDisplay = data
|
final shelvesToDisplay = data
|
||||||
// .where((element) => !element.id.contains('discover'))
|
// .where((element) => !element.id.contains('discover'))
|
||||||
.map((shelf) {
|
.map((shelf) {
|
||||||
appLogger.fine('building shelf ${shelf.label}');
|
appLogger.fine('building shelf ${shelf.label}');
|
||||||
// check if showPlayButton is enabled for the shelf
|
// check if showPlayButton is enabled for the shelf
|
||||||
// using the id of the shelf
|
// using the id of the shelf
|
||||||
final showPlayButton = switch (shelf.id) {
|
final showPlayButton = switch (shelf.id) {
|
||||||
'continue-listening' =>
|
'continue-listening' =>
|
||||||
homePageSettings.showPlayButtonOnContinueListeningShelf,
|
homePageSettings.showPlayButtonOnContinueListeningShelf,
|
||||||
'continue-series' =>
|
'continue-series' =>
|
||||||
homePageSettings.showPlayButtonOnContinueSeriesShelf,
|
homePageSettings.showPlayButtonOnContinueSeriesShelf,
|
||||||
'listen-again' =>
|
'listen-again' =>
|
||||||
homePageSettings.showPlayButtonOnListenAgainShelf,
|
homePageSettings.showPlayButtonOnListenAgainShelf,
|
||||||
_ => homePageSettings.showPlayButtonOnAllRemainingShelves,
|
_ => homePageSettings.showPlayButtonOnAllRemainingShelves,
|
||||||
};
|
};
|
||||||
return HomeShelf(
|
return HomeShelf(
|
||||||
title: shelf.label,
|
title: shelf.label,
|
||||||
shelf: shelf,
|
shelf: shelf,
|
||||||
showPlayButton: showPlayButton,
|
showPlayButton: showPlayButton,
|
||||||
);
|
);
|
||||||
}).toList();
|
})
|
||||||
|
.toList();
|
||||||
return RefreshIndicator(
|
return RefreshIndicator(
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
return ref.refresh(personalizedViewProvider);
|
return ref.refresh(personalizedViewProvider);
|
||||||
|
|
@ -132,10 +135,6 @@ class HomePageSkeleton extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return const Scaffold(
|
return const Scaffold(body: Center(child: CircularProgressIndicator()));
|
||||||
body: Center(
|
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,9 @@ class LibraryPage extends HookConsumerWidget {
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
// set the library id as the active library
|
// set the library id as the active library
|
||||||
if (libraryId != null) {
|
if (libraryId != null) {
|
||||||
ref.read(apiSettingsProvider.notifier).updateState(
|
ref
|
||||||
|
.read(apiSettingsProvider.notifier)
|
||||||
|
.updateState(
|
||||||
ref.watch(apiSettingsProvider).copyWith(activeLibraryId: libraryId),
|
ref.watch(apiSettingsProvider).copyWith(activeLibraryId: libraryId),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -48,12 +50,10 @@ class LibraryPage extends HookConsumerWidget {
|
||||||
final shelvesToDisplay = data
|
final shelvesToDisplay = data
|
||||||
// .where((element) => !element.id.contains('discover'))
|
// .where((element) => !element.id.contains('discover'))
|
||||||
.map((shelf) {
|
.map((shelf) {
|
||||||
appLogger.fine('building shelf ${shelf.label}');
|
appLogger.fine('building shelf ${shelf.label}');
|
||||||
return HomeShelf(
|
return HomeShelf(title: shelf.label, shelf: shelf);
|
||||||
title: shelf.label,
|
})
|
||||||
shelf: shelf,
|
.toList();
|
||||||
);
|
|
||||||
}).toList();
|
|
||||||
return RefreshIndicator(
|
return RefreshIndicator(
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
return ref.refresh(personalizedViewProvider);
|
return ref.refresh(personalizedViewProvider);
|
||||||
|
|
@ -85,10 +85,6 @@ class LibraryPageSkeleton extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return const Scaffold(
|
return const Scaffold(body: Center(child: CircularProgressIndicator()));
|
||||||
body: Center(
|
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,8 @@
|
||||||
part of 'router.dart';
|
part of 'router.dart';
|
||||||
|
|
||||||
class Routes {
|
class Routes {
|
||||||
static const home = _SimpleRoute(
|
static const home = _SimpleRoute(pathName: '', name: 'home');
|
||||||
pathName: '',
|
static const onboarding = _SimpleRoute(pathName: 'login', name: 'onboarding');
|
||||||
name: 'home',
|
|
||||||
);
|
|
||||||
static const onboarding = _SimpleRoute(
|
|
||||||
pathName: 'login',
|
|
||||||
name: 'onboarding',
|
|
||||||
);
|
|
||||||
static const library = _SimpleRoute(
|
static const library = _SimpleRoute(
|
||||||
pathName: 'library',
|
pathName: 'library',
|
||||||
pathParamName: 'libraryId',
|
pathParamName: 'libraryId',
|
||||||
|
|
@ -23,10 +17,7 @@ class Routes {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Local settings
|
// Local settings
|
||||||
static const settings = _SimpleRoute(
|
static const settings = _SimpleRoute(pathName: 'config', name: 'settings');
|
||||||
pathName: 'config',
|
|
||||||
name: 'settings',
|
|
||||||
);
|
|
||||||
static const themeSettings = _SimpleRoute(
|
static const themeSettings = _SimpleRoute(
|
||||||
pathName: 'theme',
|
pathName: 'theme',
|
||||||
name: 'themeSettings',
|
name: 'themeSettings',
|
||||||
|
|
@ -64,10 +55,7 @@ class Routes {
|
||||||
name: 'search',
|
name: 'search',
|
||||||
// parentRoute: library,
|
// parentRoute: library,
|
||||||
);
|
);
|
||||||
static const explore = _SimpleRoute(
|
static const explore = _SimpleRoute(pathName: 'explore', name: 'explore');
|
||||||
pathName: 'explore',
|
|
||||||
name: 'explore',
|
|
||||||
);
|
|
||||||
|
|
||||||
// downloads
|
// downloads
|
||||||
static const downloads = _SimpleRoute(
|
static const downloads = _SimpleRoute(
|
||||||
|
|
@ -83,10 +71,7 @@ class Routes {
|
||||||
);
|
);
|
||||||
|
|
||||||
// you page for the user
|
// you page for the user
|
||||||
static const you = _SimpleRoute(
|
static const you = _SimpleRoute(pathName: 'you', name: 'you');
|
||||||
pathName: 'you',
|
|
||||||
name: 'you',
|
|
||||||
);
|
|
||||||
|
|
||||||
// user management
|
// user management
|
||||||
static const userManagement = _SimpleRoute(
|
static const userManagement = _SimpleRoute(
|
||||||
|
|
@ -102,10 +87,7 @@ class Routes {
|
||||||
);
|
);
|
||||||
|
|
||||||
// logs page
|
// logs page
|
||||||
static const logs = _SimpleRoute(
|
static const logs = _SimpleRoute(pathName: 'logs', name: 'logs');
|
||||||
pathName: 'logs',
|
|
||||||
name: 'logs',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// a class to store path
|
// a class to store path
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ part 'library_item_extras.freezed.dart';
|
||||||
/// [book] is the book that the item represents
|
/// [book] is the book that the item represents
|
||||||
/// [heroTagSuffix] is the suffix to use for the hero tag to avoid conflicts
|
/// [heroTagSuffix] is the suffix to use for the hero tag to avoid conflicts
|
||||||
@freezed
|
@freezed
|
||||||
class LibraryItemExtras with _$LibraryItemExtras {
|
sealed class LibraryItemExtras with _$LibraryItemExtras {
|
||||||
const factory LibraryItemExtras({
|
const factory LibraryItemExtras({
|
||||||
BookMinified? book,
|
BookMinified? book,
|
||||||
@Default('') String heroTagSuffix,
|
@Default('') String heroTagSuffix,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// coverage:ignore-file
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// coverage:ignore-file
|
||||||
// ignore_for_file: type=lint
|
// 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
|
// 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
|
||||||
|
|
||||||
|
|
@ -9,156 +9,260 @@ part of 'library_item_extras.dart';
|
||||||
// FreezedGenerator
|
// FreezedGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
|
// dart format off
|
||||||
T _$identity<T>(T value) => value;
|
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#adding-getters-and-methods-to-our-models');
|
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$LibraryItemExtras {
|
mixin _$LibraryItemExtras {
|
||||||
BookMinified? get book => throw _privateConstructorUsedError;
|
|
||||||
String get heroTagSuffix => throw _privateConstructorUsedError;
|
|
||||||
|
|
||||||
/// Create a copy of LibraryItemExtras
|
BookMinified? get book; String get heroTagSuffix;
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// Create a copy of LibraryItemExtras
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
$LibraryItemExtrasCopyWith<LibraryItemExtras> get copyWith =>
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
throw _privateConstructorUsedError;
|
@pragma('vm:prefer-inline')
|
||||||
|
$LibraryItemExtrasCopyWith<LibraryItemExtras> get copyWith => _$LibraryItemExtrasCopyWithImpl<LibraryItemExtras>(this as LibraryItemExtras, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is LibraryItemExtras&&(identical(other.book, book) || other.book == book)&&(identical(other.heroTagSuffix, heroTagSuffix) || other.heroTagSuffix == heroTagSuffix));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,book,heroTagSuffix);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LibraryItemExtras(book: $book, heroTagSuffix: $heroTagSuffix)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
abstract class $LibraryItemExtrasCopyWith<$Res> {
|
abstract mixin class $LibraryItemExtrasCopyWith<$Res> {
|
||||||
factory $LibraryItemExtrasCopyWith(
|
factory $LibraryItemExtrasCopyWith(LibraryItemExtras value, $Res Function(LibraryItemExtras) _then) = _$LibraryItemExtrasCopyWithImpl;
|
||||||
LibraryItemExtras value, $Res Function(LibraryItemExtras) then) =
|
@useResult
|
||||||
_$LibraryItemExtrasCopyWithImpl<$Res, LibraryItemExtras>;
|
$Res call({
|
||||||
@useResult
|
BookMinified? book, String heroTagSuffix
|
||||||
$Res call({BookMinified? book, String heroTagSuffix});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
class _$LibraryItemExtrasCopyWithImpl<$Res, $Val extends LibraryItemExtras>
|
class _$LibraryItemExtrasCopyWithImpl<$Res>
|
||||||
implements $LibraryItemExtrasCopyWith<$Res> {
|
implements $LibraryItemExtrasCopyWith<$Res> {
|
||||||
_$LibraryItemExtrasCopyWithImpl(this._value, this._then);
|
_$LibraryItemExtrasCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
// ignore: unused_field
|
final LibraryItemExtras _self;
|
||||||
final $Val _value;
|
final $Res Function(LibraryItemExtras) _then;
|
||||||
// ignore: unused_field
|
|
||||||
final $Res Function($Val) _then;
|
|
||||||
|
|
||||||
/// Create a copy of LibraryItemExtras
|
/// Create a copy of LibraryItemExtras
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline') @override $Res call({Object? book = freezed,Object? heroTagSuffix = null,}) {
|
||||||
@override
|
return _then(_self.copyWith(
|
||||||
$Res call({
|
book: freezed == book ? _self.book : book // ignore: cast_nullable_to_non_nullable
|
||||||
Object? book = freezed,
|
as BookMinified?,heroTagSuffix: null == heroTagSuffix ? _self.heroTagSuffix : heroTagSuffix // ignore: cast_nullable_to_non_nullable
|
||||||
Object? heroTagSuffix = null,
|
as String,
|
||||||
}) {
|
));
|
||||||
return _then(_value.copyWith(
|
|
||||||
book: freezed == book
|
|
||||||
? _value.book
|
|
||||||
: book // ignore: cast_nullable_to_non_nullable
|
|
||||||
as BookMinified?,
|
|
||||||
heroTagSuffix: null == heroTagSuffix
|
|
||||||
? _value.heroTagSuffix
|
|
||||||
: heroTagSuffix // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
|
||||||
) as $Val);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
abstract class _$$LibraryItemExtrasImplCopyWith<$Res>
|
|
||||||
implements $LibraryItemExtrasCopyWith<$Res> {
|
|
||||||
factory _$$LibraryItemExtrasImplCopyWith(_$LibraryItemExtrasImpl value,
|
|
||||||
$Res Function(_$LibraryItemExtrasImpl) then) =
|
|
||||||
__$$LibraryItemExtrasImplCopyWithImpl<$Res>;
|
|
||||||
@override
|
|
||||||
@useResult
|
|
||||||
$Res call({BookMinified? book, String heroTagSuffix});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
class __$$LibraryItemExtrasImplCopyWithImpl<$Res>
|
|
||||||
extends _$LibraryItemExtrasCopyWithImpl<$Res, _$LibraryItemExtrasImpl>
|
|
||||||
implements _$$LibraryItemExtrasImplCopyWith<$Res> {
|
|
||||||
__$$LibraryItemExtrasImplCopyWithImpl(_$LibraryItemExtrasImpl _value,
|
|
||||||
$Res Function(_$LibraryItemExtrasImpl) _then)
|
|
||||||
: super(_value, _then);
|
|
||||||
|
|
||||||
/// Create a copy of LibraryItemExtras
|
/// Adds pattern-matching-related methods to [LibraryItemExtras].
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
extension LibraryItemExtrasPatterns on LibraryItemExtras {
|
||||||
@pragma('vm:prefer-inline')
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
@override
|
///
|
||||||
$Res call({
|
/// It is equivalent to doing:
|
||||||
Object? book = freezed,
|
/// ```dart
|
||||||
Object? heroTagSuffix = null,
|
/// switch (sealedClass) {
|
||||||
}) {
|
/// case final Subclass value:
|
||||||
return _then(_$LibraryItemExtrasImpl(
|
/// return ...;
|
||||||
book: freezed == book
|
/// case _:
|
||||||
? _value.book
|
/// return orElse();
|
||||||
: book // ignore: cast_nullable_to_non_nullable
|
/// }
|
||||||
as BookMinified?,
|
/// ```
|
||||||
heroTagSuffix: null == heroTagSuffix
|
|
||||||
? _value.heroTagSuffix
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _LibraryItemExtras value)? $default,{required TResult orElse(),}){
|
||||||
: heroTagSuffix // ignore: cast_nullable_to_non_nullable
|
final _that = this;
|
||||||
as String,
|
switch (_that) {
|
||||||
));
|
case _LibraryItemExtras() when $default != null:
|
||||||
}
|
return $default(_that);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// Callbacks receives the raw object, upcasted.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case final Subclass2 value:
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _LibraryItemExtras value) $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LibraryItemExtras():
|
||||||
|
return $default(_that);}
|
||||||
|
}
|
||||||
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _LibraryItemExtras value)? $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LibraryItemExtras() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to an `orElse` callback.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( BookMinified? book, String heroTagSuffix)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LibraryItemExtras() when $default != null:
|
||||||
|
return $default(_that.book,_that.heroTagSuffix);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// As opposed to `map`, this offers destructuring.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case Subclass2(:final field2):
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( BookMinified? book, String heroTagSuffix) $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LibraryItemExtras():
|
||||||
|
return $default(_that.book,_that.heroTagSuffix);}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to returning `null`
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( BookMinified? book, String heroTagSuffix)? $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LibraryItemExtras() when $default != null:
|
||||||
|
return $default(_that.book,_that.heroTagSuffix);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
|
|
||||||
class _$LibraryItemExtrasImpl implements _LibraryItemExtras {
|
|
||||||
const _$LibraryItemExtrasImpl({this.book, this.heroTagSuffix = ''});
|
|
||||||
|
|
||||||
@override
|
class _LibraryItemExtras implements LibraryItemExtras {
|
||||||
final BookMinified? book;
|
const _LibraryItemExtras({this.book, this.heroTagSuffix = ''});
|
||||||
@override
|
|
||||||
@JsonKey()
|
|
||||||
final String heroTagSuffix;
|
|
||||||
|
|
||||||
@override
|
@override final BookMinified? book;
|
||||||
String toString() {
|
@override@JsonKey() final String heroTagSuffix;
|
||||||
return 'LibraryItemExtras(book: $book, heroTagSuffix: $heroTagSuffix)';
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
/// Create a copy of LibraryItemExtras
|
||||||
bool operator ==(Object other) {
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
return identical(this, other) ||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
(other.runtimeType == runtimeType &&
|
@pragma('vm:prefer-inline')
|
||||||
other is _$LibraryItemExtrasImpl &&
|
_$LibraryItemExtrasCopyWith<_LibraryItemExtras> get copyWith => __$LibraryItemExtrasCopyWithImpl<_LibraryItemExtras>(this, _$identity);
|
||||||
(identical(other.book, book) || other.book == book) &&
|
|
||||||
(identical(other.heroTagSuffix, heroTagSuffix) ||
|
|
||||||
other.heroTagSuffix == heroTagSuffix));
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode => Object.hash(runtimeType, book, heroTagSuffix);
|
|
||||||
|
|
||||||
/// Create a copy of LibraryItemExtras
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
@override
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
bool operator ==(Object other) {
|
||||||
@override
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _LibraryItemExtras&&(identical(other.book, book) || other.book == book)&&(identical(other.heroTagSuffix, heroTagSuffix) || other.heroTagSuffix == heroTagSuffix));
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
_$$LibraryItemExtrasImplCopyWith<_$LibraryItemExtrasImpl> get copyWith =>
|
|
||||||
__$$LibraryItemExtrasImplCopyWithImpl<_$LibraryItemExtrasImpl>(
|
|
||||||
this, _$identity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class _LibraryItemExtras implements LibraryItemExtras {
|
|
||||||
const factory _LibraryItemExtras(
|
|
||||||
{final BookMinified? book,
|
|
||||||
final String heroTagSuffix}) = _$LibraryItemExtrasImpl;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
BookMinified? get book;
|
int get hashCode => Object.hash(runtimeType,book,heroTagSuffix);
|
||||||
@override
|
|
||||||
String get heroTagSuffix;
|
|
||||||
|
|
||||||
/// Create a copy of LibraryItemExtras
|
@override
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
String toString() {
|
||||||
@override
|
return 'LibraryItemExtras(book: $book, heroTagSuffix: $heroTagSuffix)';
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
_$$LibraryItemExtrasImplCopyWith<_$LibraryItemExtrasImpl> get copyWith =>
|
|
||||||
throw _privateConstructorUsedError;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$LibraryItemExtrasCopyWith<$Res> implements $LibraryItemExtrasCopyWith<$Res> {
|
||||||
|
factory _$LibraryItemExtrasCopyWith(_LibraryItemExtras value, $Res Function(_LibraryItemExtras) _then) = __$LibraryItemExtrasCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
BookMinified? book, String heroTagSuffix
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$LibraryItemExtrasCopyWithImpl<$Res>
|
||||||
|
implements _$LibraryItemExtrasCopyWith<$Res> {
|
||||||
|
__$LibraryItemExtrasCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _LibraryItemExtras _self;
|
||||||
|
final $Res Function(_LibraryItemExtras) _then;
|
||||||
|
|
||||||
|
/// Create a copy of LibraryItemExtras
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? book = freezed,Object? heroTagSuffix = null,}) {
|
||||||
|
return _then(_LibraryItemExtras(
|
||||||
|
book: freezed == book ? _self.book : book // ignore: cast_nullable_to_non_nullable
|
||||||
|
as BookMinified?,heroTagSuffix: null == heroTagSuffix ? _self.heroTagSuffix : heroTagSuffix // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// dart format on
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,9 @@ import 'transitions/slide.dart';
|
||||||
|
|
||||||
part 'constants.dart';
|
part 'constants.dart';
|
||||||
|
|
||||||
final GlobalKey<NavigatorState> rootNavigatorKey =
|
final GlobalKey<NavigatorState> rootNavigatorKey = GlobalKey<NavigatorState>(
|
||||||
GlobalKey<NavigatorState>(debugLabel: 'root');
|
debugLabel: 'root',
|
||||||
|
);
|
||||||
final GlobalKey<NavigatorState> sectionHomeNavigatorKey =
|
final GlobalKey<NavigatorState> sectionHomeNavigatorKey =
|
||||||
GlobalKey<NavigatorState>(debugLabel: 'HomeNavigator');
|
GlobalKey<NavigatorState>(debugLabel: 'HomeNavigator');
|
||||||
|
|
||||||
|
|
@ -35,34 +36,35 @@ class MyAppRouter {
|
||||||
const MyAppRouter();
|
const MyAppRouter();
|
||||||
|
|
||||||
GoRouter get config => GoRouter(
|
GoRouter get config => GoRouter(
|
||||||
initialLocation: Routes.home.localPath,
|
initialLocation: Routes.home.localPath,
|
||||||
debugLogDiagnostics: true,
|
debugLogDiagnostics: true,
|
||||||
|
routes: [
|
||||||
|
// sign in page
|
||||||
|
GoRoute(
|
||||||
|
path: Routes.onboarding.localPath,
|
||||||
|
name: Routes.onboarding.name,
|
||||||
|
builder: (context, state) => const OnboardingSinglePage(),
|
||||||
routes: [
|
routes: [
|
||||||
// sign in page
|
// open id callback
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: Routes.onboarding.localPath,
|
path: Routes.openIDCallback.pathName,
|
||||||
name: Routes.onboarding.name,
|
name: Routes.openIDCallback.name,
|
||||||
builder: (context, state) => const OnboardingSinglePage(),
|
|
||||||
routes: [
|
|
||||||
// open id callback
|
|
||||||
GoRoute(
|
|
||||||
path: Routes.openIDCallback.pathName,
|
|
||||||
name: Routes.openIDCallback.name,
|
|
||||||
pageBuilder: handleCallback,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
// callback for open id
|
|
||||||
// need to duplicate because of https://github.com/flutter/flutter/issues/100624
|
|
||||||
GoRoute(
|
|
||||||
path: Routes.openIDCallback.localPath,
|
|
||||||
// name: Routes.openIDCallback.name,
|
|
||||||
// builder: handleCallback,
|
|
||||||
pageBuilder: handleCallback,
|
pageBuilder: handleCallback,
|
||||||
),
|
),
|
||||||
// The main app shell
|
],
|
||||||
StatefulShellRoute.indexedStack(
|
),
|
||||||
builder: (
|
// callback for open id
|
||||||
|
// need to duplicate because of https://github.com/flutter/flutter/issues/100624
|
||||||
|
GoRoute(
|
||||||
|
path: Routes.openIDCallback.localPath,
|
||||||
|
// name: Routes.openIDCallback.name,
|
||||||
|
// builder: handleCallback,
|
||||||
|
pageBuilder: handleCallback,
|
||||||
|
),
|
||||||
|
// The main app shell
|
||||||
|
StatefulShellRoute.indexedStack(
|
||||||
|
builder:
|
||||||
|
(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
GoRouterState state,
|
GoRouterState state,
|
||||||
StatefulNavigationShell navigationShell,
|
StatefulNavigationShell navigationShell,
|
||||||
|
|
@ -73,188 +75,187 @@ class MyAppRouter {
|
||||||
// branches in a stateful way.
|
// branches in a stateful way.
|
||||||
return ScaffoldWithNavBar(navigationShell: navigationShell);
|
return ScaffoldWithNavBar(navigationShell: navigationShell);
|
||||||
},
|
},
|
||||||
branches: <StatefulShellBranch>[
|
branches: <StatefulShellBranch>[
|
||||||
// The route branch for the first tab of the bottom navigation bar.
|
// The route branch for the first tab of the bottom navigation bar.
|
||||||
StatefulShellBranch(
|
StatefulShellBranch(
|
||||||
navigatorKey: sectionHomeNavigatorKey,
|
navigatorKey: sectionHomeNavigatorKey,
|
||||||
routes: <RouteBase>[
|
routes: <RouteBase>[
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: Routes.home.localPath,
|
path: Routes.home.localPath,
|
||||||
name: Routes.home.name,
|
name: Routes.home.name,
|
||||||
// builder: (context, state) => const HomePage(),
|
// builder: (context, state) => const HomePage(),
|
||||||
pageBuilder: defaultPageBuilder(const HomePage()),
|
pageBuilder: defaultPageBuilder(const HomePage()),
|
||||||
),
|
|
||||||
GoRoute(
|
|
||||||
path: Routes.libraryItem.localPath,
|
|
||||||
name: Routes.libraryItem.name,
|
|
||||||
// builder: (context, state) {
|
|
||||||
// final itemId = state
|
|
||||||
// .pathParameters[Routes.libraryItem.pathParamName]!;
|
|
||||||
// return LibraryItemPage(
|
|
||||||
// itemId: itemId, extra: state.extra);
|
|
||||||
// },
|
|
||||||
pageBuilder: (context, state) {
|
|
||||||
final itemId = state
|
|
||||||
.pathParameters[Routes.libraryItem.pathParamName]!;
|
|
||||||
final child =
|
|
||||||
LibraryItemPage(itemId: itemId, extra: state.extra);
|
|
||||||
return buildPageWithDefaultTransition(
|
|
||||||
context: context,
|
|
||||||
state: state,
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
// downloads page
|
|
||||||
GoRoute(
|
|
||||||
path: Routes.downloads.localPath,
|
|
||||||
name: Routes.downloads.name,
|
|
||||||
pageBuilder: defaultPageBuilder(const DownloadsPage()),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
// Library page
|
path: Routes.libraryItem.localPath,
|
||||||
StatefulShellBranch(
|
name: Routes.libraryItem.name,
|
||||||
routes: <RouteBase>[
|
// builder: (context, state) {
|
||||||
GoRoute(
|
// final itemId = state
|
||||||
path: Routes.libraryBrowser.localPath,
|
// .pathParameters[Routes.libraryItem.pathParamName]!;
|
||||||
name: Routes.libraryBrowser.name,
|
// return LibraryItemPage(
|
||||||
pageBuilder: defaultPageBuilder(const LibraryBrowserPage()),
|
// itemId: itemId, extra: state.extra);
|
||||||
),
|
// },
|
||||||
],
|
pageBuilder: (context, state) {
|
||||||
|
final itemId =
|
||||||
|
state.pathParameters[Routes.libraryItem.pathParamName]!;
|
||||||
|
final child = LibraryItemPage(
|
||||||
|
itemId: itemId,
|
||||||
|
extra: state.extra,
|
||||||
|
);
|
||||||
|
return buildPageWithDefaultTransition(
|
||||||
|
context: context,
|
||||||
|
state: state,
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
// search/explore page
|
// downloads page
|
||||||
StatefulShellBranch(
|
GoRoute(
|
||||||
routes: <RouteBase>[
|
path: Routes.downloads.localPath,
|
||||||
GoRoute(
|
name: Routes.downloads.name,
|
||||||
path: Routes.explore.localPath,
|
pageBuilder: defaultPageBuilder(const DownloadsPage()),
|
||||||
name: Routes.explore.name,
|
|
||||||
// builder: (context, state) => const ExplorePage(),
|
|
||||||
pageBuilder: defaultPageBuilder(const ExplorePage()),
|
|
||||||
),
|
|
||||||
// search page
|
|
||||||
GoRoute(
|
|
||||||
path: Routes.search.localPath,
|
|
||||||
name: Routes.search.name,
|
|
||||||
// builder: (context, state) {
|
|
||||||
// final libraryId = state
|
|
||||||
// .pathParameters[Routes.library.pathParamName]!;
|
|
||||||
// return LibrarySearchPage(
|
|
||||||
// libraryId: libraryId,
|
|
||||||
// extra: state.extra,
|
|
||||||
// );
|
|
||||||
// },
|
|
||||||
pageBuilder: (context, state) {
|
|
||||||
final queryParam = state.uri.queryParameters['q']!;
|
|
||||||
final category = state.uri.queryParameters['category'];
|
|
||||||
final child = SearchResultPage(
|
|
||||||
extra: state.extra,
|
|
||||||
query: queryParam,
|
|
||||||
category: category != null
|
|
||||||
? SearchResultCategory.values.firstWhere(
|
|
||||||
(e) => e.toString().split('.').last == category,
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
);
|
|
||||||
return buildPageWithDefaultTransition(
|
|
||||||
context: context,
|
|
||||||
state: state,
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
// you page
|
|
||||||
StatefulShellBranch(
|
|
||||||
routes: <RouteBase>[
|
|
||||||
GoRoute(
|
|
||||||
path: Routes.you.localPath,
|
|
||||||
name: Routes.you.name,
|
|
||||||
pageBuilder: defaultPageBuilder(const YouPage()),
|
|
||||||
),
|
|
||||||
GoRoute(
|
|
||||||
path: Routes.settings.localPath,
|
|
||||||
name: Routes.settings.name,
|
|
||||||
// builder: (context, state) => const AppSettingsPage(),
|
|
||||||
pageBuilder: defaultPageBuilder(const AppSettingsPage()),
|
|
||||||
routes: [
|
|
||||||
GoRoute(
|
|
||||||
path: Routes.themeSettings.pathName,
|
|
||||||
name: Routes.themeSettings.name,
|
|
||||||
pageBuilder: defaultPageBuilder(
|
|
||||||
const ThemeSettingsPage(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
GoRoute(
|
|
||||||
path: Routes.autoSleepTimerSettings.pathName,
|
|
||||||
name: Routes.autoSleepTimerSettings.name,
|
|
||||||
pageBuilder: defaultPageBuilder(
|
|
||||||
const AutoSleepTimerSettingsPage(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
GoRoute(
|
|
||||||
path: Routes.notificationSettings.pathName,
|
|
||||||
name: Routes.notificationSettings.name,
|
|
||||||
pageBuilder: defaultPageBuilder(
|
|
||||||
const NotificationSettingsPage(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
GoRoute(
|
|
||||||
path: Routes.playerSettings.pathName,
|
|
||||||
name: Routes.playerSettings.name,
|
|
||||||
pageBuilder:
|
|
||||||
defaultPageBuilder(const PlayerSettingsPage()),
|
|
||||||
),
|
|
||||||
GoRoute(
|
|
||||||
path: Routes.shakeDetectorSettings.pathName,
|
|
||||||
name: Routes.shakeDetectorSettings.name,
|
|
||||||
pageBuilder: defaultPageBuilder(
|
|
||||||
const ShakeDetectorSettingsPage(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
GoRoute(
|
|
||||||
path: Routes.homePageSettings.pathName,
|
|
||||||
name: Routes.homePageSettings.name,
|
|
||||||
pageBuilder: defaultPageBuilder(
|
|
||||||
const HomePageSettingsPage(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
GoRoute(
|
|
||||||
path: Routes.userManagement.localPath,
|
|
||||||
name: Routes.userManagement.name,
|
|
||||||
// builder: (context, state) => const UserManagementPage(),
|
|
||||||
pageBuilder: defaultPageBuilder(const ServerManagerPage()),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
// loggers page
|
// Library page
|
||||||
GoRoute(
|
StatefulShellBranch(
|
||||||
path: Routes.logs.localPath,
|
routes: <RouteBase>[
|
||||||
name: Routes.logs.name,
|
GoRoute(
|
||||||
// builder: (context, state) => const LogsPage(),
|
path: Routes.libraryBrowser.localPath,
|
||||||
pageBuilder: defaultPageBuilder(const LogsPage()),
|
name: Routes.libraryBrowser.name,
|
||||||
|
pageBuilder: defaultPageBuilder(const LibraryBrowserPage()),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
// search/explore page
|
||||||
|
StatefulShellBranch(
|
||||||
|
routes: <RouteBase>[
|
||||||
|
GoRoute(
|
||||||
|
path: Routes.explore.localPath,
|
||||||
|
name: Routes.explore.name,
|
||||||
|
// builder: (context, state) => const ExplorePage(),
|
||||||
|
pageBuilder: defaultPageBuilder(const ExplorePage()),
|
||||||
|
),
|
||||||
|
// search page
|
||||||
|
GoRoute(
|
||||||
|
path: Routes.search.localPath,
|
||||||
|
name: Routes.search.name,
|
||||||
|
// builder: (context, state) {
|
||||||
|
// final libraryId = state
|
||||||
|
// .pathParameters[Routes.library.pathParamName]!;
|
||||||
|
// return LibrarySearchPage(
|
||||||
|
// libraryId: libraryId,
|
||||||
|
// extra: state.extra,
|
||||||
|
// );
|
||||||
|
// },
|
||||||
|
pageBuilder: (context, state) {
|
||||||
|
final queryParam = state.uri.queryParameters['q']!;
|
||||||
|
final category = state.uri.queryParameters['category'];
|
||||||
|
final child = SearchResultPage(
|
||||||
|
extra: state.extra,
|
||||||
|
query: queryParam,
|
||||||
|
category: category != null
|
||||||
|
? SearchResultCategory.values.firstWhere(
|
||||||
|
(e) => e.toString().split('.').last == category,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
);
|
||||||
|
return buildPageWithDefaultTransition(
|
||||||
|
context: context,
|
||||||
|
state: state,
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
// you page
|
||||||
|
StatefulShellBranch(
|
||||||
|
routes: <RouteBase>[
|
||||||
|
GoRoute(
|
||||||
|
path: Routes.you.localPath,
|
||||||
|
name: Routes.you.name,
|
||||||
|
pageBuilder: defaultPageBuilder(const YouPage()),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: Routes.settings.localPath,
|
||||||
|
name: Routes.settings.name,
|
||||||
|
// builder: (context, state) => const AppSettingsPage(),
|
||||||
|
pageBuilder: defaultPageBuilder(const AppSettingsPage()),
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: Routes.themeSettings.pathName,
|
||||||
|
name: Routes.themeSettings.name,
|
||||||
|
pageBuilder: defaultPageBuilder(const ThemeSettingsPage()),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: Routes.autoSleepTimerSettings.pathName,
|
||||||
|
name: Routes.autoSleepTimerSettings.name,
|
||||||
|
pageBuilder: defaultPageBuilder(
|
||||||
|
const AutoSleepTimerSettingsPage(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: Routes.notificationSettings.pathName,
|
||||||
|
name: Routes.notificationSettings.name,
|
||||||
|
pageBuilder: defaultPageBuilder(
|
||||||
|
const NotificationSettingsPage(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: Routes.playerSettings.pathName,
|
||||||
|
name: Routes.playerSettings.name,
|
||||||
|
pageBuilder: defaultPageBuilder(const PlayerSettingsPage()),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: Routes.shakeDetectorSettings.pathName,
|
||||||
|
name: Routes.shakeDetectorSettings.name,
|
||||||
|
pageBuilder: defaultPageBuilder(
|
||||||
|
const ShakeDetectorSettingsPage(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: Routes.homePageSettings.pathName,
|
||||||
|
name: Routes.homePageSettings.name,
|
||||||
|
pageBuilder: defaultPageBuilder(
|
||||||
|
const HomePageSettingsPage(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: Routes.userManagement.localPath,
|
||||||
|
name: Routes.userManagement.name,
|
||||||
|
// builder: (context, state) => const UserManagementPage(),
|
||||||
|
pageBuilder: defaultPageBuilder(const ServerManagerPage()),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
),
|
||||||
|
|
||||||
Page handleCallback(
|
// loggers page
|
||||||
BuildContext context,
|
GoRoute(
|
||||||
GoRouterState state,
|
path: Routes.logs.localPath,
|
||||||
) {
|
name: Routes.logs.name,
|
||||||
|
// builder: (context, state) => const LogsPage(),
|
||||||
|
pageBuilder: defaultPageBuilder(const LogsPage()),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
Page handleCallback(BuildContext context, GoRouterState state) {
|
||||||
// extract the code and state from the uri
|
// extract the code and state from the uri
|
||||||
final code = state.uri.queryParameters['code'];
|
final code = state.uri.queryParameters['code'];
|
||||||
final stateParam = state.uri.queryParameters['state'];
|
final stateParam = state.uri.queryParameters['state'];
|
||||||
appLogger.fine('deep linking callback: code: $code, state: $stateParam');
|
appLogger.fine('deep linking callback: code: $code, state: $stateParam');
|
||||||
|
|
||||||
var callbackPage =
|
var callbackPage = CallbackPage(
|
||||||
CallbackPage(code: code, state: stateParam, key: ValueKey(stateParam));
|
code: code,
|
||||||
|
state: stateParam,
|
||||||
|
key: ValueKey(stateParam),
|
||||||
|
);
|
||||||
return buildPageWithDefaultTransition(
|
return buildPageWithDefaultTransition(
|
||||||
context: context,
|
context: context,
|
||||||
state: state,
|
state: state,
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,8 @@ const bottomBarHeight = 64;
|
||||||
/// BottomNavigationBar, where [child] is placed in the body of the Scaffold.
|
/// BottomNavigationBar, where [child] is placed in the body of the Scaffold.
|
||||||
class ScaffoldWithNavBar extends HookConsumerWidget {
|
class ScaffoldWithNavBar extends HookConsumerWidget {
|
||||||
/// Constructs an [ScaffoldWithNavBar].
|
/// Constructs an [ScaffoldWithNavBar].
|
||||||
const ScaffoldWithNavBar({
|
const ScaffoldWithNavBar({required this.navigationShell, Key? key})
|
||||||
required this.navigationShell,
|
: super(key: key ?? const ValueKey<String>('ScaffoldWithNavBar'));
|
||||||
Key? key,
|
|
||||||
}) : super(key: key ?? const ValueKey<String>('ScaffoldWithNavBar'));
|
|
||||||
|
|
||||||
/// The navigation shell and container for the branch Navigators.
|
/// The navigation shell and container for the branch Navigators.
|
||||||
final StatefulNavigationShell navigationShell;
|
final StatefulNavigationShell navigationShell;
|
||||||
|
|
@ -35,10 +33,11 @@ class ScaffoldWithNavBar extends HookConsumerWidget {
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
// playerExpandProgress is used to animate bottom navigation bar to opacity 0 and slide down when player is expanded
|
// playerExpandProgress is used to animate bottom navigation bar to opacity 0 and slide down when player is expanded
|
||||||
// final playerProgress =
|
// final playerProgress =
|
||||||
// useValueListenable(ref.watch(playerExpandProgressNotifierProvider));
|
// useValueListenable(ref.watch(playerExpandProgressProvider));
|
||||||
final playerProgress = ref.watch(playerHeightProvider);
|
final playerProgress = ref.watch(playerHeightProvider);
|
||||||
final playerMaxHeight = MediaQuery.of(context).size.height;
|
final playerMaxHeight = MediaQuery.of(context).size.height;
|
||||||
var percentExpandedMiniPlayer = (playerProgress - playerMinHeight) /
|
var percentExpandedMiniPlayer =
|
||||||
|
(playerProgress - playerMinHeight) /
|
||||||
(playerMaxHeight - playerMinHeight);
|
(playerMaxHeight - playerMinHeight);
|
||||||
// Clamp the value between 0 and 1
|
// Clamp the value between 0 and 1
|
||||||
percentExpandedMiniPlayer = percentExpandedMiniPlayer.clamp(0.0, 1.0);
|
percentExpandedMiniPlayer = percentExpandedMiniPlayer.clamp(0.0, 1.0);
|
||||||
|
|
@ -52,9 +51,7 @@ class ScaffoldWithNavBar extends HookConsumerWidget {
|
||||||
|
|
||||||
// close miniplayer if it is open
|
// close miniplayer if it is open
|
||||||
if (isPlayerExpanded && pendingPlayerModals == 0) {
|
if (isPlayerExpanded && pendingPlayerModals == 0) {
|
||||||
appLogger.fine(
|
appLogger.fine('BackButtonListener: closing the player');
|
||||||
'BackButtonListener: closing the player',
|
|
||||||
);
|
|
||||||
audioBookMiniplayerController.animateToHeight(state: PanelState.MIN);
|
audioBookMiniplayerController.animateToHeight(state: PanelState.MIN);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -96,12 +93,7 @@ class ScaffoldWithNavBar extends HookConsumerWidget {
|
||||||
return BackButtonListener(
|
return BackButtonListener(
|
||||||
onBackButtonPressed: onBackButtonPressed,
|
onBackButtonPressed: onBackButtonPressed,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
body: Stack(
|
body: Stack(children: [navigationShell, const AudiobookPlayer()]),
|
||||||
children: [
|
|
||||||
navigationShell,
|
|
||||||
const AudiobookPlayer(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
bottomNavigationBar: Opacity(
|
bottomNavigationBar: Opacity(
|
||||||
// Opacity is interpolated from 1 to 0 when player is expanded
|
// Opacity is interpolated from 1 to 0 when player is expanded
|
||||||
opacity: 1 - percentExpandedMiniPlayer,
|
opacity: 1 - percentExpandedMiniPlayer,
|
||||||
|
|
@ -116,11 +108,8 @@ class ScaffoldWithNavBar extends HookConsumerWidget {
|
||||||
// `navigationShell.route.branches`.
|
// `navigationShell.route.branches`.
|
||||||
destinations: _navigationItems.map((item) {
|
destinations: _navigationItems.map((item) {
|
||||||
final isDestinationLibrary = item.name == 'Library';
|
final isDestinationLibrary = item.name == 'Library';
|
||||||
var currentLibrary =
|
var currentLibrary = ref.watch(currentLibraryProvider).value;
|
||||||
ref.watch(currentLibraryProvider).valueOrNull;
|
final libraryIcon = AbsIcons.getIconByName(currentLibrary?.icon);
|
||||||
final libraryIcon = AbsIcons.getIconByName(
|
|
||||||
currentLibrary?.icon,
|
|
||||||
);
|
|
||||||
final destinationWidget = NavigationDestination(
|
final destinationWidget = NavigationDestination(
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
isDestinationLibrary ? libraryIcon ?? item.icon : item.icon,
|
isDestinationLibrary ? libraryIcon ?? item.icon : item.icon,
|
||||||
|
|
|
||||||
|
|
@ -33,29 +33,26 @@ CustomTransitionPage buildPageWithDefaultTransition<T>({
|
||||||
child: child,
|
child: child,
|
||||||
transitionsBuilder: (context, animation, secondaryAnimation, child) =>
|
transitionsBuilder: (context, animation, secondaryAnimation, child) =>
|
||||||
FadeTransition(
|
FadeTransition(
|
||||||
opacity: animation,
|
opacity: animation,
|
||||||
child: SlideTransition(
|
child: SlideTransition(
|
||||||
position: animation.drive(
|
position: animation.drive(
|
||||||
Tween(
|
Tween(
|
||||||
begin: const Offset(0, 1.50),
|
begin: const Offset(0, 1.50),
|
||||||
end: Offset.zero,
|
end: Offset.zero,
|
||||||
).chain(
|
).chain(CurveTween(curve: Curves.easeOut)),
|
||||||
CurveTween(curve: Curves.easeOut),
|
),
|
||||||
|
child: child,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: child,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Page<dynamic> Function(BuildContext, GoRouterState) defaultPageBuilder<T>(
|
Page<dynamic> Function(BuildContext, GoRouterState) defaultPageBuilder<T>(
|
||||||
Widget child,
|
Widget child,
|
||||||
) =>
|
) => (BuildContext context, GoRouterState state) {
|
||||||
(BuildContext context, GoRouterState state) {
|
return buildPageWithDefaultTransition<T>(
|
||||||
return buildPageWithDefaultTransition<T>(
|
context: context,
|
||||||
context: context,
|
state: state,
|
||||||
state: state,
|
child: child,
|
||||||
child: child,
|
);
|
||||||
);
|
};
|
||||||
};
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ class ApiSettings extends _$ApiSettings {
|
||||||
@override
|
@override
|
||||||
model.ApiSettings build() {
|
model.ApiSettings build() {
|
||||||
state = readFromBoxOrCreate();
|
state = readFromBoxOrCreate();
|
||||||
ref.listenSelf((_, __) {
|
listenSelf((_, __) {
|
||||||
writeToBox();
|
writeToBox();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,20 +6,57 @@ part of 'api_settings_provider.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$apiSettingsHash() => r'5bc1e16e9d72b77fb10637aabadf08e8947da580';
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint, type=warning
|
||||||
|
|
||||||
/// See also [ApiSettings].
|
|
||||||
@ProviderFor(ApiSettings)
|
@ProviderFor(ApiSettings)
|
||||||
final apiSettingsProvider =
|
final apiSettingsProvider = ApiSettingsProvider._();
|
||||||
NotifierProvider<ApiSettings, model.ApiSettings>.internal(
|
|
||||||
ApiSettings.new,
|
|
||||||
name: r'apiSettingsProvider',
|
|
||||||
debugGetCreateSourceHash:
|
|
||||||
const bool.fromEnvironment('dart.vm.product') ? null : _$apiSettingsHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef _$ApiSettings = Notifier<model.ApiSettings>;
|
final class ApiSettingsProvider
|
||||||
// ignore_for_file: type=lint
|
extends $NotifierProvider<ApiSettings, model.ApiSettings> {
|
||||||
// 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
|
ApiSettingsProvider._()
|
||||||
|
: super(
|
||||||
|
from: null,
|
||||||
|
argument: null,
|
||||||
|
retry: null,
|
||||||
|
name: r'apiSettingsProvider',
|
||||||
|
isAutoDispose: false,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$apiSettingsHash();
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
ApiSettings create() => ApiSettings();
|
||||||
|
|
||||||
|
/// {@macro riverpod.override_with_value}
|
||||||
|
Override overrideWithValue(model.ApiSettings value) {
|
||||||
|
return $ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
providerOverride: $SyncValueProvider<model.ApiSettings>(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String _$apiSettingsHash() => r'02af850985338eade33d76fc9965808bed548290';
|
||||||
|
|
||||||
|
abstract class _$ApiSettings extends $Notifier<model.ApiSettings> {
|
||||||
|
model.ApiSettings build();
|
||||||
|
@$mustCallSuper
|
||||||
|
@override
|
||||||
|
void runBuild() {
|
||||||
|
final ref = this.ref as $Ref<model.ApiSettings, model.ApiSettings>;
|
||||||
|
final element =
|
||||||
|
ref.element
|
||||||
|
as $ClassProviderElement<
|
||||||
|
AnyNotifier<model.ApiSettings, model.ApiSettings>,
|
||||||
|
model.ApiSettings,
|
||||||
|
Object?,
|
||||||
|
Object?
|
||||||
|
>;
|
||||||
|
element.handleCreate(ref, build);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,10 @@ model.AppSettings loadOrCreateAppSettings() {
|
||||||
settings = _box.getAt(0);
|
settings = _box.getAt(0);
|
||||||
_logger.fine('found settings in box: $settings');
|
_logger.fine('found settings in box: $settings');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
_logger.warning('error reading settings from box: $e'
|
_logger.warning(
|
||||||
'\nclearing box');
|
'error reading settings from box: $e'
|
||||||
|
'\nclearing box',
|
||||||
|
);
|
||||||
_box.clear();
|
_box.clear();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -34,7 +36,7 @@ class AppSettings extends _$AppSettings {
|
||||||
@override
|
@override
|
||||||
model.AppSettings build() {
|
model.AppSettings build() {
|
||||||
state = loadOrCreateAppSettings();
|
state = loadOrCreateAppSettings();
|
||||||
ref.listenSelf((_, __) {
|
listenSelf((_, __) {
|
||||||
writeToBox();
|
writeToBox();
|
||||||
});
|
});
|
||||||
return state;
|
return state;
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue