From 36c90c20bcd0d16162a5c0f8180675c138e0ee48 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Wed, 18 Sep 2024 01:38:02 -0400 Subject: [PATCH 01/92] chore: update release drafter configuration and workflow to v6 --- .github/release-drafter.yml | 12 +++++++++--- .github/workflows/flutter_release.yaml | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index 1979a56..8c7d11c 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -1,4 +1,4 @@ -name-template: "v$RESOLVED_VERSION 🌈" +name-template: "v$RESOLVED_VERSION" tag-template: "v$RESOLVED_VERSION" # name-template: 'v$NEXT_PATCH_VERSION' # tag-template: 'v$NEXT_PATCH_VERSION' @@ -15,7 +15,10 @@ categories: - "bug" - title: "🧰 Maintenance" label: "chore" -change-template: "- $TITLE @$AUTHOR (#$NUMBER)" + - title: "💥 Breaking Changes" + labels: + - "breaking" +change-template: "- $TITLE by @$AUTHOR in #$NUMBER" change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. version-resolver: major: @@ -33,7 +36,7 @@ template: | $CHANGES - **Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...$NEW_TAG + **Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION exclude-labels: - "skip-changelog" @@ -54,3 +57,6 @@ autolabeler: - "/feat(ure)?/i" body: - "/JIRA-[0-9]{1,4}/" + - label: "chore" + title: + - "/chore/i" diff --git a/.github/workflows/flutter_release.yaml b/.github/workflows/flutter_release.yaml index a8fde31..3ba9d6b 100644 --- a/.github/workflows/flutter_release.yaml +++ b/.github/workflows/flutter_release.yaml @@ -62,7 +62,7 @@ jobs: - name: Generate Release Notes id: generate_release_notes - uses: release-drafter/release-drafter@v5 + uses: release-drafter/release-drafter@v6 env: GITHUB_TOKEN: ${{ github.token }} @@ -70,6 +70,6 @@ jobs: uses: ncipollo/release-action@v1 with: artifacts: build/app/outputs/flutter-apk/app-release.apk - name: Release ${{ steps.version.outputs.version }} + name: v${{ steps.version.outputs.version }} tag: ${{ github.ref }} body: ${{ steps.generate_release_notes.outputs.body }} From bee1d233bfe54d16557d5f9361858f36784d7450 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Thu, 19 Sep 2024 00:44:27 -0400 Subject: [PATCH 02/92] refactor: replace BottomNavigationBar with NavigationBar and adjust height calculation --- lib/router/scaffold_with_nav_bar.dart | 62 +++++++++++---------------- 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/lib/router/scaffold_with_nav_bar.dart b/lib/router/scaffold_with_nav_bar.dart index 0062919..2fea966 100644 --- a/lib/router/scaffold_with_nav_bar.dart +++ b/lib/router/scaffold_with_nav_bar.dart @@ -12,6 +12,8 @@ import 'package:vaani/features/player/view/player_when_expanded.dart'; // if stack is empty, push home, if already contains home, pop it final Set navigationShellStack = {}; +const bottomBarHeight = 64; + /// Builds the "shell" for the app by building a Scaffold with a /// BottomNavigationBar, where [child] is placed in the body of the Scaffold. class ScaffoldWithNavBar extends HookConsumerWidget { @@ -31,10 +33,10 @@ class ScaffoldWithNavBar extends HookConsumerWidget { // useValueListenable(ref.watch(playerExpandProgressNotifierProvider)); final playerProgress = ref.watch(playerHeightProvider); final playerMaxHeight = MediaQuery.of(context).size.height; - var percentExpanded = (playerProgress - playerMinHeight) / + var percentExpandedMiniPlayer = (playerProgress - playerMinHeight) / (playerMaxHeight - playerMinHeight); // Clamp the value between 0 and 1 - percentExpanded = percentExpanded.clamp(0.0, 1.0); + percentExpandedMiniPlayer = percentExpandedMiniPlayer.clamp(0.0, 1.0); onBackButtonPressed() async { final isPlayerExpanded = playerProgress != playerMinHeight; @@ -97,41 +99,29 @@ class ScaffoldWithNavBar extends HookConsumerWidget { ), bottomNavigationBar: Opacity( // Opacity is interpolated from 1 to 0 when player is expanded - opacity: 1 - percentExpanded, - child: SizedBox( - // height is interpolated from 0 to 56 when player is expanded - height: 56 * (1 - percentExpanded), + opacity: 1 - percentExpandedMiniPlayer, + child: NavigationBar( + elevation: 0.0, + height: bottomBarHeight * (1 - percentExpandedMiniPlayer), - child: BottomNavigationBar( - elevation: 0.0, - landscapeLayout: BottomNavigationBarLandscapeLayout.centered, - selectedFontSize: - Theme.of(context).textTheme.labelMedium!.fontSize!, - unselectedFontSize: - Theme.of(context).textTheme.labelMedium!.fontSize!, - showUnselectedLabels: false, - fixedColor: Theme.of(context).colorScheme.onSurface, - enableFeedback: true, - type: BottomNavigationBarType.fixed, - - // Here, the items of BottomNavigationBar are hard coded. In a real - // world scenario, the items would most likely be generated from the - // branches of the shell route, which can be fetched using - // `navigationShell.route.branches`. - items: _navigationItems - .map( - (item) => BottomNavigationBarItem( - icon: Icon(item.icon), - activeIcon: item.activeIcon != null - ? Icon(item.activeIcon) - : Icon(item.icon), - label: item.name, - ), - ) - .toList(), - currentIndex: navigationShell.currentIndex, - onTap: (int index) => _onTap(context, index, ref), - ), + // TODO: get destinations from the navigationShell + // Here, the items of BottomNavigationBar are hard coded. In a real + // world scenario, the items would most likely be generated from the + // branches of the shell route, which can be fetched using + // `navigationShell.route.branches`. + destinations: _navigationItems + .map( + (item) => NavigationDestination( + icon: Icon(item.icon), + selectedIcon: item.activeIcon != null + ? Icon(item.activeIcon) + : Icon(item.icon), + label: item.name, + ), + ) + .toList(), + selectedIndex: navigationShell.currentIndex, + onDestinationSelected: (int index) => _onTap(context, index, ref), ), ), ), From 792448b0efcfc749f696d13b7ca1acbce677312b Mon Sep 17 00:00:00 2001 From: "Dr.Blank" Date: Sun, 22 Sep 2024 22:05:28 -0400 Subject: [PATCH 03/92] feat: downloads support (#22) * feat: enhance download manager with improved logging and task handling * feat: add total size calculation for library items and improve download manager functionality * refactor: simplify parameters in queueAudioBookDownload and improve logging message in deleteDownloadedItem --- .../downloads/core/download_manager.dart | 120 +++-- .../downloads/providers/download_manager.dart | 121 ++++- .../providers/download_manager.g.dart | 434 +++++++++++++++--- .../view/library_item_actions.dart | 226 ++++++--- lib/main.dart | 4 - lib/shared/extensions/item_files.dart | 10 + 6 files changed, 723 insertions(+), 192 deletions(-) create mode 100644 lib/shared/extensions/item_files.dart diff --git a/lib/features/downloads/core/download_manager.dart b/lib/features/downloads/core/download_manager.dart index 99f9f1c..5b6229d 100644 --- a/lib/features/downloads/core/download_manager.dart +++ b/lib/features/downloads/core/download_manager.dart @@ -1,5 +1,6 @@ // download manager to handle download tasks of files +import 'dart:async'; import 'dart:io'; import 'package:background_downloader/background_downloader.dart'; @@ -38,6 +39,7 @@ class AudiobookDownloadManager { _logger.fine( 'requiresWiFi: $requiresWiFi, retries: $retries, allowPause: $allowPause', ); + initDownloadManager(); } // the base url for the audio files @@ -55,10 +57,17 @@ class AudiobookDownloadManager { // whether to allow pausing of downloads final bool allowPause; - // final List _downloadTasks = []; + final StreamController _taskStatusController = + StreamController.broadcast(); - Future queueAudioBookDownload(LibraryItemExpanded item) async { - _logger.info('queuing download for item: ${item.toJson()}'); + Stream get taskUpdateStream => _taskStatusController.stream; + + late StreamSubscription _updatesSubscription; + + Future queueAudioBookDownload( + LibraryItemExpanded item, + ) async { + _logger.info('queuing download for item: ${item.id}'); // create a download task for each file in the item final directory = await getApplicationSupportDirectory(); for (final file in item.libraryFiles) { @@ -80,35 +89,13 @@ class AudiobookDownloadManager { allowPause: allowPause, group: item.id, baseDirectory: downloadDirectory, + updates: Updates.statusAndProgress, // metaData: token ); // _downloadTasks.add(task); tq.add(task); - _logger.info('queued task: ${task.toJson()}'); + _logger.info('queued task: ${task.taskId}'); } - - FileDownloader().registerCallbacks( - group: item.id, - taskProgressCallback: (update) { - _logger.info('Group: ${item.id}, Progress Update: ${update.progress}'); - }, - taskStatusCallback: (update) { - switch (update.status) { - case TaskStatus.complete: - _logger.info('Group: ${item.id}, Download Complete'); - break; - case TaskStatus.failed: - _logger.warning('Group: ${item.id}, Download Failed'); - break; - default: - _logger - .info('Group: ${item.id}, Download Status: ${update.status}'); - } - }, - taskNotificationTapCallback: (task, notificationType) { - _logger.info('Group: ${item.id}, Task: ${task.toJson()}'); - }, - ); } String constructFilePath( @@ -118,23 +105,41 @@ class AudiobookDownloadManager { ) => '${directory.path}/${item.relPath}/${file.metadata.filename}'; - // void startDownload() { - // for (final task in _downloadTasks) { - // _logger.fine('enqueuing task: $task'); - // FileDownloader().enqueue(task); - // } - // } - void dispose() { - // tq.removeAll(); - _logger.fine('disposed'); + _updatesSubscription.cancel(); + FileDownloader().destroy(); + _logger.fine('Destroyed download manager'); + } + + bool isItemDownloading(String id) { + return tq.enqueued.any((task) => task.group == id); } bool isFileDownloaded(String filePath) { - // Check if the file exists - final fileExists = File(filePath).existsSync(); + return File(filePath).existsSync(); + } - return fileExists; + Future> getDownloadedFilesMetadata( + LibraryItemExpanded item, + ) async { + final directory = await getApplicationSupportDirectory(); + final downloadedFiles = []; + for (final file in item.libraryFiles) { + final filePath = constructFilePath(directory, item, file); + if (isFileDownloaded(filePath)) { + downloadedFiles.add(file); + } + } + + return downloadedFiles; + } + + Future getDownloadedSize(LibraryItemExpanded item) async { + final files = await getDownloadedFilesMetadata(item); + return files.fold( + 0, + (previousValue, element) => previousValue + element.metadata.size, + ); } Future isItemDownloaded(LibraryItemExpanded item) async { @@ -145,11 +150,12 @@ class AudiobookDownloadManager { return false; } } - + _logger.info('all files downloaded for item id: ${item.id}'); return true; } Future deleteDownloadedItem(LibraryItemExpanded item) async { + _logger.info('deleting downloaded item with id: ${item.id}'); final directory = await getApplicationSupportDirectory(); for (final file in item.libraryFiles) { final filePath = constructFilePath(directory, item, file); @@ -160,7 +166,7 @@ class AudiobookDownloadManager { } } - Future> getDownloadedFiles(LibraryItemExpanded item) async { + Future> getDownloadedFilesUri(LibraryItemExpanded item) async { final directory = await getApplicationSupportDirectory(); final files = []; for (final file in item.libraryFiles) { @@ -172,14 +178,28 @@ class AudiobookDownloadManager { return files; } -} -Future initDownloadManager() async { - // initialize the download manager - var fileDownloader = FileDownloader(); - fileDownloader.configureNotification( - running: const TaskNotification('Downloading', 'file: {filename}'), - progressBar: true, - ); - await fileDownloader.trackTasks(); + Future initDownloadManager() async { + // initialize the download manager + _logger.info('Initializing download manager'); + final fileDownloader = FileDownloader(); + + _logger.info('Configuring Notification'); + fileDownloader.configureNotification( + running: const TaskNotification('Downloading', 'file: {filename}'), + progressBar: true, + ); + + await fileDownloader.trackTasks(); + + try { + _updatesSubscription = fileDownloader.updates.listen((event) { + _logger.finer('Got event: $event'); + _taskStatusController.add(event); + }); + _logger.info('Listening to download manager updates'); + } catch (e) { + _logger.warning('Error when listening to download manager updates: $e'); + } + } } diff --git a/lib/features/downloads/providers/download_manager.dart b/lib/features/downloads/providers/download_manager.dart index 6a04a8f..9fb52dd 100644 --- a/lib/features/downloads/providers/download_manager.dart +++ b/lib/features/downloads/providers/download_manager.dart @@ -1,13 +1,17 @@ import 'package:background_downloader/background_downloader.dart'; +import 'package:logging/logging.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:shelfsdk/audiobookshelf_api.dart'; import 'package:vaani/api/api_provider.dart'; -import 'package:vaani/features/downloads/core/download_manager.dart' - as core; +import 'package:vaani/api/library_item_provider.dart'; +import 'package:vaani/features/downloads/core/download_manager.dart' as core; import 'package:vaani/settings/app_settings_provider.dart'; +import 'package:vaani/shared/extensions/item_files.dart'; part 'download_manager.g.dart'; +final _logger = Logger('AudiobookDownloadManagerProvider'); + @Riverpod(keepAlive: true) class SimpleDownloadManager extends _$SimpleDownloadManager { @override @@ -25,6 +29,7 @@ class SimpleDownloadManager extends _$SimpleDownloadManager { core.tq.maxConcurrent = downloadSettings.maxConcurrent; core.tq.maxConcurrentByHost = downloadSettings.maxConcurrentByHost; core.tq.maxConcurrentByGroup = downloadSettings.maxConcurrentByGroup; + ref.onDispose(() { manager.dispose(); }); @@ -33,6 +38,102 @@ class SimpleDownloadManager extends _$SimpleDownloadManager { } } +@Riverpod(keepAlive: true) +class DownloadManager extends _$DownloadManager { + @override + core.AudiobookDownloadManager build() { + final manager = ref.watch(simpleDownloadManagerProvider); + manager.taskUpdateStream.listen((_) { + ref.notifyListeners(); + }); + return manager; + } + + Future queueAudioBookDownload( + LibraryItemExpanded item, { + void Function(TaskStatusUpdate)? taskStatusCallback, + void Function(TaskProgressUpdate)? taskProgressCallback, + }) async { + await state.queueAudioBookDownload( + item, + taskStatusCallback: (item) { + try { + taskStatusCallback?.call(item); + } catch (e) { + _logger.severe('Error in taskStatusCallback', e); + } + ref.notifyListeners(); + }, + taskProgressCallback: (item) { + try { + taskProgressCallback?.call(item); + } catch (e) { + _logger.severe('Error in taskProgressCallback', e); + } + ref.notifyListeners(); + }, + ); + } + + Future deleteDownloadedItem(LibraryItemExpanded item) async { + await state.deleteDownloadedItem(item); + ref.notifyListeners(); + } +} + +@riverpod +class IsItemDownloading extends _$IsItemDownloading { + @override + bool build(String id) { + final manager = ref.watch(downloadManagerProvider); + return manager.isItemDownloading(id); + } +} + +@riverpod +class ItemDownloadProgress extends _$ItemDownloadProgress { + @override + Future build(String id) async { + final item = await ref.watch(libraryItemProvider(id).future); + final manager = ref.read(downloadManagerProvider); + manager.taskUpdateStream.map((taskUpdate) { + if (taskUpdate is! TaskProgressUpdate) { + return null; + } + if (taskUpdate.task.group == id) { + return taskUpdate; + } + }).listen((task) async { + if (task != null) { + final totalSize = item.totalSize; + // if total size is 0, return 0 + if (totalSize == 0) { + state = const AsyncValue.data(0.0); + return; + } + final downloadedFiles = await manager.getDownloadedFilesMetadata(item); + // calculate total size of downloaded files and total size of item, then divide + // to get percentage + final downloadedSize = downloadedFiles.fold( + 0, + (previousValue, element) => previousValue + element.metadata.size, + ); + + final inProgressFileSize = task.progress * task.expectedFileSize; + final totalDownloadedSize = downloadedSize + inProgressFileSize; + final progress = totalDownloadedSize / totalSize; + // if current progress is more than calculated progress, do not update + if (progress < (state.valueOrNull ?? 0.0)) { + return; + } + + state = AsyncValue.data(progress.clamp(0.0, 1.0)); + } + }); + return null; + } +} + @riverpod FutureOr> downloadHistory( DownloadHistoryRef ref, { @@ -41,11 +142,13 @@ FutureOr> downloadHistory( return await FileDownloader().database.allRecords(group: group); } -@Riverpod(keepAlive: false) -FutureOr downloadStatus( - DownloadStatusRef ref, - LibraryItemExpanded item, -) async { - final manager = ref.read(simpleDownloadManagerProvider); - return manager.isItemDownloaded(item); +@riverpod +class IsItemDownloaded extends _$IsItemDownloaded { + @override + FutureOr build( + LibraryItemExpanded item, + ) { + final manager = ref.watch(downloadManagerProvider); + return manager.isItemDownloaded(item); + } } diff --git a/lib/features/downloads/providers/download_manager.g.dart b/lib/features/downloads/providers/download_manager.g.dart index 7a21240..54eb02c 100644 --- a/lib/features/downloads/providers/download_manager.g.dart +++ b/lib/features/downloads/providers/download_manager.g.dart @@ -157,29 +157,358 @@ class _DownloadHistoryProviderElement String? get group => (origin as DownloadHistoryProvider).group; } -String _$downloadStatusHash() => r'f37b4678d3c2a7c6e985b0149d72ea0f9b1b42ca'; +String _$simpleDownloadManagerHash() => + r'cec95717c86e422f88f78aa014d29e800e5a2089'; -/// See also [downloadStatus]. -@ProviderFor(downloadStatus) -const downloadStatusProvider = DownloadStatusFamily(); +/// See also [SimpleDownloadManager]. +@ProviderFor(SimpleDownloadManager) +final simpleDownloadManagerProvider = NotifierProvider.internal( + SimpleDownloadManager.new, + name: r'simpleDownloadManagerProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$simpleDownloadManagerHash, + dependencies: null, + allTransitiveDependencies: null, +); -/// See also [downloadStatus]. -class DownloadStatusFamily extends Family> { - /// See also [downloadStatus]. - const DownloadStatusFamily(); +typedef _$SimpleDownloadManager = Notifier; +String _$downloadManagerHash() => r'9566b772d792b32e1b199d4aa834e28de3b034d0'; - /// See also [downloadStatus]. - DownloadStatusProvider call( +/// See also [DownloadManager]. +@ProviderFor(DownloadManager) +final downloadManagerProvider = + NotifierProvider.internal( + DownloadManager.new, + name: r'downloadManagerProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$downloadManagerHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$DownloadManager = Notifier; +String _$isItemDownloadingHash() => r'ea43c06393beec828134e08d5f896ddbcfbac8f0'; + +abstract class _$IsItemDownloading extends BuildlessAutoDisposeNotifier { + late final String id; + + bool build( + String id, + ); +} + +/// See also [IsItemDownloading]. +@ProviderFor(IsItemDownloading) +const isItemDownloadingProvider = IsItemDownloadingFamily(); + +/// See also [IsItemDownloading]. +class IsItemDownloadingFamily extends Family { + /// See also [IsItemDownloading]. + const IsItemDownloadingFamily(); + + /// See also [IsItemDownloading]. + IsItemDownloadingProvider call( + String id, + ) { + return IsItemDownloadingProvider( + id, + ); + } + + @override + IsItemDownloadingProvider getProviderOverride( + covariant IsItemDownloadingProvider provider, + ) { + return call( + provider.id, + ); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'isItemDownloadingProvider'; +} + +/// See also [IsItemDownloading]. +class IsItemDownloadingProvider + extends AutoDisposeNotifierProviderImpl { + /// See also [IsItemDownloading]. + IsItemDownloadingProvider( + String id, + ) : this._internal( + () => IsItemDownloading()..id = id, + from: isItemDownloadingProvider, + name: r'isItemDownloadingProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$isItemDownloadingHash, + dependencies: IsItemDownloadingFamily._dependencies, + allTransitiveDependencies: + IsItemDownloadingFamily._allTransitiveDependencies, + id: id, + ); + + IsItemDownloadingProvider._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 + bool runNotifierBuild( + covariant IsItemDownloading notifier, + ) { + return notifier.build( + id, + ); + } + + @override + Override overrideWith(IsItemDownloading Function() create) { + return ProviderOverride( + origin: this, + override: IsItemDownloadingProvider._internal( + () => create()..id = id, + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + id: id, + ), + ); + } + + @override + AutoDisposeNotifierProviderElement createElement() { + return _IsItemDownloadingProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is IsItemDownloadingProvider && other.id == id; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, id.hashCode); + + return _SystemHash.finish(hash); + } +} + +mixin IsItemDownloadingRef on AutoDisposeNotifierProviderRef { + /// The parameter `id` of this provider. + String get id; +} + +class _IsItemDownloadingProviderElement + extends AutoDisposeNotifierProviderElement + with IsItemDownloadingRef { + _IsItemDownloadingProviderElement(super.provider); + + @override + String get id => (origin as IsItemDownloadingProvider).id; +} + +String _$itemDownloadProgressHash() => + r'd007c55c6e2e4b992069d0306df8a600225d8598'; + +abstract class _$ItemDownloadProgress + extends BuildlessAutoDisposeAsyncNotifier { + late final String id; + + FutureOr build( + String id, + ); +} + +/// See also [ItemDownloadProgress]. +@ProviderFor(ItemDownloadProgress) +const itemDownloadProgressProvider = ItemDownloadProgressFamily(); + +/// See also [ItemDownloadProgress]. +class ItemDownloadProgressFamily extends Family> { + /// See also [ItemDownloadProgress]. + const ItemDownloadProgressFamily(); + + /// See also [ItemDownloadProgress]. + ItemDownloadProgressProvider call( + String id, + ) { + return ItemDownloadProgressProvider( + id, + ); + } + + @override + ItemDownloadProgressProvider getProviderOverride( + covariant ItemDownloadProgressProvider provider, + ) { + return call( + provider.id, + ); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'itemDownloadProgressProvider'; +} + +/// See also [ItemDownloadProgress]. +class ItemDownloadProgressProvider extends AutoDisposeAsyncNotifierProviderImpl< + ItemDownloadProgress, double?> { + /// See also [ItemDownloadProgress]. + ItemDownloadProgressProvider( + String id, + ) : this._internal( + () => ItemDownloadProgress()..id = id, + from: itemDownloadProgressProvider, + name: r'itemDownloadProgressProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$itemDownloadProgressHash, + dependencies: ItemDownloadProgressFamily._dependencies, + allTransitiveDependencies: + ItemDownloadProgressFamily._allTransitiveDependencies, + id: id, + ); + + ItemDownloadProgressProvider._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 + FutureOr runNotifierBuild( + covariant ItemDownloadProgress notifier, + ) { + return notifier.build( + id, + ); + } + + @override + Override overrideWith(ItemDownloadProgress Function() create) { + return ProviderOverride( + origin: this, + override: ItemDownloadProgressProvider._internal( + () => create()..id = id, + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + id: id, + ), + ); + } + + @override + AutoDisposeAsyncNotifierProviderElement + createElement() { + return _ItemDownloadProgressProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is ItemDownloadProgressProvider && other.id == id; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, id.hashCode); + + return _SystemHash.finish(hash); + } +} + +mixin ItemDownloadProgressRef on AutoDisposeAsyncNotifierProviderRef { + /// The parameter `id` of this provider. + String get id; +} + +class _ItemDownloadProgressProviderElement + extends AutoDisposeAsyncNotifierProviderElement with ItemDownloadProgressRef { + _ItemDownloadProgressProviderElement(super.provider); + + @override + String get id => (origin as ItemDownloadProgressProvider).id; +} + +String _$isItemDownloadedHash() => r'9bb7ba28bdb73e1ba706e849fedc9c7bd67f4b67'; + +abstract class _$IsItemDownloaded + extends BuildlessAutoDisposeAsyncNotifier { + late final LibraryItemExpanded item; + + FutureOr build( + LibraryItemExpanded item, + ); +} + +/// See also [IsItemDownloaded]. +@ProviderFor(IsItemDownloaded) +const isItemDownloadedProvider = IsItemDownloadedFamily(); + +/// See also [IsItemDownloaded]. +class IsItemDownloadedFamily extends Family> { + /// See also [IsItemDownloaded]. + const IsItemDownloadedFamily(); + + /// See also [IsItemDownloaded]. + IsItemDownloadedProvider call( LibraryItemExpanded item, ) { - return DownloadStatusProvider( + return IsItemDownloadedProvider( item, ); } @override - DownloadStatusProvider getProviderOverride( - covariant DownloadStatusProvider provider, + IsItemDownloadedProvider getProviderOverride( + covariant IsItemDownloadedProvider provider, ) { return call( provider.item, @@ -198,32 +527,30 @@ class DownloadStatusFamily extends Family> { _allTransitiveDependencies; @override - String? get name => r'downloadStatusProvider'; + String? get name => r'isItemDownloadedProvider'; } -/// See also [downloadStatus]. -class DownloadStatusProvider extends AutoDisposeFutureProvider { - /// See also [downloadStatus]. - DownloadStatusProvider( +/// See also [IsItemDownloaded]. +class IsItemDownloadedProvider + extends AutoDisposeAsyncNotifierProviderImpl { + /// See also [IsItemDownloaded]. + IsItemDownloadedProvider( LibraryItemExpanded item, ) : this._internal( - (ref) => downloadStatus( - ref as DownloadStatusRef, - item, - ), - from: downloadStatusProvider, - name: r'downloadStatusProvider', + () => IsItemDownloaded()..item = item, + from: isItemDownloadedProvider, + name: r'isItemDownloadedProvider', debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') ? null - : _$downloadStatusHash, - dependencies: DownloadStatusFamily._dependencies, + : _$isItemDownloadedHash, + dependencies: IsItemDownloadedFamily._dependencies, allTransitiveDependencies: - DownloadStatusFamily._allTransitiveDependencies, + IsItemDownloadedFamily._allTransitiveDependencies, item: item, ); - DownloadStatusProvider._internal( + IsItemDownloadedProvider._internal( super._createNotifier, { required super.name, required super.dependencies, @@ -236,13 +563,20 @@ class DownloadStatusProvider extends AutoDisposeFutureProvider { final LibraryItemExpanded item; @override - Override overrideWith( - FutureOr Function(DownloadStatusRef provider) create, + FutureOr runNotifierBuild( + covariant IsItemDownloaded notifier, ) { + return notifier.build( + item, + ); + } + + @override + Override overrideWith(IsItemDownloaded Function() create) { return ProviderOverride( origin: this, - override: DownloadStatusProvider._internal( - (ref) => create(ref as DownloadStatusRef), + override: IsItemDownloadedProvider._internal( + () => create()..item = item, from: from, name: null, dependencies: null, @@ -254,13 +588,14 @@ class DownloadStatusProvider extends AutoDisposeFutureProvider { } @override - AutoDisposeFutureProviderElement createElement() { - return _DownloadStatusProviderElement(this); + AutoDisposeAsyncNotifierProviderElement + createElement() { + return _IsItemDownloadedProviderElement(this); } @override bool operator ==(Object other) { - return other is DownloadStatusProvider && other.item == item; + return other is IsItemDownloadedProvider && other.item == item; } @override @@ -272,35 +607,18 @@ class DownloadStatusProvider extends AutoDisposeFutureProvider { } } -mixin DownloadStatusRef on AutoDisposeFutureProviderRef { +mixin IsItemDownloadedRef on AutoDisposeAsyncNotifierProviderRef { /// The parameter `item` of this provider. LibraryItemExpanded get item; } -class _DownloadStatusProviderElement - extends AutoDisposeFutureProviderElement with DownloadStatusRef { - _DownloadStatusProviderElement(super.provider); +class _IsItemDownloadedProviderElement + extends AutoDisposeAsyncNotifierProviderElement + with IsItemDownloadedRef { + _IsItemDownloadedProviderElement(super.provider); @override - LibraryItemExpanded get item => (origin as DownloadStatusProvider).item; + LibraryItemExpanded get item => (origin as IsItemDownloadedProvider).item; } - -String _$simpleDownloadManagerHash() => - r'cec95717c86e422f88f78aa014d29e800e5a2089'; - -/// See also [SimpleDownloadManager]. -@ProviderFor(SimpleDownloadManager) -final simpleDownloadManagerProvider = NotifierProvider.internal( - SimpleDownloadManager.new, - name: r'simpleDownloadManagerProvider', - debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') - ? null - : _$simpleDownloadManagerHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef _$SimpleDownloadManager = Notifier; // ignore_for_file: type=lint // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/features/item_viewer/view/library_item_actions.dart b/lib/features/item_viewer/view/library_item_actions.dart index f92d32d..1e96e14 100644 --- a/lib/features/item_viewer/view/library_item_actions.dart +++ b/lib/features/item_viewer/view/library_item_actions.dart @@ -1,5 +1,6 @@ import 'package:background_downloader/background_downloader.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_animate/flutter_animate.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:shelfsdk/audiobookshelf_api.dart' as shelfsdk; @@ -8,7 +9,10 @@ import 'package:vaani/constants/hero_tag_conventions.dart'; import 'package:vaani/features/downloads/providers/download_manager.dart' show downloadHistoryProvider, - downloadStatusProvider, + downloadManagerProvider, + isItemDownloadedProvider, + isItemDownloadingProvider, + itemDownloadProgressProvider, simpleDownloadManagerProvider; import 'package:vaani/features/item_viewer/view/library_item_page.dart'; import 'package:vaani/features/per_book_settings/providers/book_settings_provider.dart'; @@ -33,10 +37,7 @@ class LibraryItemActions extends HookConsumerWidget { late final shelfsdk.BookExpanded book; @override Widget build(BuildContext context, WidgetRef ref) { - final manager = ref.read(simpleDownloadManagerProvider); final downloadHistory = ref.watch(downloadHistoryProvider(group: item.id)); - final isItemDownloaded = ref.watch(downloadStatusProvider(item)); - final isBookPlaying = ref.watch(audiobookPlayerProvider).book != null; final apiSettings = ref.watch(apiSettingsProvider); return Padding( @@ -93,64 +94,9 @@ class LibraryItemActions extends HookConsumerWidget { }, icon: const Icon(Icons.share_rounded), ), - // check if the book is downloaded using manager.isItemDownloaded - isItemDownloaded.when( - data: (isDownloaded) { - if (isDownloaded) { - // already downloaded button - return IconButton( - onPressed: () { - appLogger - .fine('Pressed already downloaded button'); - // manager.openDownloadedFile(item); - // open popup menu to open or delete the file - showModalBottomSheet( - useRootNavigator: false, - context: context, - builder: (context) { - return Padding( - padding: EdgeInsets.only( - top: 8.0, - bottom: (isBookPlaying - ? playerMinHeight - : 0) + - 8, - ), - child: DownloadSheet( - item: item, - ), - ); - }, - ); - }, - icon: const Icon( - Icons.download_done_rounded, - ), - ); - } - // download button - return IconButton( - onPressed: () { - appLogger.fine('Pressed download button'); - manager.queueAudioBookDownload(item); - }, - icon: const Icon( - Icons.download_rounded, - ), - ); - }, - loading: () => const CircularProgressIndicator(), - error: (error, stackTrace) { - return IconButton( - onPressed: () { - appLogger.warning( - 'Error checking download status: $error', - ); - }, - icon: const Icon(Icons.error_rounded), - ); - }, - ), + // download button + LibItemDownloadButton(item: item), + // more button IconButton( onPressed: () { @@ -257,6 +203,130 @@ class LibraryItemActions extends HookConsumerWidget { } } +class LibItemDownloadButton extends HookConsumerWidget { + const LibItemDownloadButton({ + super.key, + required this.item, + }); + + final shelfsdk.LibraryItemExpanded item; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final isItemDownloaded = ref.watch(isItemDownloadedProvider(item)); + if (isItemDownloaded.valueOrNull ?? false) { + return AlreadyItemDownloadedButton(item: item); + } + final isItemDownloading = ref.watch(isItemDownloadingProvider(item.id)); + + return isItemDownloading + ? ItemCurrentlyInDownloadQueue( + item: item, + ) + : IconButton( + onPressed: () { + appLogger.fine('Pressed download button'); + + ref + .read(downloadManagerProvider.notifier) + .queueAudioBookDownload(item); + }, + icon: const Icon( + Icons.download_rounded, + ), + ); + } +} + +class ItemCurrentlyInDownloadQueue extends HookConsumerWidget { + const ItemCurrentlyInDownloadQueue({ + super.key, + required this.item, + }); + + final shelfsdk.LibraryItemExpanded item; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final progress = + ref.watch(itemDownloadProgressProvider(item.id)).valueOrNull; + + if (progress == 1) { + return AlreadyItemDownloadedButton(item: item); + } + + const shimmerDuration = Duration(milliseconds: 1000); + return Stack( + alignment: Alignment.center, + children: [ + CircularProgressIndicator( + value: progress, + strokeWidth: 2, + ), + const Icon( + Icons.download, + // color: Theme.of(context).progressIndicatorTheme.color, + ) + .animate( + onPlay: (controller) => controller.repeat(), + ) + .fade( + duration: shimmerDuration, + end: 1, + begin: 0.6, + curve: Curves.linearToEaseOut, + ) + .fade( + duration: shimmerDuration, + end: 0.7, + begin: 1, + curve: Curves.easeInToLinear, + ), + ], + ); + } +} + +class AlreadyItemDownloadedButton extends HookConsumerWidget { + const AlreadyItemDownloadedButton({ + super.key, + required this.item, + }); + + final shelfsdk.LibraryItemExpanded item; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final isBookPlaying = ref.watch(audiobookPlayerProvider).book != null; + + return IconButton( + onPressed: () { + appLogger.fine('Pressed already downloaded button'); + // manager.openDownloadedFile(item); + // open popup menu to open or delete the file + showModalBottomSheet( + useRootNavigator: false, + context: context, + builder: (context) { + return Padding( + padding: EdgeInsets.only( + top: 8.0, + bottom: (isBookPlaying ? playerMinHeight : 0) + 8, + ), + child: DownloadSheet( + item: item, + ), + ); + }, + ); + }, + icon: const Icon( + Icons.download_done_rounded, + ), + ); + } +} + class DownloadSheet extends HookConsumerWidget { const DownloadSheet({ super.key, @@ -267,7 +337,7 @@ class DownloadSheet extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final manager = ref.read(simpleDownloadManagerProvider); + final manager = ref.watch(downloadManagerProvider); return Column( mainAxisSize: MainAxisSize.min, @@ -296,9 +366,9 @@ class DownloadSheet extends HookConsumerWidget { leading: const Icon( Icons.delete_rounded, ), - onTap: () { + onTap: () async { // show the delete dialog - showDialog( + final wasDeleted = await showDialog( useRootNavigator: false, context: context, builder: (context) { @@ -311,16 +381,18 @@ class DownloadSheet extends HookConsumerWidget { TextButton( onPressed: () { // delete the file - manager.deleteDownloadedItem( - item, - ); - GoRouter.of(context).pop(); + ref + .read(downloadManagerProvider.notifier) + .deleteDownloadedItem( + item, + ); + GoRouter.of(context).pop(true); }, child: const Text('Yes'), ), TextButton( onPressed: () { - GoRouter.of(context).pop(); + GoRouter.of(context).pop(false); }, child: const Text('No'), ), @@ -328,6 +400,18 @@ class DownloadSheet extends HookConsumerWidget { ); }, ); + + if (wasDeleted ?? false) { + appLogger.fine('Deleted ${item.media.metadata.title}'); + GoRouter.of(context).pop(); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + 'Deleted ${item.media.metadata.title}', + ), + ), + ); + } }, ), ], @@ -444,7 +528,7 @@ Future libraryItemPlayButtonOnPressed({ final downloadManager = ref.watch(simpleDownloadManagerProvider); final libItem = await ref.read(libraryItemProvider(book.libraryItemId).future); - final downloadedUris = await downloadManager.getDownloadedFiles(libItem); + final downloadedUris = await downloadManager.getDownloadedFilesUri(libItem); setSourceFuture = player.setSourceAudiobook( book, initialPosition: userMediaProgress?.currentTime, diff --git a/lib/main.dart b/lib/main.dart index 2630802..381d27f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -8,7 +8,6 @@ import 'package:just_audio_media_kit/just_audio_media_kit.dart' import 'package:logging/logging.dart'; import 'package:vaani/api/server_provider.dart'; import 'package:vaani/db/storage.dart'; -import 'package:vaani/features/downloads/core/download_manager.dart'; import 'package:vaani/features/downloads/providers/download_manager.dart'; import 'package:vaani/features/playback_reporting/providers/playback_reporter_provider.dart'; import 'package:vaani/features/player/providers/audiobook_player.dart'; @@ -49,9 +48,6 @@ void main() async { androidNotificationOngoing: true, ); - // for initializing the download manager - await initDownloadManager(); - // run the app runApp( const ProviderScope( diff --git a/lib/shared/extensions/item_files.dart b/lib/shared/extensions/item_files.dart new file mode 100644 index 0000000..b658f24 --- /dev/null +++ b/lib/shared/extensions/item_files.dart @@ -0,0 +1,10 @@ +import 'package:shelfsdk/audiobookshelf_api.dart'; + +extension TotalSize on LibraryItemExpanded { + int get totalSize { + return libraryFiles.fold( + 0, + (previousValue, element) => previousValue + element.metadata.size, + ); + } +} From 5c9273c812ca6b122a6aa74f661f1f9aca871356 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Sun, 22 Sep 2024 22:24:36 -0400 Subject: [PATCH 04/92] refactor: simplify queueAudioBookDownload method by removing callback handling --- .../downloads/providers/download_manager.dart | 22 ++----------------- .../providers/download_manager.g.dart | 2 +- 2 files changed, 3 insertions(+), 21 deletions(-) diff --git a/lib/features/downloads/providers/download_manager.dart b/lib/features/downloads/providers/download_manager.dart index 9fb52dd..87a2191 100644 --- a/lib/features/downloads/providers/download_manager.dart +++ b/lib/features/downloads/providers/download_manager.dart @@ -50,28 +50,10 @@ class DownloadManager extends _$DownloadManager { } Future queueAudioBookDownload( - LibraryItemExpanded item, { - void Function(TaskStatusUpdate)? taskStatusCallback, - void Function(TaskProgressUpdate)? taskProgressCallback, - }) async { + LibraryItemExpanded item, + ) async { await state.queueAudioBookDownload( item, - taskStatusCallback: (item) { - try { - taskStatusCallback?.call(item); - } catch (e) { - _logger.severe('Error in taskStatusCallback', e); - } - ref.notifyListeners(); - }, - taskProgressCallback: (item) { - try { - taskProgressCallback?.call(item); - } catch (e) { - _logger.severe('Error in taskProgressCallback', e); - } - ref.notifyListeners(); - }, ); } diff --git a/lib/features/downloads/providers/download_manager.g.dart b/lib/features/downloads/providers/download_manager.g.dart index 54eb02c..43fc01c 100644 --- a/lib/features/downloads/providers/download_manager.g.dart +++ b/lib/features/downloads/providers/download_manager.g.dart @@ -174,7 +174,7 @@ final simpleDownloadManagerProvider = NotifierProvider; -String _$downloadManagerHash() => r'9566b772d792b32e1b199d4aa834e28de3b034d0'; +String _$downloadManagerHash() => r'7296a39439230f77abbe7d3231dae748f09c7ecf'; /// See also [DownloadManager]. @ProviderFor(DownloadManager) From ef134af1fc7cea681c6cabac619cd7e715630860 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Sun, 22 Sep 2024 22:30:58 -0400 Subject: [PATCH 05/92] feat: add GitHub Actions workflow for Flutter testing and APK build --- .github/workflows/flutter_test.yaml | 41 +++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .github/workflows/flutter_test.yaml diff --git a/.github/workflows/flutter_test.yaml b/.github/workflows/flutter_test.yaml new file mode 100644 index 0000000..dac19be --- /dev/null +++ b/.github/workflows/flutter_test.yaml @@ -0,0 +1,41 @@ +name: Flutter Test + +on: + push: + branches: + - main + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Checkout shelfsdk + uses: actions/checkout@v3 + with: + repository: Dr-Blank/shelfsdk + path: ./shelfsdk + + - name: Set Up Java + uses: actions/setup-java@v3.12.0 + with: + distribution: "oracle" + java-version: "17" + + - name: Set up Flutter + uses: subosito/flutter-action@v2 + with: + channel: "stable" + + - name: Install dependencies + run: flutter pub get + + # - name: Run tests + # run: flutter test + + - name: Build APK + run: flutter build apk --release From c032595fc133ac8f059d02a3bb160670906aeea4 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Sun, 22 Sep 2024 22:43:10 -0400 Subject: [PATCH 06/92] chore: bump version to 0.0.4+1 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index b08f1d1..8a659a7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.0.3+1 +version: 0.0.4+1 environment: sdk: ">=3.3.4 <4.0.0" From d25d23a0b710b83f978d261c8e138ee86b3e02bd Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Mon, 23 Sep 2024 01:09:45 -0400 Subject: [PATCH 07/92] feat: add keystore decoding and signing configuration for release builds --- .github/workflows/flutter_release.yaml | 6 ++++++ .github/workflows/flutter_test.yaml | 6 ++++++ android/app/build.gradle | 19 +++++++++++++++++-- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/.github/workflows/flutter_release.yaml b/.github/workflows/flutter_release.yaml index 3ba9d6b..ec1053b 100644 --- a/.github/workflows/flutter_release.yaml +++ b/.github/workflows/flutter_release.yaml @@ -18,6 +18,12 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 + - name: Decode android/upload.jks + run: echo "${{ secrets.UPLOAD_KEYSTORE_JKS }}" | base64 --decode > android/upload.jks + + - name: Decode android/key.properties + run: echo "${{ secrets.KEY_PROPERTIES }}" | base64 --decode > android/key.properties + - name: Checkout shelfsdk uses: actions/checkout@v3 with: diff --git a/.github/workflows/flutter_test.yaml b/.github/workflows/flutter_test.yaml index dac19be..c2f502f 100644 --- a/.github/workflows/flutter_test.yaml +++ b/.github/workflows/flutter_test.yaml @@ -14,6 +14,12 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 + - name: Decode android/upload.jks + run: echo "${{ secrets.UPLOAD_KEYSTORE_JKS }}" | base64 --decode > android/upload.jks + + - name: Decode android/key.properties + run: echo "${{ secrets.KEY_PROPERTIES }}" | base64 --decode > android/key.properties + - name: Checkout shelfsdk uses: actions/checkout@v3 with: diff --git a/android/app/build.gradle b/android/app/build.gradle index 0759e63..b13356f 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -22,6 +22,12 @@ if (flutterVersionName == null) { flutterVersionName = '1.0' } +def keystoreProperties = new Properties() +def keystorePropertiesFile = rootProject.file('key.properties') +if (keystorePropertiesFile.exists()) { + keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) +} + android { namespace "dr.blank.vaani" compileSdk flutter.compileSdkVersion @@ -51,11 +57,20 @@ android { versionName flutterVersionName } + signingConfigs { + release { + keyAlias = keystoreProperties['keyAlias'] + keyPassword = keystoreProperties['keyPassword'] + storeFile = keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null + storePassword = keystoreProperties['storePassword'] + } + } + buildTypes { release { - // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug + // signingConfig signingConfigs.debug + signingConfig = signingConfigs.release } } } From 405d625cdcaf9e715027aa240bcd2a2ea606bbda Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Mon, 23 Sep 2024 03:55:32 -0400 Subject: [PATCH 08/92] refactor: update cover image handling to use item IDs and simplify library item actions --- lib/api/image_provider.dart | 24 +- lib/api/image_provider.g.dart | 38 +-- lib/api/library_item_provider.dart | 4 +- lib/api/library_item_provider.g.dart | 19 +- lib/features/explore/view/explore_page.dart | 2 +- .../view/library_item_actions.dart | 16 +- .../view/library_item_hero_section.dart | 294 +++++++++--------- .../view/library_item_metadata.dart | 106 +++---- .../item_viewer/view/library_item_page.dart | 77 ++--- .../player/view/audiobook_player.dart | 4 +- lib/router/models/library_item_extras.dart | 3 - .../models/library_item_extras.freezed.dart | 34 +- lib/shared/widgets/shelves/book_shelf.dart | 9 +- lib/theme/theme_from_cover_provider.dart | 7 +- lib/theme/theme_from_cover_provider.g.dart | 30 +- 15 files changed, 305 insertions(+), 362 deletions(-) diff --git a/lib/api/image_provider.dart b/lib/api/image_provider.dart index 42b9e4b..9707542 100644 --- a/lib/api/image_provider.dart +++ b/lib/api/image_provider.dart @@ -4,6 +4,7 @@ import 'package:logging/logging.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:shelfsdk/audiobookshelf_api.dart'; import 'package:vaani/api/api_provider.dart'; +import 'package:vaani/api/library_item_provider.dart'; import 'package:vaani/db/cache_manager.dart'; /// provides cover images for the audiobooks @@ -19,52 +20,53 @@ final _logger = Logger('cover_image_provider'); @Riverpod(keepAlive: true) class CoverImage extends _$CoverImage { @override - Stream build(LibraryItem libraryItem) async* { + Stream build(String itemId) async* { final api = ref.watch(authenticatedApiProvider); // ! artifical delay for testing // await Future.delayed(const Duration(seconds: 2)); // try to get the image from the cache - final file = await imageCacheManager.getFileFromMemory(libraryItem.id) ?? - await imageCacheManager.getFileFromCache(libraryItem.id); + final file = await imageCacheManager.getFileFromMemory(itemId) ?? + await imageCacheManager.getFileFromCache(itemId); if (file != null) { // if the image is in the cache, yield it _logger.fine( - 'cover image found in cache for ${libraryItem.id} at ${file.file.path}', + 'cover image found in cache for $itemId at ${file.file.path}', ); yield await file.file.readAsBytes(); + final libraryItem = await ref.watch(libraryItemProvider(itemId).future); // return if no need to fetch from the server if (libraryItem.updatedAt.isBefore(await file.file.lastModified())) { _logger.fine( - 'cover image is up to date for ${libraryItem.id}, no need to fetch from the server', + 'cover image is up to date for $itemId, no need to fetch from the server', ); return; } else { _logger.fine( - 'cover image stale for ${libraryItem.id}, fetching from the server', + 'cover image stale for $itemId, fetching from the server', ); } } else { - _logger.fine('cover image not found in cache for ${libraryItem.id}'); + _logger.fine('cover image not found in cache for $itemId'); } // check if the image is in the cache final coverImage = await api.items.getCover( - libraryItemId: libraryItem.id, + libraryItemId: itemId, parameters: const GetImageReqParams(width: 1200), ); // save the image to the cache if (coverImage != null) { final newFile = await imageCacheManager.putFile( - libraryItem.id, + itemId, coverImage, - key: libraryItem.id, + key: itemId, fileExtension: 'jpg', ); _logger.fine( - 'cover image fetched for for ${libraryItem.id}, file time: ${await newFile.lastModified()}', + 'cover image fetched for for $itemId, file time: ${await newFile.lastModified()}', ); } diff --git a/lib/api/image_provider.g.dart b/lib/api/image_provider.g.dart index 74f9d8e..5fa646e 100644 --- a/lib/api/image_provider.g.dart +++ b/lib/api/image_provider.g.dart @@ -6,7 +6,7 @@ part of 'image_provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$coverImageHash() => r'702afafa217dfcbb290837caf21cc1ef54defd55'; +String _$coverImageHash() => r'89cc4783cbc76bb41beae34384d92fb277135c75'; /// Copied from Dart SDK class _SystemHash { @@ -30,10 +30,10 @@ class _SystemHash { } abstract class _$CoverImage extends BuildlessStreamNotifier { - late final LibraryItem libraryItem; + late final String itemId; Stream build( - LibraryItem libraryItem, + String itemId, ); } @@ -48,10 +48,10 @@ class CoverImageFamily extends Family> { /// See also [CoverImage]. CoverImageProvider call( - LibraryItem libraryItem, + String itemId, ) { return CoverImageProvider( - libraryItem, + itemId, ); } @@ -60,7 +60,7 @@ class CoverImageFamily extends Family> { covariant CoverImageProvider provider, ) { return call( - provider.libraryItem, + provider.itemId, ); } @@ -84,9 +84,9 @@ class CoverImageProvider extends StreamNotifierProviderImpl { /// See also [CoverImage]. CoverImageProvider( - LibraryItem libraryItem, + String itemId, ) : this._internal( - () => CoverImage()..libraryItem = libraryItem, + () => CoverImage()..itemId = itemId, from: coverImageProvider, name: r'coverImageProvider', debugGetCreateSourceHash: @@ -96,7 +96,7 @@ class CoverImageProvider dependencies: CoverImageFamily._dependencies, allTransitiveDependencies: CoverImageFamily._allTransitiveDependencies, - libraryItem: libraryItem, + itemId: itemId, ); CoverImageProvider._internal( @@ -106,17 +106,17 @@ class CoverImageProvider required super.allTransitiveDependencies, required super.debugGetCreateSourceHash, required super.from, - required this.libraryItem, + required this.itemId, }) : super.internal(); - final LibraryItem libraryItem; + final String itemId; @override Stream runNotifierBuild( covariant CoverImage notifier, ) { return notifier.build( - libraryItem, + itemId, ); } @@ -125,13 +125,13 @@ class CoverImageProvider return ProviderOverride( origin: this, override: CoverImageProvider._internal( - () => create()..libraryItem = libraryItem, + () => create()..itemId = itemId, from: from, name: null, dependencies: null, allTransitiveDependencies: null, debugGetCreateSourceHash: null, - libraryItem: libraryItem, + itemId: itemId, ), ); } @@ -143,21 +143,21 @@ class CoverImageProvider @override bool operator ==(Object other) { - return other is CoverImageProvider && other.libraryItem == libraryItem; + return other is CoverImageProvider && other.itemId == itemId; } @override int get hashCode { var hash = _SystemHash.combine(0, runtimeType.hashCode); - hash = _SystemHash.combine(hash, libraryItem.hashCode); + hash = _SystemHash.combine(hash, itemId.hashCode); return _SystemHash.finish(hash); } } mixin CoverImageRef on StreamNotifierProviderRef { - /// The parameter `libraryItem` of this provider. - LibraryItem get libraryItem; + /// The parameter `itemId` of this provider. + String get itemId; } class _CoverImageProviderElement @@ -166,7 +166,7 @@ class _CoverImageProviderElement _CoverImageProviderElement(super.provider); @override - LibraryItem get libraryItem => (origin as CoverImageProvider).libraryItem; + String get itemId => (origin as CoverImageProvider).itemId; } // ignore_for_file: type=lint // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/api/library_item_provider.dart b/lib/api/library_item_provider.dart index cf81ebd..013f62e 100644 --- a/lib/api/library_item_provider.dart +++ b/lib/api/library_item_provider.dart @@ -13,7 +13,7 @@ part 'library_item_provider.g.dart'; final _logger = Logger('LibraryItemProvider'); /// provides the library item for the given id -@riverpod +@Riverpod(keepAlive: true) class LibraryItem extends _$LibraryItem { @override Stream build(String id) async* { @@ -22,7 +22,7 @@ class LibraryItem extends _$LibraryItem { _logger.fine('LibraryItemProvider fetching library item: $id'); // ! this is a mock delay - // await Future.delayed(const Duration(seconds: 10)); + // await Future.delayed(const Duration(seconds: 150)); // look for the item in the cache final key = CacheKey.libraryItem(id); diff --git a/lib/api/library_item_provider.g.dart b/lib/api/library_item_provider.g.dart index 80370c6..af297d0 100644 --- a/lib/api/library_item_provider.g.dart +++ b/lib/api/library_item_provider.g.dart @@ -6,7 +6,7 @@ part of 'library_item_provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$libraryItemHash() => r'fa3f8309349c5b1b777f1bc919616e51c3f5b520'; +String _$libraryItemHash() => r'a3cfa7f912e9498a70b5782899018b6964d6445c'; /// Copied from Dart SDK class _SystemHash { @@ -30,7 +30,7 @@ class _SystemHash { } abstract class _$LibraryItem - extends BuildlessAutoDisposeStreamNotifier { + extends BuildlessStreamNotifier { late final String id; Stream build( @@ -92,8 +92,8 @@ class LibraryItemFamily /// provides the library item for the given id /// /// Copied from [LibraryItem]. -class LibraryItemProvider extends AutoDisposeStreamNotifierProviderImpl< - LibraryItem, shelfsdk.LibraryItemExpanded> { +class LibraryItemProvider extends StreamNotifierProviderImpl { /// provides the library item for the given id /// /// Copied from [LibraryItem]. @@ -151,8 +151,8 @@ class LibraryItemProvider extends AutoDisposeStreamNotifierProviderImpl< } @override - AutoDisposeStreamNotifierProviderElement createElement() { + StreamNotifierProviderElement + createElement() { return _LibraryItemProviderElement(this); } @@ -171,14 +171,13 @@ class LibraryItemProvider extends AutoDisposeStreamNotifierProviderImpl< } mixin LibraryItemRef - on AutoDisposeStreamNotifierProviderRef { + on StreamNotifierProviderRef { /// The parameter `id` of this provider. String get id; } -class _LibraryItemProviderElement - extends AutoDisposeStreamNotifierProviderElement with LibraryItemRef { +class _LibraryItemProviderElement extends StreamNotifierProviderElement< + LibraryItem, shelfsdk.LibraryItemExpanded> with LibraryItemRef { _LibraryItemProviderElement(super.provider); @override diff --git a/lib/features/explore/view/explore_page.dart b/lib/features/explore/view/explore_page.dart index e25db0e..2a46983 100644 --- a/lib/features/explore/view/explore_page.dart +++ b/lib/features/explore/view/explore_page.dart @@ -234,7 +234,7 @@ class BookSearchResultMini extends HookConsumerWidget { final item = ref.watch(libraryItemProvider(book.libraryItemId)).valueOrNull; final image = item == null ? const AsyncValue.loading() - : ref.watch(coverImageProvider(item)); + : ref.watch(coverImageProvider(item.id)); return ListTile( leading: SizedBox( width: 50, diff --git a/lib/features/item_viewer/view/library_item_actions.dart b/lib/features/item_viewer/view/library_item_actions.dart index 1e96e14..7bc4c9c 100644 --- a/lib/features/item_viewer/view/library_item_actions.dart +++ b/lib/features/item_viewer/view/library_item_actions.dart @@ -26,17 +26,19 @@ import 'package:vaani/shared/extensions/model_conversions.dart'; import 'package:vaani/shared/utils.dart'; class LibraryItemActions extends HookConsumerWidget { - LibraryItemActions({ + const LibraryItemActions({ super.key, - required this.item, - }) { - book = item.media.asBookExpanded; - } + required this.id, + }); + + final String id; - final shelfsdk.LibraryItemExpanded item; - late final shelfsdk.BookExpanded book; @override Widget build(BuildContext context, WidgetRef ref) { + final item = ref.watch(libraryItemProvider(id)).valueOrNull; + if (item == null) { + return const SizedBox.shrink(); + } final downloadHistory = ref.watch(downloadHistoryProvider(group: item.id)); final apiSettings = ref.watch(apiSettingsProvider); diff --git a/lib/features/item_viewer/view/library_item_hero_section.dart b/lib/features/item_viewer/view/library_item_hero_section.dart index 88ef7b0..ea21da6 100644 --- a/lib/features/item_viewer/view/library_item_hero_section.dart +++ b/lib/features/item_viewer/view/library_item_hero_section.dart @@ -5,6 +5,7 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:shelfsdk/audiobookshelf_api.dart' as shelfsdk; import 'package:vaani/api/image_provider.dart'; +import 'package:vaani/api/library_item_provider.dart'; import 'package:vaani/constants/hero_tag_conventions.dart'; import 'package:vaani/features/item_viewer/view/library_item_page.dart'; import 'package:vaani/features/player/providers/audiobook_player.dart'; @@ -14,125 +15,120 @@ import 'package:vaani/settings/app_settings_provider.dart'; import 'package:vaani/shared/extensions/duration_format.dart'; import 'package:vaani/shared/extensions/model_conversions.dart'; import 'package:vaani/shared/widgets/shelves/book_shelf.dart'; +import 'package:vaani/theme/theme_from_cover_provider.dart'; class LibraryItemHeroSection extends HookConsumerWidget { const LibraryItemHeroSection({ super.key, required this.itemId, required this.extraMap, - required this.providedCacheImage, - required this.item, - required this.itemBookMetadata, - required this.bookDetailsCached, - required this.coverColorScheme, }); final String itemId; final LibraryItemExtras? extraMap; - final Image? providedCacheImage; - final AsyncValue item; - final shelfsdk.BookMetadataExpanded? itemBookMetadata; - final shelfsdk.BookMinified? bookDetailsCached; - final AsyncValue coverColorScheme; @override Widget build(BuildContext context, WidgetRef ref) { return SliverToBoxAdapter( - child: LayoutBuilder( - builder: (context, constraints) { - return Container( - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - // book cover - LayoutBuilder( - builder: (context, constraints) { - return SizedBox( - width: calculateWidth(context, constraints), - child: Column( - children: [ - Hero( - tag: HeroTagPrefixes.bookCover + - itemId + - (extraMap?.heroTagSuffix ?? ''), - child: ClipRRect( - borderRadius: BorderRadius.circular(16), - child: _BookCover( - itemId: itemId, - extraMap: extraMap, - providedCacheImage: providedCacheImage, - coverColorScheme: coverColorScheme.valueOrNull, - item: item, - ), - ), - ), - // a progress bar if available - item.when( - data: (libraryItem) { - return Padding( - padding: const EdgeInsets.only( - top: 8.0, - right: 8.0, - left: 8.0, - ), - child: _LibraryItemProgressIndicator( - libraryItem: libraryItem, - ), - ); - }, - loading: () => const SizedBox.shrink(), - error: (error, stack) => const SizedBox.shrink(), - ), - ], + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + // book cover + LayoutBuilder( + builder: (context, constraints) { + return SizedBox( + width: calculateWidth(context, constraints), + child: Column( + children: [ + Hero( + tag: HeroTagPrefixes.bookCover + + itemId + + (extraMap?.heroTagSuffix ?? ''), + child: ClipRRect( + borderRadius: BorderRadius.circular(16), + child: _BookCover( + itemId: itemId, + ), ), - ); - }, - ), - // book details - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 8), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - _BookTitle( - extraMap: extraMap, - itemBookMetadata: itemBookMetadata, - bookDetailsCached: bookDetailsCached, - ), - Container( - margin: const EdgeInsets.symmetric(vertical: 16), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - // authors info if available - _BookAuthors( - itemBookMetadata: itemBookMetadata, - bookDetailsCached: bookDetailsCached, - ), - // narrators info if available - _BookNarrators( - itemBookMetadata: itemBookMetadata, - bookDetailsCached: bookDetailsCached, - ), - // series info if available - _BookSeries( - itemBookMetadata: itemBookMetadata, - bookDetailsCached: bookDetailsCached, - ), - ], - ), - ), - ], ), - ), + // a progress bar + Padding( + padding: const EdgeInsets.only( + top: 8.0, + right: 8.0, + left: 8.0, + ), + child: _LibraryItemProgressIndicator( + id: itemId, + ), + ), + ], ), - ], + ); + }, + ), + // book details + _BookDetails(id: itemId, extraMap: extraMap), + ], + ), + ); + } +} + +class _BookDetails extends HookConsumerWidget { + const _BookDetails({ + super.key, + required this.id, + this.extraMap, + }); + + final String id; + final LibraryItemExtras? extraMap; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final itemFromApi = ref.watch(libraryItemProvider(id)); + + final itemBookMetadata = + itemFromApi.valueOrNull?.media.metadata.asBookMetadataExpanded; + + return Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + _BookTitle( + extraMap: extraMap, + itemBookMetadata: itemBookMetadata, ), - ); - }, + Container( + margin: const EdgeInsets.symmetric(vertical: 16), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + // authors info if available + _BookAuthors( + itemBookMetadata: itemBookMetadata, + bookDetailsCached: extraMap?.book, + ), + // narrators info if available + _BookNarrators( + itemBookMetadata: itemBookMetadata, + bookDetailsCached: extraMap?.book, + ), + // series info if available + _BookSeries( + itemBookMetadata: itemBookMetadata, + bookDetailsCached: extraMap?.book, + ), + ], + ), + ), + ], + ), ), ); } @@ -141,14 +137,19 @@ class LibraryItemHeroSection extends HookConsumerWidget { class _LibraryItemProgressIndicator extends HookConsumerWidget { const _LibraryItemProgressIndicator({ super.key, - required this.libraryItem, + required this.id, }); - final shelfsdk.LibraryItemExpanded libraryItem; + final String id; @override Widget build(BuildContext context, WidgetRef ref) { final player = ref.watch(audiobookPlayerProvider); + final libraryItem = ref.watch(libraryItemProvider(id)).valueOrNull; + if (libraryItem == null) { + return const SizedBox.shrink(); + } + final mediaProgress = libraryItem.userMediaProgress; if (mediaProgress == null && player.book?.libraryItemId != libraryItem.id) { return const SizedBox.shrink(); @@ -188,6 +189,8 @@ class _LibraryItemProgressIndicator extends HookConsumerWidget { LinearProgressIndicator( value: progress.clamp(0.03, 1), borderRadius: BorderRadius.circular(8), + semanticsLabel: 'Book progress', + semanticsValue: '${progressInPercent.toStringAsFixed(2)}%', ), const SizedBox.square( dimension: 4.0, @@ -341,24 +344,30 @@ class _BookCover extends HookConsumerWidget { const _BookCover({ super.key, required this.itemId, - required this.extraMap, - required this.providedCacheImage, - required this.item, - this.coverColorScheme, }); final String itemId; - final LibraryItemExtras? extraMap; - final Image? providedCacheImage; - final AsyncValue item; - final ColorScheme? coverColorScheme; @override Widget build(BuildContext context, WidgetRef ref) { + final coverImage = ref.watch(coverImageProvider(itemId)); final themeData = Theme.of(context); + // final item = ref.watch(libraryItemProvider(itemId)); final useMaterialThemeOnItemPage = ref.watch(appSettingsProvider).themeSettings.useMaterialThemeOnItemPage; + ColorScheme? coverColorScheme; + if (useMaterialThemeOnItemPage) { + coverColorScheme = ref + .watch( + themeOfLibraryItemProvider( + itemId, + brightness: Theme.of(context).brightness, + ), + ) + .valueOrNull; + } + return ThemeSwitcher( builder: (context) { // change theme after 2 seconds @@ -368,7 +377,7 @@ class _BookCover extends HookConsumerWidget { ThemeSwitcher.of(context).changeTheme( theme: coverColorScheme != null ? ThemeData.from( - colorScheme: coverColorScheme!, + colorScheme: coverColorScheme, textTheme: themeData.textTheme, ) : themeData, @@ -378,42 +387,27 @@ class _BookCover extends HookConsumerWidget { } }); } - return providedCacheImage ?? - item.when( - data: (libraryItem) { - final coverImage = ref.watch(coverImageProvider(libraryItem)); - return Stack( - children: [ - coverImage.when( - data: (image) { - // return const BookCoverSkeleton(); - if (image.isEmpty) { - return const Icon(Icons.error); - } - // cover 80% of parent height - return Image.memory( - image, - fit: BoxFit.cover, - // cacheWidth: (height * - // MediaQuery.of(context).devicePixelRatio) - // .round(), - ); - }, - loading: () { - return const Center( - child: BookCoverSkeleton(), - ); - }, - error: (error, stack) { - return const Icon(Icons.error); - }, - ), - ], - ); - }, - error: (error, stack) => const Icon(Icons.error), - loading: () => const Center(child: BookCoverSkeleton()), + return coverImage.when( + data: (image) { + // return const BookCoverSkeleton(); + if (image.isEmpty) { + return const Icon(Icons.error); + } + + return Image.memory( + image, + fit: BoxFit.cover, ); + }, + loading: () { + return const Center( + child: BookCoverSkeleton(), + ); + }, + error: (error, stack) { + return const Center(child: Icon(Icons.error)); + }, + ); }, ); } @@ -424,12 +418,10 @@ class _BookTitle extends StatelessWidget { super.key, required this.extraMap, required this.itemBookMetadata, - required this.bookDetailsCached, }); final LibraryItemExtras? extraMap; final shelfsdk.BookMetadataExpanded? itemBookMetadata; - final shelfsdk.BookMinified? bookDetailsCached; @override Widget build(BuildContext context) { @@ -449,7 +441,7 @@ class _BookTitle extends StatelessWidget { // pauseBetween: 150.ms, // numberOfReps: 3, style: themeData.textTheme.headlineLarge, - itemBookMetadata?.title ?? bookDetailsCached?.metadata.title ?? '', + itemBookMetadata?.title ?? extraMap?.book?.metadata.title ?? '', ), ), // subtitle if available @@ -482,7 +474,7 @@ class _BookAuthors extends StatelessWidget { String generateAuthorsString() { final authors = (itemBookMetadata)?.authors ?? []; if (authors.isEmpty) { - return (bookDetailsCached?.metadata as shelfsdk.BookMetadataMinified?) + return (bookDetailsCached?.metadata.asBookMetadataMinified) ?.authorName ?? ''; } diff --git a/lib/features/item_viewer/view/library_item_metadata.dart b/lib/features/item_viewer/view/library_item_metadata.dart index 1eef261..5874a92 100644 --- a/lib/features/item_viewer/view/library_item_metadata.dart +++ b/lib/features/item_viewer/view/library_item_metadata.dart @@ -1,20 +1,65 @@ import 'package:flutter/material.dart'; -import 'package:shelfsdk/audiobookshelf_api.dart' as shelfsdk; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:vaani/api/library_item_provider.dart'; +import 'package:vaani/shared/extensions/model_conversions.dart'; -class LibraryItemMetadata extends StatelessWidget { +class LibraryItemMetadata extends HookConsumerWidget { const LibraryItemMetadata({ super.key, - required this.item, - this.itemBookMetadata, - this.bookDetailsCached, + required this.id, }); - final shelfsdk.LibraryItemExpanded item; - final shelfsdk.BookMetadataExpanded? itemBookMetadata; - final shelfsdk.BookMinified? bookDetailsCached; + final String id; @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { + final item = ref.watch(libraryItemProvider(id)).valueOrNull; + + /// formats the duration of the book as `10h 30m` + /// + /// will add up all the durations of the audio files first + /// then convert them to the given format + String? getDurationFormatted() { + final book = (item?.media.asBookExpanded); + if (book == null) { + return null; + } + final duration = book.audioFiles + .map((e) => e.duration) + .reduce((value, element) => value + element); + final hours = duration.inHours; + final minutes = duration.inMinutes.remainder(60); + return '${hours}h ${minutes}m'; + } + + /// will return the size of the book in MB + /// + /// will add up all the sizes of the audio files first + /// then convert them to MB + String? getSizeFormatted() { + final book = (item?.media.asBookExpanded); + if (book == null) { + return null; + } + final size = book.audioFiles + .map((e) => e.metadata.size) + .reduce((value, element) => value + element); + return '${size / 1024 ~/ 1024} MB'; + } + + /// will return the codec and bitrate of the book + String? getCodecAndBitrate() { + final book = (item?.media.asBookExpanded); + if (book == null) { + return null; + } + final codec = book.audioFiles.first.codec.toUpperCase(); + // final bitrate = book.audioFiles.first.bitRate; + return codec; + } + + final itemBookMetadata = item?.media.metadata.asBookMetadataExpanded; + final children = [ // duration of the book _MetadataItem( @@ -59,49 +104,6 @@ class LibraryItemMetadata extends StatelessWidget { ), ); } - - /// formats the duration of the book as `10h 30m` - /// - /// will add up all the durations of the audio files first - /// then convert them to the given format - String? getDurationFormatted() { - final book = (item.media as shelfsdk.BookExpanded?); - if (book == null) { - return null; - } - final duration = book.audioFiles - .map((e) => e.duration) - .reduce((value, element) => value + element); - final hours = duration.inHours; - final minutes = duration.inMinutes.remainder(60); - return '${hours}h ${minutes}m'; - } - - /// will return the size of the book in MB - /// - /// will add up all the sizes of the audio files first - /// then convert them to MB - String? getSizeFormatted() { - final book = (item.media as shelfsdk.BookExpanded?); - if (book == null) { - return null; - } - final size = book.audioFiles - .map((e) => e.metadata.size) - .reduce((value, element) => value + element); - return '${size / 1024 ~/ 1024} MB'; - } - - /// will return the codec and bitrate of the book - String? getCodecAndBitrate() { - final book = (item.media as shelfsdk.BookExpanded?); - if (book == null) { - return null; - } - final codec = book.audioFiles.first.codec.toUpperCase(); - // final bitrate = book.audioFiles.first.bitRate; - return codec; - } } /// key-value pair to display as column diff --git a/lib/features/item_viewer/view/library_item_page.dart b/lib/features/item_viewer/view/library_item_page.dart index d682f4a..9e98003 100644 --- a/lib/features/item_viewer/view/library_item_page.dart +++ b/lib/features/item_viewer/view/library_item_page.dart @@ -8,10 +8,7 @@ import 'package:vaani/api/library_item_provider.dart'; import 'package:vaani/features/item_viewer/view/library_item_sliver_app_bar.dart'; import 'package:vaani/features/player/providers/player_form.dart'; import 'package:vaani/router/models/library_item_extras.dart'; -import 'package:vaani/settings/app_settings_provider.dart'; -import 'package:vaani/shared/extensions/model_conversions.dart'; import 'package:vaani/shared/widgets/expandable_description.dart'; -import 'package:vaani/theme/theme_from_cover_provider.dart'; import 'library_item_actions.dart'; import 'library_item_hero_section.dart'; @@ -28,33 +25,9 @@ class LibraryItemPage extends HookConsumerWidget { final Object? extra; @override Widget build(BuildContext context, WidgetRef ref) { - final extraMap = + final additionalItemData = extra is LibraryItemExtras ? extra as LibraryItemExtras : null; - final bookDetailsCached = extraMap?.book; - final providedCacheImage = extraMap?.coverImage != null - ? Image.memory(extraMap!.coverImage!) - : null; - final itemFromApi = ref.watch(libraryItemProvider(itemId)); - - var itemBookMetadata = - itemFromApi.valueOrNull?.media.metadata.asBookMetadataExpanded; - - final useMaterialThemeOnItemPage = - ref.watch(appSettingsProvider).themeSettings.useMaterialThemeOnItemPage; - AsyncValue coverColorScheme = const AsyncValue.loading(); - if (useMaterialThemeOnItemPage) { - coverColorScheme = ref.watch( - themeOfLibraryItemProvider( - itemFromApi.valueOrNull, - brightness: Theme.of(context).brightness, - ), - ); - debugPrint('ColorScheme: ${coverColorScheme.valueOrNull}'); - } else { - debugPrint('useMaterialThemeOnItemPage is false'); - // AsyncValue coverColorScheme = const AsyncValue.loading(); - } return ThemeProvider( initTheme: Theme.of(context), duration: 200.ms, @@ -67,40 +40,20 @@ class LibraryItemPage extends HookConsumerWidget { padding: const EdgeInsets.all(8), sliver: LibraryItemHeroSection( itemId: itemId, - extraMap: extraMap, - providedCacheImage: providedCacheImage, - item: itemFromApi, - itemBookMetadata: itemBookMetadata, - bookDetailsCached: bookDetailsCached, - coverColorScheme: coverColorScheme, + extraMap: additionalItemData, ), ), // a horizontal display with dividers of metadata SliverToBoxAdapter( - child: itemFromApi.valueOrNull != null - ? LibraryItemMetadata( - item: itemFromApi.valueOrNull!, - itemBookMetadata: itemBookMetadata, - bookDetailsCached: bookDetailsCached, - ) - : const SizedBox.shrink(), + child: LibraryItemMetadata(id: itemId), ), // a row of actions like play, download, share, etc SliverToBoxAdapter( - child: itemFromApi.valueOrNull != null - ? LibraryItemActions(item: itemFromApi.valueOrNull!) - : const SizedBox.shrink(), + child: LibraryItemActions(id: itemId), ), // a expandable section for book description SliverToBoxAdapter( - child: - itemFromApi.valueOrNull?.media.metadata.description != null - ? ExpandableDescription( - title: 'About the Book', - content: itemFromApi - .valueOrNull!.media.metadata.description!, - ) - : const SizedBox.shrink(), + child: LibraryItemDescription(id: itemId), ), // a padding at the bottom to make sure the last item is not hidden by mini player const SliverToBoxAdapter( @@ -114,6 +67,26 @@ class LibraryItemPage extends HookConsumerWidget { } } +class LibraryItemDescription extends HookConsumerWidget { + const LibraryItemDescription({ + super.key, + required this.id, + }); + + final String id; + @override + Widget build(BuildContext context, WidgetRef ref) { + final item = ref.watch(libraryItemProvider(id)).valueOrNull; + if (item == null) { + return const SizedBox(); + } + return ExpandableDescription( + title: 'About the Book', + content: item.media.metadata.description ?? 'Sorry, no description found', + ); + } +} + /// Calculate the width of the book cover based on the screen size double calculateWidth( BuildContext context, diff --git a/lib/features/player/view/audiobook_player.dart b/lib/features/player/view/audiobook_player.dart index f227342..46ed7aa 100644 --- a/lib/features/player/view/audiobook_player.dart +++ b/lib/features/player/view/audiobook_player.dart @@ -36,7 +36,7 @@ class AudiobookPlayer extends HookConsumerWidget { final player = ref.watch(audiobookPlayerProvider); final imageOfItemBeingPlayed = itemBeingPlayed.valueOrNull != null ? ref.watch( - coverImageProvider(itemBeingPlayed.valueOrNull!), + coverImageProvider(itemBeingPlayed.valueOrNull!.id), ) : null; final imgWidget = imageOfItemBeingPlayed?.valueOrNull != null @@ -63,7 +63,7 @@ class AudiobookPlayer extends HookConsumerWidget { // theme from image final imageTheme = ref.watch( themeOfLibraryItemProvider( - itemBeingPlayed.valueOrNull, + itemBeingPlayed.valueOrNull?.id, brightness: Theme.of(context).brightness, ), ); diff --git a/lib/router/models/library_item_extras.dart b/lib/router/models/library_item_extras.dart index 089d649..0d50040 100644 --- a/lib/router/models/library_item_extras.dart +++ b/lib/router/models/library_item_extras.dart @@ -1,7 +1,5 @@ // a freezed class to store the settings of the app -import 'dart:typed_data'; - import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:shelfsdk/audiobookshelf_api.dart'; @@ -17,7 +15,6 @@ class LibraryItemExtras with _$LibraryItemExtras { const factory LibraryItemExtras({ BookMinified? book, @Default('') String heroTagSuffix, - Uint8List? coverImage, }) = _LibraryItemExtras; } diff --git a/lib/router/models/library_item_extras.freezed.dart b/lib/router/models/library_item_extras.freezed.dart index 00c6385..900fdec 100644 --- a/lib/router/models/library_item_extras.freezed.dart +++ b/lib/router/models/library_item_extras.freezed.dart @@ -18,7 +18,6 @@ final _privateConstructorUsedError = UnsupportedError( mixin _$LibraryItemExtras { BookMinified? get book => throw _privateConstructorUsedError; String get heroTagSuffix => throw _privateConstructorUsedError; - Uint8List? get coverImage => throw _privateConstructorUsedError; /// Create a copy of LibraryItemExtras /// with the given fields replaced by the non-null parameter values. @@ -33,7 +32,7 @@ abstract class $LibraryItemExtrasCopyWith<$Res> { LibraryItemExtras value, $Res Function(LibraryItemExtras) then) = _$LibraryItemExtrasCopyWithImpl<$Res, LibraryItemExtras>; @useResult - $Res call({BookMinified? book, String heroTagSuffix, Uint8List? coverImage}); + $Res call({BookMinified? book, String heroTagSuffix}); } /// @nodoc @@ -53,7 +52,6 @@ class _$LibraryItemExtrasCopyWithImpl<$Res, $Val extends LibraryItemExtras> $Res call({ Object? book = freezed, Object? heroTagSuffix = null, - Object? coverImage = freezed, }) { return _then(_value.copyWith( book: freezed == book @@ -64,10 +62,6 @@ class _$LibraryItemExtrasCopyWithImpl<$Res, $Val extends LibraryItemExtras> ? _value.heroTagSuffix : heroTagSuffix // ignore: cast_nullable_to_non_nullable as String, - coverImage: freezed == coverImage - ? _value.coverImage - : coverImage // ignore: cast_nullable_to_non_nullable - as Uint8List?, ) as $Val); } } @@ -80,7 +74,7 @@ abstract class _$$LibraryItemExtrasImplCopyWith<$Res> __$$LibraryItemExtrasImplCopyWithImpl<$Res>; @override @useResult - $Res call({BookMinified? book, String heroTagSuffix, Uint8List? coverImage}); + $Res call({BookMinified? book, String heroTagSuffix}); } /// @nodoc @@ -98,7 +92,6 @@ class __$$LibraryItemExtrasImplCopyWithImpl<$Res> $Res call({ Object? book = freezed, Object? heroTagSuffix = null, - Object? coverImage = freezed, }) { return _then(_$LibraryItemExtrasImpl( book: freezed == book @@ -109,10 +102,6 @@ class __$$LibraryItemExtrasImplCopyWithImpl<$Res> ? _value.heroTagSuffix : heroTagSuffix // ignore: cast_nullable_to_non_nullable as String, - coverImage: freezed == coverImage - ? _value.coverImage - : coverImage // ignore: cast_nullable_to_non_nullable - as Uint8List?, )); } } @@ -120,20 +109,17 @@ class __$$LibraryItemExtrasImplCopyWithImpl<$Res> /// @nodoc class _$LibraryItemExtrasImpl implements _LibraryItemExtras { - const _$LibraryItemExtrasImpl( - {this.book, this.heroTagSuffix = '', this.coverImage}); + const _$LibraryItemExtrasImpl({this.book, this.heroTagSuffix = ''}); @override final BookMinified? book; @override @JsonKey() final String heroTagSuffix; - @override - final Uint8List? coverImage; @override String toString() { - return 'LibraryItemExtras(book: $book, heroTagSuffix: $heroTagSuffix, coverImage: $coverImage)'; + return 'LibraryItemExtras(book: $book, heroTagSuffix: $heroTagSuffix)'; } @override @@ -143,14 +129,11 @@ class _$LibraryItemExtrasImpl implements _LibraryItemExtras { other is _$LibraryItemExtrasImpl && (identical(other.book, book) || other.book == book) && (identical(other.heroTagSuffix, heroTagSuffix) || - other.heroTagSuffix == heroTagSuffix) && - const DeepCollectionEquality() - .equals(other.coverImage, coverImage)); + other.heroTagSuffix == heroTagSuffix)); } @override - int get hashCode => Object.hash(runtimeType, book, heroTagSuffix, - const DeepCollectionEquality().hash(coverImage)); + int get hashCode => Object.hash(runtimeType, book, heroTagSuffix); /// Create a copy of LibraryItemExtras /// with the given fields replaced by the non-null parameter values. @@ -165,15 +148,12 @@ class _$LibraryItemExtrasImpl implements _LibraryItemExtras { abstract class _LibraryItemExtras implements LibraryItemExtras { const factory _LibraryItemExtras( {final BookMinified? book, - final String heroTagSuffix, - final Uint8List? coverImage}) = _$LibraryItemExtrasImpl; + final String heroTagSuffix}) = _$LibraryItemExtrasImpl; @override BookMinified? get book; @override String get heroTagSuffix; - @override - Uint8List? get coverImage; /// Create a copy of LibraryItemExtras /// with the given fields replaced by the non-null parameter values. diff --git a/lib/shared/widgets/shelves/book_shelf.dart b/lib/shared/widgets/shelves/book_shelf.dart index e4d264a..692d3b3 100644 --- a/lib/shared/widgets/shelves/book_shelf.dart +++ b/lib/shared/widgets/shelves/book_shelf.dart @@ -8,8 +8,7 @@ import 'package:shelfsdk/audiobookshelf_api.dart'; import 'package:shimmer/shimmer.dart' show Shimmer; import 'package:vaani/api/api_provider.dart'; import 'package:vaani/api/image_provider.dart'; -import 'package:vaani/api/library_item_provider.dart' - show libraryItemProvider; +import 'package:vaani/api/library_item_provider.dart' show libraryItemProvider; import 'package:vaani/constants/hero_tag_conventions.dart'; import 'package:vaani/features/item_viewer/view/library_item_actions.dart'; import 'package:vaani/features/player/providers/audiobook_player.dart'; @@ -72,7 +71,7 @@ class BookOnShelf extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final book = item.media.asBookMinified; final metadata = book.metadata.asBookMetadataMinified; - final coverImage = ref.watch(coverImageProvider(item)); + final coverImage = ref.watch(coverImageProvider(item.id)); return LayoutBuilder( builder: (context, constraints) { final height = min(constraints.maxHeight, 500); @@ -87,7 +86,6 @@ class BookOnShelf extends HookConsumerWidget { extra: LibraryItemExtras( book: book, heroTagSuffix: heroTagSuffix, - coverImage: coverImage.valueOrNull, ), ); } @@ -228,10 +226,9 @@ class _BookOnShelfPlayButton extends HookConsumerWidget { AsyncValue coverColorScheme = const AsyncValue.loading(); if (useMaterialThemeOnItemPage && isCurrentBookSetInPlayer) { - final itemFromApi = ref.watch(libraryItemProvider(libraryItemId)); coverColorScheme = ref.watch( themeOfLibraryItemProvider( - itemFromApi.valueOrNull, + libraryItemId, brightness: Theme.of(context).brightness, ), ); diff --git a/lib/theme/theme_from_cover_provider.dart b/lib/theme/theme_from_cover_provider.dart index e6bb8b6..a535f2f 100644 --- a/lib/theme/theme_from_cover_provider.dart +++ b/lib/theme/theme_from_cover_provider.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:logging/logging.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; -import 'package:shelfsdk/audiobookshelf_api.dart'; import 'package:vaani/api/image_provider.dart'; part 'theme_from_cover_provider.g.dart'; @@ -49,13 +48,13 @@ Future> themeFromCover( @Riverpod(keepAlive: true) FutureOr themeOfLibraryItem( ThemeOfLibraryItemRef ref, - LibraryItem? item, { + String? itemId, { Brightness brightness = Brightness.dark, }) async { - if (item == null) { + if (itemId == null) { return null; } - final coverImage = await ref.watch(coverImageProvider(item).future); + final coverImage = await ref.watch(coverImageProvider(itemId).future); final val = await ref.watch( themeFromCoverProvider(MemoryImage(coverImage), brightness: brightness) .future, diff --git a/lib/theme/theme_from_cover_provider.g.dart b/lib/theme/theme_from_cover_provider.g.dart index 8201917..61a86a9 100644 --- a/lib/theme/theme_from_cover_provider.g.dart +++ b/lib/theme/theme_from_cover_provider.g.dart @@ -175,7 +175,7 @@ class _ThemeFromCoverProviderElement } String _$themeOfLibraryItemHash() => - r'575a390a0ab0e66cf54cb090a358c08847270798'; + r'a1d0e5d81f4debe88d5a6ce46c3af28623ad4273'; /// See also [themeOfLibraryItem]. @ProviderFor(themeOfLibraryItem) @@ -188,11 +188,11 @@ class ThemeOfLibraryItemFamily extends Family> { /// See also [themeOfLibraryItem]. ThemeOfLibraryItemProvider call( - LibraryItem? item, { + String? itemId, { Brightness brightness = Brightness.dark, }) { return ThemeOfLibraryItemProvider( - item, + itemId, brightness: brightness, ); } @@ -202,7 +202,7 @@ class ThemeOfLibraryItemFamily extends Family> { covariant ThemeOfLibraryItemProvider provider, ) { return call( - provider.item, + provider.itemId, brightness: provider.brightness, ); } @@ -226,12 +226,12 @@ class ThemeOfLibraryItemFamily extends Family> { class ThemeOfLibraryItemProvider extends FutureProvider { /// See also [themeOfLibraryItem]. ThemeOfLibraryItemProvider( - LibraryItem? item, { + String? itemId, { Brightness brightness = Brightness.dark, }) : this._internal( (ref) => themeOfLibraryItem( ref as ThemeOfLibraryItemRef, - item, + itemId, brightness: brightness, ), from: themeOfLibraryItemProvider, @@ -243,7 +243,7 @@ class ThemeOfLibraryItemProvider extends FutureProvider { dependencies: ThemeOfLibraryItemFamily._dependencies, allTransitiveDependencies: ThemeOfLibraryItemFamily._allTransitiveDependencies, - item: item, + itemId: itemId, brightness: brightness, ); @@ -254,11 +254,11 @@ class ThemeOfLibraryItemProvider extends FutureProvider { required super.allTransitiveDependencies, required super.debugGetCreateSourceHash, required super.from, - required this.item, + required this.itemId, required this.brightness, }) : super.internal(); - final LibraryItem? item; + final String? itemId; final Brightness brightness; @override @@ -274,7 +274,7 @@ class ThemeOfLibraryItemProvider extends FutureProvider { dependencies: null, allTransitiveDependencies: null, debugGetCreateSourceHash: null, - item: item, + itemId: itemId, brightness: brightness, ), ); @@ -288,14 +288,14 @@ class ThemeOfLibraryItemProvider extends FutureProvider { @override bool operator ==(Object other) { return other is ThemeOfLibraryItemProvider && - other.item == item && + other.itemId == itemId && other.brightness == brightness; } @override int get hashCode { var hash = _SystemHash.combine(0, runtimeType.hashCode); - hash = _SystemHash.combine(hash, item.hashCode); + hash = _SystemHash.combine(hash, itemId.hashCode); hash = _SystemHash.combine(hash, brightness.hashCode); return _SystemHash.finish(hash); @@ -303,8 +303,8 @@ class ThemeOfLibraryItemProvider extends FutureProvider { } mixin ThemeOfLibraryItemRef on FutureProviderRef { - /// The parameter `item` of this provider. - LibraryItem? get item; + /// The parameter `itemId` of this provider. + String? get itemId; /// The parameter `brightness` of this provider. Brightness get brightness; @@ -315,7 +315,7 @@ class _ThemeOfLibraryItemProviderElement _ThemeOfLibraryItemProviderElement(super.provider); @override - LibraryItem? get item => (origin as ThemeOfLibraryItemProvider).item; + String? get itemId => (origin as ThemeOfLibraryItemProvider).itemId; @override Brightness get brightness => (origin as ThemeOfLibraryItemProvider).brightness; From a5ec573a76d83c0f7655262df9063cdfe8d07c5e Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Mon, 23 Sep 2024 03:57:15 -0400 Subject: [PATCH 09/92] chore: bump version to 0.0.5+1 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 8a659a7..17f7b22 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.0.4+1 +version: 0.0.5+1 environment: sdk: ">=3.3.4 <4.0.0" From 84e5fd9d8159bf1da23f9b375e2186b072e4b76a Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Mon, 23 Sep 2024 04:28:08 -0400 Subject: [PATCH 10/92] refactor: clamp download progress value to start from .05 --- .../view/library_item_actions.dart | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/lib/features/item_viewer/view/library_item_actions.dart b/lib/features/item_viewer/view/library_item_actions.dart index 7bc4c9c..f1eec3d 100644 --- a/lib/features/item_viewer/view/library_item_actions.dart +++ b/lib/features/item_viewer/view/library_item_actions.dart @@ -222,21 +222,21 @@ class LibItemDownloadButton extends HookConsumerWidget { final isItemDownloading = ref.watch(isItemDownloadingProvider(item.id)); return isItemDownloading - ? ItemCurrentlyInDownloadQueue( - item: item, - ) - : IconButton( - onPressed: () { - appLogger.fine('Pressed download button'); + ? ItemCurrentlyInDownloadQueue( + item: item, + ) + : IconButton( + onPressed: () { + appLogger.fine('Pressed download button'); - ref - .read(downloadManagerProvider.notifier) - .queueAudioBookDownload(item); - }, - icon: const Icon( - Icons.download_rounded, - ), - ); + ref + .read(downloadManagerProvider.notifier) + .queueAudioBookDownload(item); + }, + icon: const Icon( + Icons.download_rounded, + ), + ); } } @@ -250,8 +250,10 @@ class ItemCurrentlyInDownloadQueue extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final progress = - ref.watch(itemDownloadProgressProvider(item.id)).valueOrNull; + final progress = ref + .watch(itemDownloadProgressProvider(item.id)) + .valueOrNull + ?.clamp(0.05, 1.0); if (progress == 1) { return AlreadyItemDownloadedButton(item: item); From bf53ec92993c09dc91e284c8038d631391a74aed Mon Sep 17 00:00:00 2001 From: "Dr.Blank" Date: Tue, 24 Sep 2024 00:17:36 -0400 Subject: [PATCH 11/92] fix android notification icon missing for media playback (#25) --- lib/main.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/main.dart b/lib/main.dart index 381d27f..cbf2737 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -46,6 +46,7 @@ void main() async { androidNotificationChannelId: 'com.vaani.bg_demo.channel.audio', androidNotificationChannelName: 'Audio playback', androidNotificationOngoing: true, + androidNotificationIcon: 'mipmap/launcher_icon', ); // run the app From 721b0a87fc38c0abb9c42a8c6cc13c75bc496c16 Mon Sep 17 00:00:00 2001 From: "Dr.Blank" Date: Wed, 25 Sep 2024 02:58:33 -0400 Subject: [PATCH 12/92] feat: enhance navigation handling by adding debug messages and settings page routing (#29) --- lib/router/scaffold_with_nav_bar.dart | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/router/scaffold_with_nav_bar.dart b/lib/router/scaffold_with_nav_bar.dart index 2fea966..467ec71 100644 --- a/lib/router/scaffold_with_nav_bar.dart +++ b/lib/router/scaffold_with_nav_bar.dart @@ -6,6 +6,7 @@ import 'package:vaani/features/explore/providers/search_controller.dart'; import 'package:vaani/features/player/providers/player_form.dart'; import 'package:vaani/features/player/view/audiobook_player.dart'; import 'package:vaani/features/player/view/player_when_expanded.dart'; +import 'package:vaani/router/router.dart'; // stack to track changes in navigationShell.currentIndex // home is always at index 0 and at the start and should be the last before popping @@ -153,6 +154,8 @@ class ScaffoldWithNavBar extends HookConsumerWidget { // Check if the current branch is the same as the branch that was tapped. // If it is, debugPrint a message to the console. if (index == navigationShell.currentIndex) { + debugPrint('Tapped the current branch'); + // if current branch is explore, open the search view if (index == 2) { final searchController = ref.read(globalSearchControllerProvider); @@ -163,7 +166,14 @@ class ScaffoldWithNavBar extends HookConsumerWidget { searchController.closeView(null); } } - debugPrint('Tapped the current branch'); + + // open settings page if the current branch is you + if (index == 3) { + // do not open settings page if it is already open + if (GoRouterState.of(context).topRoute?.name != Routes.settings.name) { + GoRouter.of(context).pushNamed(Routes.settings.name); + } + } } } } From 3cf0a0b1244f0ccd154153a05046a2f727a8ec31 Mon Sep 17 00:00:00 2001 From: "Dr.Blank" Date: Wed, 25 Sep 2024 03:13:42 -0400 Subject: [PATCH 13/92] feat: extensive settings for media controls through notification (#28) * feat: add notification settings customisation options * feat: add notification settings page and update routing --- .../ic_stat_notification_logo.png | Bin 0 -> 1139 bytes .../ic_stat_notification_logo.png | Bin 0 -> 743 bytes .../ic_stat_notification_logo.png | Bin 0 -> 1741 bytes .../ic_stat_notification_logo.png | Bin 0 -> 2519 bytes .../ic_stat_notification_logo.png | Bin 0 -> 3869 bytes .../player/core/audiobook_player.dart | 51 +- lib/features/player/core/init.dart | 62 +++ lib/main.dart | 21 +- lib/router/constants.dart | 9 +- lib/router/router.dart | 26 +- lib/settings/app_settings_provider.dart | 22 +- lib/settings/app_settings_provider.g.dart | 2 +- lib/settings/models/app_settings.dart | 52 ++ lib/settings/models/app_settings.freezed.dart | 343 +++++++++++- lib/settings/models/app_settings.g.dart | 52 ++ lib/settings/view/app_settings_page.dart | 494 +++++++++--------- .../view/auto_sleep_timer_settings_page.dart | 157 +++--- .../view/notification_settings_page.dart | 404 ++++++++++++++ lib/settings/view/simple_settings_page.dart | 53 ++ pubspec.lock | 11 +- pubspec.yaml | 8 +- 21 files changed, 1391 insertions(+), 376 deletions(-) create mode 100644 android/app/src/main/res/drawable-hdpi/ic_stat_notification_logo.png create mode 100644 android/app/src/main/res/drawable-mdpi/ic_stat_notification_logo.png create mode 100644 android/app/src/main/res/drawable-xhdpi/ic_stat_notification_logo.png create mode 100644 android/app/src/main/res/drawable-xxhdpi/ic_stat_notification_logo.png create mode 100644 android/app/src/main/res/drawable-xxxhdpi/ic_stat_notification_logo.png create mode 100644 lib/features/player/core/init.dart create mode 100644 lib/settings/view/notification_settings_page.dart create mode 100644 lib/settings/view/simple_settings_page.dart diff --git a/android/app/src/main/res/drawable-hdpi/ic_stat_notification_logo.png b/android/app/src/main/res/drawable-hdpi/ic_stat_notification_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b2ccfefbb76bc96838fa03fd96fd0cab2bab31e4 GIT binary patch literal 1139 zcmV-(1dRKMP)9LGJ|jFL6k3z=jv!;F6q9%+aCBb8eu{f0hFA;0XqUjRS$e zmq@;_OTg}jo1G^h9CgP@F&cowXI6*QrBl9$+EDjCTxZy&Qg;a@WA`MSomZfdI4DAs zakkF}G?em51L%zl&OPatumFvutYgSA zh5hVtkVA`&NF%vx14^Jg7{?{pRUI9?tBR0-tUY4ao3f&@mbyGYK!WXubRf2}0@*t9 z3e-i@hYA526E%>n)7Bn<+G=``*41%3t+e?_q^zx?n7V01Oas=mmr~Yx3#F3q|4RSaL&TO}*c?!?aHN*`Hn4Z*YBh+mm z9eW+l5tC;i1FA7kO`o9Fqj_N#u|DUsNC#&sHn$^^7zR-RnNAtKMy{hEo6dIHJEK0E zcUt^=sn7HZBRju9`i!+5Xv0jR(+X>+0O|isx5}n&`;rr=FCb(3balOq?$c>sOY{oJ z>uQ_Dd+l9OCEq{>)MB2?P$r#+ejtg?4IY0f_lb(cFpd>Sw*Vahx)bS=ubZU6mIJh; z)`5(On0Mu^lr?q9s2M;y+oDb}MaTe>58ZQga4Ho5qiOV&Vg@pxhVeA7D=7fo@?P)vF2gt5 z^SlR&p+A-Cq`>ya9fxl&{q=AY->B=$CUBO(1q`S(f$7w}PzrNkFc3nZn0^~<$M!3! zz-a=D8L%}%pat7Ge0}DdaDnqo+>XG9umJtl$`s!>`Tp4=(rw0m8}`C7*aEe15AMP$ zxB#s-UR#nEY!UTCs6pUOoWN@w7vU@HfsHT>yP+O7z%3I#Os#mGjeiEv1=R@19+|;& z?APEkD2q+-6Li?eOh6gRUI(v20(a;)Bk(e*z%~NE*u-Z-0$TA9JaIBuOuG+(A8`U& zU5|pC3@+0?1W!W(Gw6?iuJBc;U}9yPDN%=9gm)&CNPqzqistZxcTi6E6g1)cZoWm- zx&&(#3i&XAKkW-JIETtVOpKjo)1JEm)9Al|HK6#ECa_rfmcT5~4O6B^@&9%ObW0jQ zw?{WZ-@$QE+5;>i*93;>>l?`w`zm%}&~@&BR$@{L$ZQcoYAaQ3i4N~Q41yk1%KSQq zkMwm@{DOTUm9Dk^pi9v0{zp+~Alq`d54y|RCjV9H!*f46`URM;gATSTSal{fHv`vb zlj*RpKtD8Un<8TLC#`_W@a+j=V}DZov!gtQk0~)w}4{ika{clQ+@c2P=aYJMIh|k^Qs}!aC4jrK_l{ zvX(>{*jDLFeg^s)=EG71)Segt6VdCw0S!#9$2ew5oPi1GHJ^|O0&mBhoq+!mNHSqK Z<}YeL8YrT5KlK0r002ovPDHLkV1ie0Sik@P literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-xhdpi/ic_stat_notification_logo.png b/android/app/src/main/res/drawable-xhdpi/ic_stat_notification_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..753dbe0c3a67ff72d54481eb14abdc23cb329f22 GIT binary patch literal 1741 zcmV;;1~U1HP)4!6^*#WD)`>w=r_Ao~98wv+Ik1rXzv=hRIn-U z?@LXHZ=HZ1?_kgaxfg08K!*~X1Wp8_>0mK+yYQ@=I{=(c-TWZepLaLmcoqfxi6_a2&Xd!6%2=m+0s~U}7Nw>U6cUz(6pU zHvRd2D9^71bafT#MPOo3Tm_tAQ;3H_Z!nI5Cj|o9>ZRZs>L!#Bc#3)>tgh4uJB9B( zczzzd29BsF0e$xs-~n(!1p+toZ4|f?Wg06G7{T|c1q5ED&5;QRoPo@v$QG3(n>Y!9 zyjh(fNd}r;1A)R7xRCaDfm|v9HU;w}2(G2ytLsG|?=8ABzkx`&XqMqlmLNIMla8=ATN6`;9j4 z0nNmA+PwL{jHOD2STe&I2fAkS9!b<(QW40H z5=_9DpqKHIcPxtJ4(JtT-ZAw!dNEz&CA9Ihm#VagKv)euhyl$*x~a!eD3r@#q6(z9 zrrtxoskd3~VB~*Jr9F*WOdyc(u1J&U20UeH&ykrV1U%U5!8}*&iQK1YmA73c1Of@e zzwXdKKinI`OQSE!dri0;nCE!CqA9hgWJVy6IFny(TTj&s1z*f-7dHNVyq^oqX-q-N z&bYO*$(n#sdNLRZR-&M3L9Rf+>v(s5$3 z)Y)JP_!aoiPSw*^5+d~=p!t|VP5`C^eSv3O|3~m(qKOTwl%OS1JTH?ufv^f4`So1u zuN&J8_ATIe9Z}xvluSxp2m}(InY~r>bY)yP9Lzv@)AP(qJqg&iCn?RwV#?rwzUF+V z65F~F2&K41w1yzI)f j)RjP{n#Oe2>IwV@0Tn%7>Ek}!00000NkvXXu0mjfd)6v$ literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-xxhdpi/ic_stat_notification_logo.png b/android/app/src/main/res/drawable-xxhdpi/ic_stat_notification_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..fee76705b0746649b7198162f279ea5314479597 GIT binary patch literal 2519 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 literal 0 HcmV?d00001 diff --git a/lib/features/player/core/audiobook_player.dart b/lib/features/player/core/audiobook_player.dart index 106a547..6fe3bfa 100644 --- a/lib/features/player/core/audiobook_player.dart +++ b/lib/features/player/core/audiobook_player.dart @@ -8,6 +8,9 @@ import 'package:just_audio/just_audio.dart'; import 'package:just_audio_background/just_audio_background.dart'; import 'package:logging/logging.dart'; import 'package:shelfsdk/audiobookshelf_api.dart'; +import 'package:vaani/settings/app_settings_provider.dart'; +import 'package:vaani/settings/models/app_settings.dart'; +import 'package:vaani/shared/extensions/model_conversions.dart'; final _logger = Logger('AudiobookPlayer'); @@ -81,6 +84,7 @@ class AudiobookPlayer extends AudioPlayer { List? downloadedUris, Uri? artworkUri, }) async { + final appSettings = loadOrCreateAppSettings(); // if the book is null, stop the player if (book == null) { _book = null; @@ -128,8 +132,10 @@ class AudiobookPlayer extends AudioPlayer { // Specify a unique ID for each media item: id: book.libraryItemId + track.index.toString(), // Metadata to display in the notification: - album: book.metadata.title, - title: book.metadata.title ?? track.title, + title: appSettings.notificationSettings.primaryTitle + .formatNotificationTitle(book), + album: appSettings.notificationSettings.secondaryTitle + .formatNotificationTitle(book), artUri: artworkUri ?? Uri.parse( '$baseUrl/api/items/${book.libraryItemId}/cover?token=$token&width=800', @@ -198,7 +204,7 @@ class AudiobookPlayer extends AudioPlayer { @override Stream get positionStream { - // return the positioninbook stream + // return the positionInBook stream return super.positionStream.map((position) { if (_book == null) { return Duration.zero; @@ -267,3 +273,42 @@ Uri _getUri( return uri ?? Uri.parse('${baseUrl.toString()}${track.contentUrl}?token=$token'); } + +extension FormatNotificationTitle on String { + String formatNotificationTitle(BookExpanded book) { + return replaceAllMapped( + RegExp(r'\$(\w+)'), + (match) { + final type = match.group(1); + return NotificationTitleType.values + .firstWhere((element) => element.stringValue == type) + .extractFrom(book) ?? + match.group(0) ?? + ''; + }, + ); + } +} + +extension NotificationTitleUtils on NotificationTitleType { + String? extractFrom(BookExpanded book) { + var bookMetadataExpanded = book.metadata.asBookMetadataExpanded; + switch (this) { + case NotificationTitleType.bookTitle: + return bookMetadataExpanded.title; + case NotificationTitleType.chapterTitle: + // TODO: implement chapter title; depends on https://github.com/Dr-Blank/Vaani/issues/2 + return bookMetadataExpanded.title; + case NotificationTitleType.author: + return bookMetadataExpanded.authorName; + case NotificationTitleType.narrator: + return bookMetadataExpanded.narratorName; + case NotificationTitleType.series: + return bookMetadataExpanded.seriesName; + case NotificationTitleType.subtitle: + return bookMetadataExpanded.subtitle; + case NotificationTitleType.year: + return bookMetadataExpanded.publishedYear; + } + } +} diff --git a/lib/features/player/core/init.dart b/lib/features/player/core/init.dart new file mode 100644 index 0000000..c61637b --- /dev/null +++ b/lib/features/player/core/init.dart @@ -0,0 +1,62 @@ +import 'package:audio_service/audio_service.dart'; +import 'package:audio_session/audio_session.dart'; +import 'package:just_audio_background/just_audio_background.dart' + show JustAudioBackground, NotificationConfig; +import 'package:just_audio_media_kit/just_audio_media_kit.dart' + show JustAudioMediaKit; +import 'package:vaani/settings/app_settings_provider.dart'; +import 'package:vaani/settings/models/app_settings.dart'; + +Future configurePlayer() async { + // for playing audio on windows, linux + JustAudioMediaKit.ensureInitialized(); + + // for configuring how this app will interact with other audio apps + final session = await AudioSession.instance; + await session.configure(const AudioSessionConfiguration.speech()); + + final appSettings = loadOrCreateAppSettings(); + + // for playing audio in the background + await JustAudioBackground.init( + androidNotificationChannelId: 'com.vaani.bg_demo.channel.audio', + androidNotificationChannelName: 'Audio playback', + androidNotificationOngoing: true, + androidStopForegroundOnPause: true, + androidNotificationChannelDescription: 'Audio playback in the background', + androidNotificationIcon: 'drawable/ic_stat_notification_logo', + rewindInterval: appSettings.notificationSettings.rewindInterval, + fastForwardInterval: appSettings.notificationSettings.fastForwardInterval, + androidShowNotificationBadge: false, + notificationConfigBuilder: (state) { + final controls = [ + if (appSettings.notificationSettings.mediaControls + .contains(NotificationMediaControl.skipToPreviousChapter) && + state.hasPrevious) + MediaControl.skipToPrevious, + if (appSettings.notificationSettings.mediaControls + .contains(NotificationMediaControl.rewind)) + MediaControl.rewind, + if (state.playing) MediaControl.pause else MediaControl.play, + if (appSettings.notificationSettings.mediaControls + .contains(NotificationMediaControl.fastForward)) + MediaControl.fastForward, + if (appSettings.notificationSettings.mediaControls + .contains(NotificationMediaControl.skipToNextChapter) && + state.hasNext) + MediaControl.skipToNext, + if (appSettings.notificationSettings.mediaControls + .contains(NotificationMediaControl.stop)) + MediaControl.stop, + ]; + return NotificationConfig( + controls: controls, + systemActions: const { + MediaAction.seek, + MediaAction.seekForward, + MediaAction.seekBackward, + }, + ); + }, + ); +} diff --git a/lib/main.dart b/lib/main.dart index cbf2737..cea6f7f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,15 +1,11 @@ -import 'package:audio_session/audio_session.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:just_audio_background/just_audio_background.dart' - show JustAudioBackground; -import 'package:just_audio_media_kit/just_audio_media_kit.dart' - show JustAudioMediaKit; import 'package:logging/logging.dart'; import 'package:vaani/api/server_provider.dart'; import 'package:vaani/db/storage.dart'; import 'package:vaani/features/downloads/providers/download_manager.dart'; import 'package:vaani/features/playback_reporting/providers/playback_reporter_provider.dart'; +import 'package:vaani/features/player/core/init.dart'; import 'package:vaani/features/player/providers/audiobook_player.dart'; import 'package:vaani/features/sleep_timer/providers/sleep_timer_provider.dart'; import 'package:vaani/router/router.dart'; @@ -31,23 +27,12 @@ void main() async { ); }); - // for playing audio on windows, linux - JustAudioMediaKit.ensureInitialized(); - // initialize the storage await initStorage(); - // for configuring how this app will interact with other audio apps - final session = await AudioSession.instance; - await session.configure(const AudioSessionConfiguration.speech()); + // initialize audio player + await configurePlayer(); - // for playing audio in the background - await JustAudioBackground.init( - androidNotificationChannelId: 'com.vaani.bg_demo.channel.audio', - androidNotificationChannelName: 'Audio playback', - androidNotificationOngoing: true, - androidNotificationIcon: 'mipmap/launcher_icon', - ); // run the app runApp( diff --git a/lib/router/constants.dart b/lib/router/constants.dart index 5073e60..9dd15ad 100644 --- a/lib/router/constants.dart +++ b/lib/router/constants.dart @@ -28,9 +28,14 @@ class Routes { name: 'settings', ); static const autoSleepTimerSettings = _SimpleRoute( - pathName: 'autosleeptimer', + pathName: 'autoSleepTimer', name: 'autoSleepTimerSettings', - // parentRoute: settings, + parentRoute: settings, + ); + static const notificationSettings = _SimpleRoute( + pathName: 'notifications', + name: 'notificationSettings', + parentRoute: settings, ); // search and explore diff --git a/lib/router/router.dart b/lib/router/router.dart index b3085ee..8781e6f 100644 --- a/lib/router/router.dart +++ b/lib/router/router.dart @@ -12,6 +12,7 @@ import 'package:vaani/features/you/view/you_page.dart'; import 'package:vaani/pages/home_page.dart'; import 'package:vaani/settings/view/app_settings_page.dart'; import 'package:vaani/settings/view/auto_sleep_timer_settings_page.dart'; +import 'package:vaani/settings/view/notification_settings_page.dart'; import 'scaffold_with_nav_bar.dart'; import 'transitions/slide.dart'; @@ -172,15 +173,22 @@ class MyAppRouter { name: Routes.settings.name, // builder: (context, state) => const AppSettingsPage(), pageBuilder: defaultPageBuilder(const AppSettingsPage()), - ), - GoRoute( - path: Routes.autoSleepTimerSettings.localPath, - name: Routes.autoSleepTimerSettings.name, - // builder: (context, state) => - // const AutoSleepTimerSettingsPage(), - pageBuilder: defaultPageBuilder( - const AutoSleepTimerSettingsPage(), - ), + routes: [ + 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.userManagement.localPath, diff --git a/lib/settings/app_settings_provider.dart b/lib/settings/app_settings_provider.dart index b23d18d..662a043 100644 --- a/lib/settings/app_settings_provider.dart +++ b/lib/settings/app_settings_provider.dart @@ -11,25 +11,29 @@ final _box = AvailableHiveBoxes.userPrefsBox; final _logger = Logger('AppSettingsProvider'); -model.AppSettings readFromBoxOrCreate() { +model.AppSettings loadOrCreateAppSettings() { // see if the settings are already in the box + model.AppSettings? settings; if (_box.isNotEmpty) { - final foundSettings = _box.getAt(0); - _logger.fine('found settings in box: $foundSettings'); - return foundSettings; + try { + settings = _box.getAt(0); + _logger.fine('found settings in box: $settings'); + } catch (e) { + _logger.warning('error reading settings from box: $e' + '\nclearing box'); + _box.clear(); + } } else { - // create a new settings object - const settings = model.AppSettings(); - _logger.fine('created new settings: $settings'); - return settings; + _logger.fine('no settings found in box, creating new settings'); } + return settings ?? const model.AppSettings(); } @Riverpod(keepAlive: true) class AppSettings extends _$AppSettings { @override model.AppSettings build() { - state = readFromBoxOrCreate(); + state = loadOrCreateAppSettings(); ref.listenSelf((_, __) { writeToBox(); }); diff --git a/lib/settings/app_settings_provider.g.dart b/lib/settings/app_settings_provider.g.dart index 4956783..2f321ee 100644 --- a/lib/settings/app_settings_provider.g.dart +++ b/lib/settings/app_settings_provider.g.dart @@ -6,7 +6,7 @@ part of 'app_settings_provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$appSettingsHash() => r'e0e132b782b97f11d9791d4f1e45bf4ee67dd99b'; +String _$appSettingsHash() => r'f51d55f117692d4fb9f4b4febf02906c0953d334'; /// See also [AppSettings]. @ProviderFor(AppSettings) diff --git a/lib/settings/models/app_settings.dart b/lib/settings/models/app_settings.dart index 0591e9f..cc4506b 100644 --- a/lib/settings/models/app_settings.dart +++ b/lib/settings/models/app_settings.dart @@ -1,5 +1,6 @@ // a freezed class to store the settings of the app +import 'package:flutter/material.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'app_settings.freezed.dart'; @@ -14,6 +15,7 @@ class AppSettings with _$AppSettings { @Default(ThemeSettings()) ThemeSettings themeSettings, @Default(PlayerSettings()) PlayerSettings playerSettings, @Default(DownloadSettings()) DownloadSettings downloadSettings, + @Default(NotificationSettings()) NotificationSettings notificationSettings, }) = _AppSettings; factory AppSettings.fromJson(Map json) => @@ -133,3 +135,53 @@ class DownloadSettings with _$DownloadSettings { factory DownloadSettings.fromJson(Map json) => _$DownloadSettingsFromJson(json); } + +@freezed +class NotificationSettings with _$NotificationSettings { + const factory NotificationSettings({ + @Default(Duration(seconds: 30)) Duration fastForwardInterval, + @Default(Duration(seconds: 10)) Duration rewindInterval, + @Default(true) bool progressBarIsChapterProgress, + @Default('\$bookTitle') String primaryTitle, + @Default('\$author') String secondaryTitle, + @Default( + [ + NotificationMediaControl.rewind, + NotificationMediaControl.fastForward, + NotificationMediaControl.skipToPreviousChapter, + NotificationMediaControl.skipToNextChapter, + ], + ) + List mediaControls, + }) = _NotificationSettings; + + factory NotificationSettings.fromJson(Map json) => + _$NotificationSettingsFromJson(json); +} + +enum NotificationTitleType { + chapterTitle('chapterTitle'), + bookTitle('bookTitle'), + author('author'), + subtitle('subtitle'), + series('series'), + narrator('narrator'), + year('year'); + + const NotificationTitleType(this.stringValue); + + final String stringValue; +} + +enum NotificationMediaControl { + fastForward(Icons.fast_forward), + rewind(Icons.fast_rewind), + speedToggle(Icons.speed), + stop(Icons.stop), + skipToNextChapter(Icons.skip_next), + skipToPreviousChapter(Icons.skip_previous); + + const NotificationMediaControl(this.icon); + + final IconData icon; +} diff --git a/lib/settings/models/app_settings.freezed.dart b/lib/settings/models/app_settings.freezed.dart index 90d2cd2..204d314 100644 --- a/lib/settings/models/app_settings.freezed.dart +++ b/lib/settings/models/app_settings.freezed.dart @@ -23,6 +23,8 @@ mixin _$AppSettings { ThemeSettings get themeSettings => throw _privateConstructorUsedError; PlayerSettings get playerSettings => throw _privateConstructorUsedError; DownloadSettings get downloadSettings => throw _privateConstructorUsedError; + NotificationSettings get notificationSettings => + throw _privateConstructorUsedError; /// Serializes this AppSettings to a JSON map. Map toJson() => throw _privateConstructorUsedError; @@ -43,11 +45,13 @@ abstract class $AppSettingsCopyWith<$Res> { $Res call( {ThemeSettings themeSettings, PlayerSettings playerSettings, - DownloadSettings downloadSettings}); + DownloadSettings downloadSettings, + NotificationSettings notificationSettings}); $ThemeSettingsCopyWith<$Res> get themeSettings; $PlayerSettingsCopyWith<$Res> get playerSettings; $DownloadSettingsCopyWith<$Res> get downloadSettings; + $NotificationSettingsCopyWith<$Res> get notificationSettings; } /// @nodoc @@ -68,6 +72,7 @@ class _$AppSettingsCopyWithImpl<$Res, $Val extends AppSettings> Object? themeSettings = null, Object? playerSettings = null, Object? downloadSettings = null, + Object? notificationSettings = null, }) { return _then(_value.copyWith( themeSettings: null == themeSettings @@ -82,6 +87,10 @@ class _$AppSettingsCopyWithImpl<$Res, $Val extends AppSettings> ? _value.downloadSettings : downloadSettings // ignore: cast_nullable_to_non_nullable as DownloadSettings, + notificationSettings: null == notificationSettings + ? _value.notificationSettings + : notificationSettings // ignore: cast_nullable_to_non_nullable + as NotificationSettings, ) as $Val); } @@ -114,6 +123,17 @@ class _$AppSettingsCopyWithImpl<$Res, $Val extends AppSettings> return _then(_value.copyWith(downloadSettings: value) as $Val); }); } + + /// Create a copy of AppSettings + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $NotificationSettingsCopyWith<$Res> get notificationSettings { + return $NotificationSettingsCopyWith<$Res>(_value.notificationSettings, + (value) { + return _then(_value.copyWith(notificationSettings: value) as $Val); + }); + } } /// @nodoc @@ -127,7 +147,8 @@ abstract class _$$AppSettingsImplCopyWith<$Res> $Res call( {ThemeSettings themeSettings, PlayerSettings playerSettings, - DownloadSettings downloadSettings}); + DownloadSettings downloadSettings, + NotificationSettings notificationSettings}); @override $ThemeSettingsCopyWith<$Res> get themeSettings; @@ -135,6 +156,8 @@ abstract class _$$AppSettingsImplCopyWith<$Res> $PlayerSettingsCopyWith<$Res> get playerSettings; @override $DownloadSettingsCopyWith<$Res> get downloadSettings; + @override + $NotificationSettingsCopyWith<$Res> get notificationSettings; } /// @nodoc @@ -153,6 +176,7 @@ class __$$AppSettingsImplCopyWithImpl<$Res> Object? themeSettings = null, Object? playerSettings = null, Object? downloadSettings = null, + Object? notificationSettings = null, }) { return _then(_$AppSettingsImpl( themeSettings: null == themeSettings @@ -167,6 +191,10 @@ class __$$AppSettingsImplCopyWithImpl<$Res> ? _value.downloadSettings : downloadSettings // ignore: cast_nullable_to_non_nullable as DownloadSettings, + notificationSettings: null == notificationSettings + ? _value.notificationSettings + : notificationSettings // ignore: cast_nullable_to_non_nullable + as NotificationSettings, )); } } @@ -177,7 +205,8 @@ class _$AppSettingsImpl implements _AppSettings { const _$AppSettingsImpl( {this.themeSettings = const ThemeSettings(), this.playerSettings = const PlayerSettings(), - this.downloadSettings = const DownloadSettings()}); + this.downloadSettings = const DownloadSettings(), + this.notificationSettings = const NotificationSettings()}); factory _$AppSettingsImpl.fromJson(Map json) => _$$AppSettingsImplFromJson(json); @@ -191,10 +220,13 @@ class _$AppSettingsImpl implements _AppSettings { @override @JsonKey() final DownloadSettings downloadSettings; + @override + @JsonKey() + final NotificationSettings notificationSettings; @override String toString() { - return 'AppSettings(themeSettings: $themeSettings, playerSettings: $playerSettings, downloadSettings: $downloadSettings)'; + return 'AppSettings(themeSettings: $themeSettings, playerSettings: $playerSettings, downloadSettings: $downloadSettings, notificationSettings: $notificationSettings)'; } @override @@ -207,13 +239,15 @@ class _$AppSettingsImpl implements _AppSettings { (identical(other.playerSettings, playerSettings) || other.playerSettings == playerSettings) && (identical(other.downloadSettings, downloadSettings) || - other.downloadSettings == downloadSettings)); + other.downloadSettings == downloadSettings) && + (identical(other.notificationSettings, notificationSettings) || + other.notificationSettings == notificationSettings)); } @JsonKey(includeFromJson: false, includeToJson: false) @override - int get hashCode => - Object.hash(runtimeType, themeSettings, playerSettings, downloadSettings); + int get hashCode => Object.hash(runtimeType, themeSettings, playerSettings, + downloadSettings, notificationSettings); /// Create a copy of AppSettings /// with the given fields replaced by the non-null parameter values. @@ -235,7 +269,8 @@ abstract class _AppSettings implements AppSettings { const factory _AppSettings( {final ThemeSettings themeSettings, final PlayerSettings playerSettings, - final DownloadSettings downloadSettings}) = _$AppSettingsImpl; + final DownloadSettings downloadSettings, + final NotificationSettings notificationSettings}) = _$AppSettingsImpl; factory _AppSettings.fromJson(Map json) = _$AppSettingsImpl.fromJson; @@ -246,6 +281,8 @@ abstract class _AppSettings implements AppSettings { PlayerSettings get playerSettings; @override DownloadSettings get downloadSettings; + @override + NotificationSettings get notificationSettings; /// Create a copy of AppSettings /// with the given fields replaced by the non-null parameter values. @@ -1935,3 +1972,293 @@ abstract class _DownloadSettings implements DownloadSettings { _$$DownloadSettingsImplCopyWith<_$DownloadSettingsImpl> get copyWith => throw _privateConstructorUsedError; } + +NotificationSettings _$NotificationSettingsFromJson(Map json) { + return _NotificationSettings.fromJson(json); +} + +/// @nodoc +mixin _$NotificationSettings { + Duration get fastForwardInterval => throw _privateConstructorUsedError; + Duration get rewindInterval => throw _privateConstructorUsedError; + bool get progressBarIsChapterProgress => throw _privateConstructorUsedError; + String get primaryTitle => throw _privateConstructorUsedError; + String get secondaryTitle => throw _privateConstructorUsedError; + List get mediaControls => + throw _privateConstructorUsedError; + + /// Serializes this NotificationSettings to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of NotificationSettings + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $NotificationSettingsCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $NotificationSettingsCopyWith<$Res> { + factory $NotificationSettingsCopyWith(NotificationSettings value, + $Res Function(NotificationSettings) then) = + _$NotificationSettingsCopyWithImpl<$Res, NotificationSettings>; + @useResult + $Res call( + {Duration fastForwardInterval, + Duration rewindInterval, + bool progressBarIsChapterProgress, + String primaryTitle, + String secondaryTitle, + List mediaControls}); +} + +/// @nodoc +class _$NotificationSettingsCopyWithImpl<$Res, + $Val extends NotificationSettings> + implements $NotificationSettingsCopyWith<$Res> { + _$NotificationSettingsCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of NotificationSettings + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? fastForwardInterval = null, + Object? rewindInterval = null, + Object? progressBarIsChapterProgress = null, + Object? primaryTitle = null, + Object? secondaryTitle = null, + Object? mediaControls = null, + }) { + return _then(_value.copyWith( + fastForwardInterval: null == fastForwardInterval + ? _value.fastForwardInterval + : fastForwardInterval // ignore: cast_nullable_to_non_nullable + as Duration, + rewindInterval: null == rewindInterval + ? _value.rewindInterval + : rewindInterval // ignore: cast_nullable_to_non_nullable + as Duration, + progressBarIsChapterProgress: null == progressBarIsChapterProgress + ? _value.progressBarIsChapterProgress + : progressBarIsChapterProgress // ignore: cast_nullable_to_non_nullable + as bool, + primaryTitle: null == primaryTitle + ? _value.primaryTitle + : primaryTitle // ignore: cast_nullable_to_non_nullable + as String, + secondaryTitle: null == secondaryTitle + ? _value.secondaryTitle + : secondaryTitle // ignore: cast_nullable_to_non_nullable + as String, + mediaControls: null == mediaControls + ? _value.mediaControls + : mediaControls // ignore: cast_nullable_to_non_nullable + as List, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$NotificationSettingsImplCopyWith<$Res> + implements $NotificationSettingsCopyWith<$Res> { + factory _$$NotificationSettingsImplCopyWith(_$NotificationSettingsImpl value, + $Res Function(_$NotificationSettingsImpl) then) = + __$$NotificationSettingsImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {Duration fastForwardInterval, + Duration rewindInterval, + bool progressBarIsChapterProgress, + String primaryTitle, + String secondaryTitle, + List mediaControls}); +} + +/// @nodoc +class __$$NotificationSettingsImplCopyWithImpl<$Res> + extends _$NotificationSettingsCopyWithImpl<$Res, _$NotificationSettingsImpl> + implements _$$NotificationSettingsImplCopyWith<$Res> { + __$$NotificationSettingsImplCopyWithImpl(_$NotificationSettingsImpl _value, + $Res Function(_$NotificationSettingsImpl) _then) + : super(_value, _then); + + /// Create a copy of NotificationSettings + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? fastForwardInterval = null, + Object? rewindInterval = null, + Object? progressBarIsChapterProgress = null, + Object? primaryTitle = null, + Object? secondaryTitle = null, + Object? mediaControls = null, + }) { + return _then(_$NotificationSettingsImpl( + fastForwardInterval: null == fastForwardInterval + ? _value.fastForwardInterval + : fastForwardInterval // ignore: cast_nullable_to_non_nullable + as Duration, + rewindInterval: null == rewindInterval + ? _value.rewindInterval + : rewindInterval // ignore: cast_nullable_to_non_nullable + as Duration, + progressBarIsChapterProgress: null == progressBarIsChapterProgress + ? _value.progressBarIsChapterProgress + : progressBarIsChapterProgress // ignore: cast_nullable_to_non_nullable + as bool, + primaryTitle: null == primaryTitle + ? _value.primaryTitle + : primaryTitle // ignore: cast_nullable_to_non_nullable + as String, + secondaryTitle: null == secondaryTitle + ? _value.secondaryTitle + : secondaryTitle // ignore: cast_nullable_to_non_nullable + as String, + mediaControls: null == mediaControls + ? _value._mediaControls + : mediaControls // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$NotificationSettingsImpl implements _NotificationSettings { + const _$NotificationSettingsImpl( + {this.fastForwardInterval = const Duration(seconds: 30), + this.rewindInterval = const Duration(seconds: 10), + this.progressBarIsChapterProgress = true, + this.primaryTitle = '\$bookTitle', + this.secondaryTitle = '\$author', + final List mediaControls = const [ + NotificationMediaControl.rewind, + NotificationMediaControl.fastForward, + NotificationMediaControl.skipToPreviousChapter, + NotificationMediaControl.skipToNextChapter + ]}) + : _mediaControls = mediaControls; + + factory _$NotificationSettingsImpl.fromJson(Map json) => + _$$NotificationSettingsImplFromJson(json); + + @override + @JsonKey() + final Duration fastForwardInterval; + @override + @JsonKey() + final Duration rewindInterval; + @override + @JsonKey() + final bool progressBarIsChapterProgress; + @override + @JsonKey() + final String primaryTitle; + @override + @JsonKey() + final String secondaryTitle; + final List _mediaControls; + @override + @JsonKey() + List get mediaControls { + if (_mediaControls is EqualUnmodifiableListView) return _mediaControls; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_mediaControls); + } + + @override + String toString() { + return 'NotificationSettings(fastForwardInterval: $fastForwardInterval, rewindInterval: $rewindInterval, progressBarIsChapterProgress: $progressBarIsChapterProgress, primaryTitle: $primaryTitle, secondaryTitle: $secondaryTitle, mediaControls: $mediaControls)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$NotificationSettingsImpl && + (identical(other.fastForwardInterval, fastForwardInterval) || + other.fastForwardInterval == fastForwardInterval) && + (identical(other.rewindInterval, rewindInterval) || + other.rewindInterval == rewindInterval) && + (identical(other.progressBarIsChapterProgress, + progressBarIsChapterProgress) || + other.progressBarIsChapterProgress == + progressBarIsChapterProgress) && + (identical(other.primaryTitle, primaryTitle) || + other.primaryTitle == primaryTitle) && + (identical(other.secondaryTitle, secondaryTitle) || + other.secondaryTitle == secondaryTitle) && + const DeepCollectionEquality() + .equals(other._mediaControls, _mediaControls)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + fastForwardInterval, + rewindInterval, + progressBarIsChapterProgress, + primaryTitle, + secondaryTitle, + const DeepCollectionEquality().hash(_mediaControls)); + + /// Create a copy of NotificationSettings + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$NotificationSettingsImplCopyWith<_$NotificationSettingsImpl> + get copyWith => + __$$NotificationSettingsImplCopyWithImpl<_$NotificationSettingsImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$NotificationSettingsImplToJson( + this, + ); + } +} + +abstract class _NotificationSettings implements NotificationSettings { + const factory _NotificationSettings( + {final Duration fastForwardInterval, + final Duration rewindInterval, + final bool progressBarIsChapterProgress, + final String primaryTitle, + final String secondaryTitle, + final List mediaControls}) = + _$NotificationSettingsImpl; + + factory _NotificationSettings.fromJson(Map json) = + _$NotificationSettingsImpl.fromJson; + + @override + Duration get fastForwardInterval; + @override + Duration get rewindInterval; + @override + bool get progressBarIsChapterProgress; + @override + String get primaryTitle; + @override + String get secondaryTitle; + @override + List get mediaControls; + + /// Create a copy of NotificationSettings + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$NotificationSettingsImplCopyWith<_$NotificationSettingsImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/settings/models/app_settings.g.dart b/lib/settings/models/app_settings.g.dart index 8986989..58aaad4 100644 --- a/lib/settings/models/app_settings.g.dart +++ b/lib/settings/models/app_settings.g.dart @@ -20,6 +20,10 @@ _$AppSettingsImpl _$$AppSettingsImplFromJson(Map json) => ? const DownloadSettings() : DownloadSettings.fromJson( json['downloadSettings'] as Map), + notificationSettings: json['notificationSettings'] == null + ? const NotificationSettings() + : NotificationSettings.fromJson( + json['notificationSettings'] as Map), ); Map _$$AppSettingsImplToJson(_$AppSettingsImpl instance) => @@ -27,6 +31,7 @@ Map _$$AppSettingsImplToJson(_$AppSettingsImpl instance) => 'themeSettings': instance.themeSettings, 'playerSettings': instance.playerSettings, 'downloadSettings': instance.downloadSettings, + 'notificationSettings': instance.notificationSettings, }; _$ThemeSettingsImpl _$$ThemeSettingsImplFromJson(Map json) => @@ -203,3 +208,50 @@ Map _$$DownloadSettingsImplToJson( 'maxConcurrentByHost': instance.maxConcurrentByHost, 'maxConcurrentByGroup': instance.maxConcurrentByGroup, }; + +_$NotificationSettingsImpl _$$NotificationSettingsImplFromJson( + Map json) => + _$NotificationSettingsImpl( + fastForwardInterval: json['fastForwardInterval'] == null + ? const Duration(seconds: 30) + : Duration( + microseconds: (json['fastForwardInterval'] as num).toInt()), + rewindInterval: json['rewindInterval'] == null + ? const Duration(seconds: 10) + : Duration(microseconds: (json['rewindInterval'] as num).toInt()), + progressBarIsChapterProgress: + json['progressBarIsChapterProgress'] as bool? ?? true, + primaryTitle: json['primaryTitle'] as String? ?? '\$bookTitle', + secondaryTitle: json['secondaryTitle'] as String? ?? '\$author', + mediaControls: (json['mediaControls'] as List?) + ?.map((e) => $enumDecode(_$NotificationMediaControlEnumMap, e)) + .toList() ?? + const [ + NotificationMediaControl.rewind, + NotificationMediaControl.fastForward, + NotificationMediaControl.skipToPreviousChapter, + NotificationMediaControl.skipToNextChapter + ], + ); + +Map _$$NotificationSettingsImplToJson( + _$NotificationSettingsImpl instance) => + { + 'fastForwardInterval': instance.fastForwardInterval.inMicroseconds, + 'rewindInterval': instance.rewindInterval.inMicroseconds, + 'progressBarIsChapterProgress': instance.progressBarIsChapterProgress, + 'primaryTitle': instance.primaryTitle, + 'secondaryTitle': instance.secondaryTitle, + 'mediaControls': instance.mediaControls + .map((e) => _$NotificationMediaControlEnumMap[e]!) + .toList(), + }; + +const _$NotificationMediaControlEnumMap = { + NotificationMediaControl.fastForward: 'fastForward', + NotificationMediaControl.rewind: 'rewind', + NotificationMediaControl.speedToggle: 'speedToggle', + NotificationMediaControl.stop: 'stop', + NotificationMediaControl.skipToNextChapter: 'skipToNextChapter', + NotificationMediaControl.skipToPreviousChapter: 'skipToPreviousChapter', +}; diff --git a/lib/settings/view/app_settings_page.dart b/lib/settings/view/app_settings_page.dart index 6cf2298..bca69fe 100644 --- a/lib/settings/view/app_settings_page.dart +++ b/lib/settings/view/app_settings_page.dart @@ -11,6 +11,7 @@ import 'package:vaani/api/server_provider.dart'; import 'package:vaani/router/router.dart'; import 'package:vaani/settings/app_settings_provider.dart'; import 'package:vaani/settings/models/app_settings.dart' as model; +import 'package:vaani/settings/view/simple_settings_page.dart'; class AppSettingsPage extends HookConsumerWidget { const AppSettingsPage({ @@ -26,253 +27,272 @@ class AppSettingsPage extends HookConsumerWidget { final serverURIController = useTextEditingController(); final sleepTimerSettings = appSettings.playerSettings.sleepTimerSettings; - return Scaffold( - appBar: AppBar( - title: const Text('App Settings'), - ), - body: SettingsList( - sections: [ - // Appearance section - SettingsSection( - margin: const EdgeInsetsDirectional.symmetric( - horizontal: 16.0, - vertical: 8.0, - ), - title: Text( - 'Appearance', - style: Theme.of(context).textTheme.titleLarge, - ), - tiles: [ - SettingsTile.switchTile( - initialValue: appSettings.themeSettings.isDarkMode, - title: const Text('Dark Mode'), - description: const Text('we all know dark mode is better'), - leading: appSettings.themeSettings.isDarkMode - ? const Icon(Icons.dark_mode) - : const Icon(Icons.light_mode), - onToggle: (value) { - ref.read(appSettingsProvider.notifier).toggleDarkMode(); - }, - ), - SettingsTile.switchTile( - initialValue: - appSettings.themeSettings.useMaterialThemeOnItemPage, - title: const Text('Adaptive Theme on Item Page'), - description: const Text( - 'get fancy with the colors on the item page at the cost of some performance', - ), - leading: appSettings.themeSettings.useMaterialThemeOnItemPage - ? const Icon(Icons.auto_fix_high) - : const Icon(Icons.auto_fix_off), - onToggle: (value) { - ref.read(appSettingsProvider.notifier).update( - appSettings.copyWith.themeSettings( - useMaterialThemeOnItemPage: value, - ), - ); - }, - ), - ], + return SimpleSettingsPage( + title: const Text('App Settings'), + sections: [ + // General section + SettingsSection( + margin: const EdgeInsetsDirectional.symmetric( + horizontal: 16.0, + vertical: 8.0, ), - - // Sleep Timer section - SettingsSection( - margin: const EdgeInsetsDirectional.symmetric( - horizontal: 16.0, - vertical: 8.0, + title: Text( + 'General', + style: Theme.of(context).textTheme.titleLarge, + ), + tiles: [ + SettingsTile( + title: const Text('Notification Media Player'), + leading: const Icon(Icons.play_lesson), + description: const Text( + 'Customize the media player in notifications', + ), + onPressed: (context) { + context.pushNamed(Routes.notificationSettings.name); + }, ), - title: Text( - 'Sleep Timer', - style: Theme.of(context).textTheme.titleLarge, + ], + ), + // Appearance section + SettingsSection( + margin: const EdgeInsetsDirectional.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + title: Text( + 'Appearance', + style: Theme.of(context).textTheme.titleLarge, + ), + tiles: [ + SettingsTile.switchTile( + initialValue: appSettings.themeSettings.isDarkMode, + title: const Text('Dark Mode'), + description: const Text('we all know dark mode is better'), + leading: appSettings.themeSettings.isDarkMode + ? const Icon(Icons.dark_mode) + : const Icon(Icons.light_mode), + onToggle: (value) { + ref.read(appSettingsProvider.notifier).toggleDarkMode(); + }, ), - tiles: [ - SettingsTile.navigation( - // initialValue: sleepTimerSettings.autoTurnOnTimer, - title: const Text('Auto Turn On Timer'), - description: const Text( - 'Automatically turn on the sleep timer based on the time of day', - ), - leading: sleepTimerSettings.autoTurnOnTimer - ? const Icon(Icons.timer) - : const Icon(Icons.timer_off), - onPressed: (context) { - // push the sleep timer settings page - context.pushNamed(Routes.autoSleepTimerSettings.name); - }, - // a switch to enable or disable the auto turn off time - trailing: IntrinsicHeight( - child: Row( - children: [ - VerticalDivider( - color: Theme.of(context).dividerColor.withOpacity(0.5), - indent: 8.0, - endIndent: 8.0, - // width: 8.0, - // thickness: 2.0, - // height: 24.0, + SettingsTile.switchTile( + initialValue: + appSettings.themeSettings.useMaterialThemeOnItemPage, + title: const Text('Adaptive Theme on Item Page'), + description: const Text( + 'get fancy with the colors on the item page at the cost of some performance', + ), + leading: appSettings.themeSettings.useMaterialThemeOnItemPage + ? const Icon(Icons.auto_fix_high) + : const Icon(Icons.auto_fix_off), + onToggle: (value) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.themeSettings( + useMaterialThemeOnItemPage: value, ), - Switch( - value: sleepTimerSettings.autoTurnOnTimer, - onChanged: (value) { - ref.read(appSettingsProvider.notifier).update( - appSettings.copyWith.playerSettings - .sleepTimerSettings( - autoTurnOnTimer: value, + ); + }, + ), + ], + ), + + // Sleep Timer section + SettingsSection( + margin: const EdgeInsetsDirectional.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + title: Text( + 'Sleep Timer', + style: Theme.of(context).textTheme.titleLarge, + ), + tiles: [ + SettingsTile.navigation( + // initialValue: sleepTimerSettings.autoTurnOnTimer, + title: const Text('Auto Turn On Timer'), + description: const Text( + 'Automatically turn on the sleep timer based on the time of day', + ), + leading: sleepTimerSettings.autoTurnOnTimer + ? const Icon(Icons.timer) + : const Icon(Icons.timer_off), + onPressed: (context) { + // push the sleep timer settings page + context.pushNamed(Routes.autoSleepTimerSettings.name); + }, + // a switch to enable or disable the auto turn off time + trailing: IntrinsicHeight( + child: Row( + children: [ + VerticalDivider( + color: Theme.of(context).dividerColor.withOpacity(0.5), + indent: 8.0, + endIndent: 8.0, + // width: 8.0, + // thickness: 2.0, + // height: 24.0, + ), + Switch( + value: sleepTimerSettings.autoTurnOnTimer, + onChanged: (value) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.playerSettings + .sleepTimerSettings( + autoTurnOnTimer: value, + ), + ); + }, + ), + ], + ), + ), + ), + ], + ), + + // Backup and Restore section + SettingsSection( + margin: const EdgeInsetsDirectional.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + title: Text( + 'Backup and Restore', + style: Theme.of(context).textTheme.titleLarge, + ), + tiles: [ + SettingsTile( + title: const Text('Copy to Clipboard'), + leading: const Icon(Icons.copy), + description: const Text( + 'Copy the app settings to the clipboard', + ), + onPressed: (context) async { + // copy to clipboard + await Clipboard.setData( + ClipboardData( + text: jsonEncode(appSettings.toJson()), + ), + ); + // show toast + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Settings copied to clipboard'), + ), + ); + }, + ), + SettingsTile( + title: const Text('Restore'), + leading: const Icon(Icons.restore), + description: const Text( + 'Restore the app settings from the backup', + ), + onPressed: (context) { + final formKey = GlobalKey(); + // show a dialog to get the backup + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: const Text('Restore Backup'), + content: Form( + key: formKey, + child: TextFormField( + controller: serverURIController, + decoration: const InputDecoration( + labelText: 'Backup', + hintText: 'Paste the backup here', + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please paste the backup here'; + } + return null; + }, + ), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text('Cancel'), + ), + TextButton( + onPressed: () { + if (formKey.currentState!.validate()) { + final backup = serverURIController.text; + final newSettings = model.AppSettings.fromJson( + // decode the backup as json + jsonDecode(backup), + ); + ref + .read(appSettingsProvider.notifier) + .update(newSettings); + Navigator.of(context).pop(); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Settings restored'), ), ); - }, + // clear the backup + serverURIController.clear(); + } + }, + child: const Text('Restore'), + ), + ], + ); + }, + ); + }, + ), + + // a button to reset the app settings + SettingsTile( + title: const Text('Reset App Settings'), + leading: const Icon(Icons.settings_backup_restore), + description: const Text( + 'Reset the app settings to the default values', + ), + onPressed: (context) async { + // confirm the reset + final res = await showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: const Text('Reset App Settings'), + content: const Text( + 'Are you sure you want to reset the app settings?', ), - ], - ), - ), - ), - ], - ), - - // Backup and Restore section - SettingsSection( - margin: const EdgeInsetsDirectional.symmetric( - horizontal: 16.0, - vertical: 8.0, - ), - title: Text( - 'Backup and Restore', - style: Theme.of(context).textTheme.titleLarge, - ), - tiles: [ - SettingsTile( - title: const Text('Copy to Clipboard'), - leading: const Icon(Icons.copy), - description: const Text( - 'Copy the app settings to the clipboard', - ), - onPressed: (context) async { - // copy to clipboard - await Clipboard.setData( - ClipboardData( - text: jsonEncode(appSettings.toJson()), - ), - ); - // show toast - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Settings copied to clipboard'), - ), - ); - }, - ), - SettingsTile( - title: const Text('Restore'), - leading: const Icon(Icons.restore), - description: const Text( - 'Restore the app settings from the backup', - ), - onPressed: (context) { - final formKey = GlobalKey(); - // show a dialog to get the backup - showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: const Text('Restore Backup'), - content: Form( - key: formKey, - child: TextFormField( - controller: serverURIController, - decoration: const InputDecoration( - labelText: 'Backup', - hintText: 'Paste the backup here', - ), - validator: (value) { - if (value == null || value.isEmpty) { - return 'Please paste the backup here'; - } - return null; - }, - ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(false); + }, + child: const Text('Cancel'), ), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: const Text('Cancel'), - ), - TextButton( - onPressed: () { - if (formKey.currentState!.validate()) { - final backup = serverURIController.text; - final newSettings = model.AppSettings.fromJson( - // decode the backup as json - jsonDecode(backup), - ); - ref - .read(appSettingsProvider.notifier) - .update(newSettings); - Navigator.of(context).pop(); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Settings restored'), - ), - ); - // clear the backup - serverURIController.clear(); - } - }, - child: const Text('Restore'), - ), - ], - ); - }, - ); - }, - ), - - // a button to reset the app settings - SettingsTile( - title: const Text('Reset App Settings'), - leading: const Icon(Icons.settings_backup_restore), - description: const Text( - 'Reset the app settings to the default values', - ), - onPressed: (context) async { - // confirm the reset - final res = await showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: const Text('Reset App Settings'), - content: const Text( - 'Are you sure you want to reset the app settings?', + TextButton( + onPressed: () { + Navigator.of(context).pop(true); + }, + child: const Text('Reset'), ), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(false); - }, - child: const Text('Cancel'), - ), - TextButton( - onPressed: () { - Navigator.of(context).pop(true); - }, - child: const Text('Reset'), - ), - ], - ); - }, - ); + ], + ); + }, + ); - // if the user confirms the reset - if (res == true) { - ref.read(appSettingsProvider.notifier).reset(); - } - }, - ), - ], - ), - ], - ), + // if the user confirms the reset + if (res == true) { + ref.read(appSettingsProvider.notifier).reset(); + } + }, + ), + ], + ), + ], ); } } diff --git a/lib/settings/view/auto_sleep_timer_settings_page.dart b/lib/settings/view/auto_sleep_timer_settings_page.dart index 2383ba1..29524a9 100644 --- a/lib/settings/view/auto_sleep_timer_settings_page.dart +++ b/lib/settings/view/auto_sleep_timer_settings_page.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_settings_ui/flutter_settings_ui.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:vaani/settings/app_settings_provider.dart'; +import 'package:vaani/settings/view/simple_settings_page.dart'; import 'package:vaani/shared/extensions/time_of_day.dart'; class AutoSleepTimerSettingsPage extends HookConsumerWidget { @@ -14,97 +15,87 @@ class AutoSleepTimerSettingsPage extends HookConsumerWidget { final appSettings = ref.watch(appSettingsProvider); final sleepTimerSettings = appSettings.playerSettings.sleepTimerSettings; - return Scaffold( - appBar: AppBar( - title: const Text('Auto Sleep Timer Settings'), - ), - body: SettingsList( - sections: [ - SettingsSection( - margin: const EdgeInsetsDirectional.symmetric( - horizontal: 16.0, - vertical: 8.0, + return SimpleSettingsPage( + title: const Text('Auto Sleep Timer Settings'), + sections: [ + SettingsSection( + margin: const EdgeInsetsDirectional.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + tiles: [ + SettingsTile.switchTile( + // initialValue: sleepTimerSettings.autoTurnOnTimer, + title: const Text('Auto Turn On Timer'), + description: const Text( + 'Automatically turn on the sleep timer based on the time of day', + ), + leading: sleepTimerSettings.autoTurnOnTimer + ? const Icon(Icons.timer) + : const Icon(Icons.timer_off), + onToggle: (value) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.playerSettings.sleepTimerSettings( + autoTurnOnTimer: value, + ), + ); + }, + initialValue: sleepTimerSettings.autoTurnOnTimer, ), - tiles: [ - SettingsTile.switchTile( - // initialValue: sleepTimerSettings.autoTurnOnTimer, - title: const Text('Auto Turn On Timer'), - description: const Text( - 'Automatically turn on the sleep timer based on the time of day', - ), - leading: sleepTimerSettings.autoTurnOnTimer - ? const Icon(Icons.timer) - : const Icon(Icons.timer_off), - onToggle: (value) { + // auto turn on time settings, enabled only when autoTurnOnTimer is enabled + SettingsTile.navigation( + enabled: sleepTimerSettings.autoTurnOnTimer, + title: const Text('Auto Turn On Time'), + description: const Text( + 'Turn on the sleep timer at the specified time', + ), + onPressed: (context) async { + // navigate to the time picker + final selected = await showTimePicker( + context: context, + initialTime: sleepTimerSettings.autoTurnOnTime.toTimeOfDay(), + ); + if (selected != null) { ref.read(appSettingsProvider.notifier).update( appSettings.copyWith.playerSettings.sleepTimerSettings( - autoTurnOnTimer: value, + autoTurnOnTime: selected.toDuration(), ), ); - }, - initialValue: sleepTimerSettings.autoTurnOnTimer, + } + }, + value: Text( + sleepTimerSettings.autoTurnOnTime.toTimeOfDay().format(context), ), - // auto turn on time settings, enabled only when autoTurnOnTimer is enabled - SettingsTile.navigation( - enabled: sleepTimerSettings.autoTurnOnTimer, - title: const Text('Auto Turn On Time'), - description: const Text( - 'Turn on the sleep timer at the specified time', - ), - onPressed: (context) async { - // navigate to the time picker - final selected = await showTimePicker( - context: context, - initialTime: - sleepTimerSettings.autoTurnOnTime.toTimeOfDay(), - ); - if (selected != null) { - ref.read(appSettingsProvider.notifier).update( - appSettings.copyWith.playerSettings - .sleepTimerSettings( - autoTurnOnTime: selected.toDuration(), - ), - ); - } - }, - value: Text( - sleepTimerSettings.autoTurnOnTime - .toTimeOfDay() - .format(context), - ), + ), + SettingsTile.navigation( + title: const Text('Auto Turn Off Time'), + description: const Text( + 'Turn off the sleep timer at the specified time', ), - SettingsTile.navigation( - title: const Text('Auto Turn Off Time'), - description: const Text( - 'Turn off the sleep timer at the specified time', - ), - enabled: sleepTimerSettings.autoTurnOnTimer, - onPressed: (context) async { - // navigate to the time picker - final selected = await showTimePicker( - context: context, - initialTime: - sleepTimerSettings.autoTurnOffTime.toTimeOfDay(), - ); - if (selected != null) { - ref.read(appSettingsProvider.notifier).update( - appSettings.copyWith.playerSettings - .sleepTimerSettings( - autoTurnOffTime: selected.toDuration(), - ), - ); - } - }, - value: Text( - sleepTimerSettings.autoTurnOffTime - .toTimeOfDay() - .format(context), - ), + enabled: sleepTimerSettings.autoTurnOnTimer, + onPressed: (context) async { + // navigate to the time picker + final selected = await showTimePicker( + context: context, + initialTime: sleepTimerSettings.autoTurnOffTime.toTimeOfDay(), + ); + if (selected != null) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.playerSettings.sleepTimerSettings( + autoTurnOffTime: selected.toDuration(), + ), + ); + } + }, + value: Text( + sleepTimerSettings.autoTurnOffTime + .toTimeOfDay() + .format(context), ), - ], - ), - ], - ), + ), + ], + ), + ], ); } } diff --git a/lib/settings/view/notification_settings_page.dart b/lib/settings/view/notification_settings_page.dart new file mode 100644 index 0000000..df1c5e5 --- /dev/null +++ b/lib/settings/view/notification_settings_page.dart @@ -0,0 +1,404 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:flutter_settings_ui/flutter_settings_ui.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:vaani/settings/app_settings_provider.dart'; +import 'package:vaani/settings/models/app_settings.dart'; +import 'package:vaani/settings/view/simple_settings_page.dart'; + +class NotificationSettingsPage extends HookConsumerWidget { + const NotificationSettingsPage({ + super.key, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final appSettings = ref.watch(appSettingsProvider); + final notificationSettings = appSettings.notificationSettings; + + return SimpleSettingsPage( + title: const Text('Notification Settings'), + sections: [ + SettingsSection( + margin: const EdgeInsetsDirectional.only( + start: 16.0, + end: 16.0, + top: 8.0, + bottom: 8.0, + ), + tiles: [ + // set the primary and secondary titles + SettingsTile( + title: const Text('Primary Title'), + description: Text.rich( + TextSpan( + text: 'The title of the notification\n', + children: [ + TextSpan( + text: notificationSettings.primaryTitle, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + ], + ), + ), + leading: const Icon(Icons.title), + onPressed: (context) async { + // show the notification title picker + final selectedTitle = await showDialog( + context: context, + builder: (context) { + return NotificationTitlePicker( + initialValue: notificationSettings.primaryTitle, + title: 'Primary Title', + ); + }, + ); + if (selectedTitle != null) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.notificationSettings( + primaryTitle: selectedTitle, + ), + ); + } + }, + ), + + SettingsTile( + title: const Text('Secondary Title'), + description: Text.rich( + TextSpan( + text: 'The subtitle of the notification\n', + children: [ + TextSpan( + text: notificationSettings.secondaryTitle, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + ], + ), + ), + leading: const Icon(Icons.title), + onPressed: (context) async { + // show the notification title picker + final selectedTitle = await showDialog( + context: context, + builder: (context) { + return NotificationTitlePicker( + initialValue: notificationSettings.secondaryTitle, + title: 'Secondary Title', + ); + }, + ); + if (selectedTitle != null) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.notificationSettings( + secondaryTitle: selectedTitle, + ), + ); + } + }, + ), + + // set forward and backward intervals + SettingsTile( + title: const Text('Forward Interval'), + description: Row( + children: [ + Text( + '${notificationSettings.fastForwardInterval.inSeconds} seconds', + ), + Expanded( + child: TimeIntervalSlider( + defaultValue: notificationSettings.fastForwardInterval, + onChangedEnd: (interval) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.notificationSettings( + fastForwardInterval: interval, + ), + ); + }, + ), + ), + ], + ), + leading: const Icon(Icons.fast_forward), + ), + SettingsTile( + title: const Text('Backward Interval'), + description: Row( + children: [ + Text( + '${notificationSettings.rewindInterval.inSeconds} seconds', + ), + Expanded( + child: TimeIntervalSlider( + defaultValue: notificationSettings.rewindInterval, + onChangedEnd: (interval) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.notificationSettings( + rewindInterval: interval, + ), + ); + }, + ), + ), + ], + ), + leading: const Icon(Icons.fast_rewind), + ), + // set the media controls + SettingsTile( + title: const Text('Media Controls'), + leading: const Icon(Icons.control_camera), + // description: const Text('Select the media controls to display'), + description: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text('Select the media controls to display'), + Wrap( + spacing: 8.0, + children: notificationSettings.mediaControls + .map( + (control) => Icon(control.icon), + ) + .toList(), + ), + ], + ), + onPressed: (context) async { + final selectedControls = + await showDialog>( + context: context, + builder: (context) { + return MediaControlsPicker( + selectedControls: notificationSettings.mediaControls, + ); + }, + ); + if (selectedControls != null) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.notificationSettings( + mediaControls: selectedControls, + ), + ); + } + }, + ), + + // set the progress bar to show chapter progress + SettingsTile.switchTile( + title: const Text('Show Chapter Progress'), + leading: const Icon(Icons.book), + description: + const Text('instead of the overall progress of the book'), + initialValue: notificationSettings.progressBarIsChapterProgress, + onToggle: (value) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.notificationSettings( + progressBarIsChapterProgress: value, + ), + ); + }, + ), + ], + ), + ], + ); + } +} + +class MediaControlsPicker extends HookConsumerWidget { + const MediaControlsPicker({ + super.key, + required this.selectedControls, + }); + + final List selectedControls; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final selectedMediaControls = useState(selectedControls); + return AlertDialog( + title: const Text('Media Controls'), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text('Cancel'), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(selectedMediaControls.value); + }, + child: const Text('OK'), + ), + ], + // a list of chips to easily select the media controls to display + // with icons and labels + content: Wrap( + spacing: 8.0, + children: NotificationMediaControl.values + .map( + (control) => ChoiceChip( + label: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(control.icon), + const SizedBox(width: 4.0), + Text(control.name), + ], + ), + selected: selectedMediaControls.value.contains(control), + onSelected: (selected) { + if (selected) { + selectedMediaControls.value = [ + ...selectedMediaControls.value, + control, + ]; + } else { + selectedMediaControls.value = [ + ...selectedMediaControls.value.where((c) => c != control), + ]; + } + }, + ), + ) + .toList(), + ), + ); + } +} + +class TimeIntervalSlider extends HookConsumerWidget { + const TimeIntervalSlider({ + super.key, + this.title, + required this.defaultValue, + this.onChanged, + this.onChangedEnd, + this.min = const Duration(seconds: 5), + this.max = const Duration(seconds: 120), + this.step = const Duration(seconds: 5), + }); + + final Widget? title; + final Duration defaultValue; + final ValueChanged? onChanged; + final ValueChanged? onChangedEnd; + final Duration min; + final Duration max; + final Duration step; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final selectedInterval = useState(defaultValue); + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + title ?? const SizedBox.shrink(), + if (title != null) const SizedBox(height: 8.0), + Slider( + value: selectedInterval.value.inSeconds.toDouble(), + min: min.inSeconds.toDouble(), + max: max.inSeconds.toDouble(), + divisions: ((max.inSeconds - min.inSeconds) ~/ step.inSeconds), + label: '${selectedInterval.value.inSeconds} seconds', + onChanged: (value) { + selectedInterval.value = Duration(seconds: value.toInt()); + onChanged?.call(selectedInterval.value); + }, + onChangeEnd: (value) { + onChangedEnd?.call(selectedInterval.value); + }, + ), + ], + ); + } +} + +class NotificationTitlePicker extends HookConsumerWidget { + const NotificationTitlePicker({ + super.key, + required this.initialValue, + required this.title, + }); + + final String initialValue; + final String title; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final selectedTitle = useState(initialValue); + final controller = useTextEditingController(text: initialValue); + return AlertDialog( + title: Text(title), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text('Cancel'), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(selectedTitle.value); + }, + child: const Text('OK'), + ), + ], + // a list of chips to easily insert available fields into the text field + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextField( + autofocus: true, + controller: controller, + onChanged: (value) { + selectedTitle.value = value; + }, + decoration: InputDecoration( + helper: const Text('Select a field below to insert it'), + suffix: IconButton( + icon: const Icon(Icons.clear), + onPressed: () { + controller.clear(); + selectedTitle.value = ''; + }, + ), + ), + ), + const SizedBox(height: 8.0), + Wrap( + spacing: 8.0, + children: NotificationTitleType.values + .map( + (type) => ActionChip( + label: Text(type.stringValue), + onPressed: () { + final text = controller.text; + final newText = '$text\$${type.stringValue}'; + controller.text = newText; + selectedTitle.value = newText; + }, + ), + ) + .toList(), + ), + ], + ), + ); + } +} + +Future showNotificationTitlePicker( + BuildContext context, { + required String initialValue, + required String title, +}) async { + return showDialog( + context: context, + builder: (context) { + return NotificationTitlePicker(initialValue: initialValue, title: title); + }, + ); +} diff --git a/lib/settings/view/simple_settings_page.dart b/lib/settings/view/simple_settings_page.dart new file mode 100644 index 0000000..586e986 --- /dev/null +++ b/lib/settings/view/simple_settings_page.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_settings_ui/flutter_settings_ui.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +class SimpleSettingsPage extends HookConsumerWidget { + const SimpleSettingsPage({ + super.key, + this.title, + this.sections, + }); + + final Widget? title; + final List? sections; + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Scaffold( + // appBar: AppBar( + // title: title, + // ), + // body: body, + // an app bar which is bigger than the default app bar but on scroll shrinks to the default app bar with the title being animated + body: CustomScrollView( + slivers: [ + SliverAppBar( + expandedHeight: 200.0, + floating: false, + pinned: true, + flexibleSpace: FlexibleSpaceBar( + title: title, + // background: Theme.of(context).primaryColor, + ), + ), + if (sections != null) + SliverList( + delegate: SliverChildListDelegate( + [ + ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(20)), + child: SettingsList( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + sections: sections!, + ), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 2fe54a5..f7059ef 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -71,7 +71,7 @@ packages: source: hosted version: "2.11.0" audio_service: - dependency: transitive + dependency: "direct main" description: name: audio_service sha256: "9dd5ba7e77567b290c35908b1950d61485b4dfdd3a0ac398e98cfeec04651b75" @@ -704,10 +704,11 @@ packages: just_audio_background: dependency: "direct main" description: - name: just_audio_background - sha256: "7547b076d5445431c780b0915707f18baa6d9588077d5d8f811e8a77b4e0bec5" - url: "https://pub.dev" - source: hosted + path: just_audio_background + ref: media-notification-config + resolved-ref: "79ac48a7d322d5b8db8847b35ed0c8555fa249bc" + url: "https://github.com/Dr-Blank/just_audio" + source: git version: "0.0.1-beta.13" just_audio_media_kit: dependency: "direct main" diff --git a/pubspec.yaml b/pubspec.yaml index 17f7b22..888f8b6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -32,6 +32,7 @@ isar_version: &isar_version ^4.0.0-dev.13 # define the version to be used dependencies: animated_list_plus: ^0.5.2 animated_theme_switcher: ^2.0.10 + audio_service: ^0.18.15 audio_session: ^0.1.19 audio_video_progress_bar: ^2.0.2 auto_scroll_text: ^0.0.7 @@ -59,7 +60,12 @@ dependencies: isar_flutter_libs: ^4.0.0-dev.13 json_annotation: ^4.9.0 just_audio: ^0.9.37 - just_audio_background: ^0.0.1-beta.11 + just_audio_background: + # TODO Remove git dep when https://github.com/ryanheise/just_audio/issues/912 is closed + git: + url: https://github.com/Dr-Blank/just_audio + ref: media-notification-config + path: just_audio_background just_audio_media_kit: ^2.0.4 list_wheel_scroll_view_nls: ^0.0.3 logging: ^1.2.0 From 7279fa0bd6e8f0e9cc4b873613a2859f9f3a84fa Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Wed, 25 Sep 2024 03:23:44 -0400 Subject: [PATCH 14/92] chore: bump version to 0.0.6+1 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 888f8b6..11f5621 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.0.5+1 +version: 0.0.6+1 environment: sdk: ">=3.3.4 <4.0.0" From 8049a660e6036ca470fc2c971b80a00a37bf3740 Mon Sep 17 00:00:00 2001 From: "Dr.Blank" Date: Thu, 26 Sep 2024 01:39:43 -0400 Subject: [PATCH 15/92] feat: new settings to configure when to report playback and when to mark item complete (#32) --- .../core/playback_reporter.dart | 61 ++++++++++++++++++- .../providers/playback_reporter_provider.dart | 6 +- .../playback_reporter_provider.g.dart | 2 +- lib/settings/models/app_settings.dart | 2 + lib/settings/models/app_settings.freezed.dart | 52 +++++++++++++++- lib/settings/models/app_settings.g.dart | 13 ++++ 6 files changed, 129 insertions(+), 7 deletions(-) diff --git a/lib/features/playback_reporting/core/playback_reporter.dart b/lib/features/playback_reporting/core/playback_reporter.dart index 7416927..81c6265 100644 --- a/lib/features/playback_reporting/core/playback_reporter.dart +++ b/lib/features/playback_reporting/core/playback_reporter.dart @@ -39,7 +39,15 @@ class PlaybackReporter { /// the minimum duration to report final Duration reportingDurationThreshold; + /// the duration to wait before starting the reporting + /// this is to ignore the initial duration in case user is browsing + final Duration? minimumPositionForReporting; + + /// the duration to mark the book as complete when the time left is less than this + final Duration markCompleteWhenTimeLeft; + /// timer to report every 10 seconds + /// tracking the time since the last report Timer? _reportTimer; /// metadata to report @@ -61,6 +69,8 @@ class PlaybackReporter { this.deviceManufacturer, this.reportingDurationThreshold = const Duration(seconds: 1), Duration reportingInterval = const Duration(seconds: 10), + this.minimumPositionForReporting, + this.markCompleteWhenTimeLeft = const Duration(seconds: 5), }) : _reportingInterval = reportingInterval { // initial conditions if (player.playing) { @@ -97,23 +107,35 @@ class PlaybackReporter { _logger.fine( 'player state observed, stopping stopwatch at ${_stopwatch.elapsed}', ); - await syncCurrentPosition(); + await tryReportPlayback(null); } }), ); _logger.fine( - 'initialized with interval: $reportingInterval, threshold: $reportingDurationThreshold', + 'initialized with reportingInterval: $reportingInterval, reportingDurationThreshold: $reportingDurationThreshold', + ); + _logger.fine( + 'initialized with minimumPositionForReporting: $minimumPositionForReporting, markCompleteWhenTimeLeft: $markCompleteWhenTimeLeft', ); _logger.fine( 'initialized with deviceModel: $deviceModel, deviceSdkVersion: $deviceSdkVersion, deviceClientName: $deviceClientName, deviceClientVersion: $deviceClientVersion, deviceManufacturer: $deviceManufacturer', ); } - void tryReportPlayback(_) async { + Future tryReportPlayback(_) async { _logger.fine( 'callback called when elapsed ${_stopwatch.elapsed}', ); + if (player.book != null && + player.positionInBook >= + player.book!.duration - markCompleteWhenTimeLeft) { + _logger.info( + 'marking complete as time left is less than $markCompleteWhenTimeLeft', + ); + await markComplete(); + return; + } if (_stopwatch.elapsed > reportingDurationThreshold) { _logger.fine( 'reporting now with elapsed ${_stopwatch.elapsed} > threshold $reportingDurationThreshold', @@ -159,6 +181,22 @@ class PlaybackReporter { return _session; } + Future markComplete() async { + if (player.book == null) { + throw NoAudiobookPlayingError(); + } + await authenticatedApi.me.createUpdateMediaProgress( + libraryItemId: player.book!.libraryItemId, + parameters: CreateUpdateProgressReqParams( + isFinished: true, + currentTime: player.positionInBook, + duration: player.book!.duration, + ), + responseErrorHandler: _responseErrorHandler, + ); + _logger.info('Marked complete for book: ${player.book!.libraryItemId}'); + } + Future syncCurrentPosition() async { final data = _getSyncData(); if (data == null) { @@ -229,6 +267,23 @@ class PlaybackReporter { ); return null; } + + // if in the ignore duration, don't sync + if (minimumPositionForReporting != null && + player.positionInBook < minimumPositionForReporting!) { + // but if elapsed time is more than the minimumPositionForReporting, sync + if (_stopwatch.elapsed > minimumPositionForReporting!) { + _logger.info( + 'Syncing position despite being less than minimumPositionForReporting as elapsed time is more: ${_stopwatch.elapsed}', + ); + } else { + _logger.info( + 'Ignoring sync for position: ${player.positionInBook} < $minimumPositionForReporting', + ); + return null; + } + } + return SyncSessionReqParams( currentTime: player.positionInBook, timeListened: _stopwatch.elapsed, diff --git a/lib/features/playback_reporting/providers/playback_reporter_provider.dart b/lib/features/playback_reporting/providers/playback_reporter_provider.dart index e76f7ff..a7ca1d5 100644 --- a/lib/features/playback_reporting/providers/playback_reporter_provider.dart +++ b/lib/features/playback_reporting/providers/playback_reporter_provider.dart @@ -13,7 +13,7 @@ part 'playback_reporter_provider.g.dart'; class PlaybackReporter extends _$PlaybackReporter { @override Future build() async { - final appSettings = ref.watch(appSettingsProvider); + final playerSettings = ref.watch(appSettingsProvider).playerSettings; final player = ref.watch(simpleAudiobookPlayerProvider); final packageInfo = await PackageInfo.fromPlatform(); final api = ref.watch(authenticatedApiProvider); @@ -26,7 +26,9 @@ class PlaybackReporter extends _$PlaybackReporter { final reporter = core.PlaybackReporter( player, api, - reportingInterval: appSettings.playerSettings.playbackReportInterval, + reportingInterval: playerSettings.playbackReportInterval, + markCompleteWhenTimeLeft: playerSettings.markCompleteWhenTimeLeft, + minimumPositionForReporting: playerSettings.minimumPositionForReporting, deviceName: deviceName, deviceModel: deviceModel, deviceSdkVersion: deviceSdkVersion, diff --git a/lib/features/playback_reporting/providers/playback_reporter_provider.g.dart b/lib/features/playback_reporting/providers/playback_reporter_provider.g.dart index 2a76328..8b8936d 100644 --- a/lib/features/playback_reporting/providers/playback_reporter_provider.g.dart +++ b/lib/features/playback_reporting/providers/playback_reporter_provider.g.dart @@ -6,7 +6,7 @@ part of 'playback_reporter_provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$playbackReporterHash() => r'c210b7286d9c151fd59a9ead9eb4a28d1cffdc7c'; +String _$playbackReporterHash() => r'f5436d652e51c37bcc684acdaec94e17a97e68e5'; /// See also [PlaybackReporter]. @ProviderFor(PlaybackReporter) diff --git a/lib/settings/models/app_settings.dart b/lib/settings/models/app_settings.dart index cc4506b..8ccb320 100644 --- a/lib/settings/models/app_settings.dart +++ b/lib/settings/models/app_settings.dart @@ -45,7 +45,9 @@ class PlayerSettings with _$PlayerSettings { @Default(1) double preferredDefaultSpeed, @Default([0.75, 1, 1.25, 1.5, 1.75, 2]) List speedOptions, @Default(SleepTimerSettings()) SleepTimerSettings sleepTimerSettings, + @Default(Duration(seconds: 10)) Duration minimumPositionForReporting, @Default(Duration(seconds: 10)) Duration playbackReportInterval, + @Default(Duration(seconds: 15)) Duration markCompleteWhenTimeLeft, @Default(true) bool configurePlayerForEveryBook, }) = _PlayerSettings; diff --git a/lib/settings/models/app_settings.freezed.dart b/lib/settings/models/app_settings.freezed.dart index 204d314..b07b684 100644 --- a/lib/settings/models/app_settings.freezed.dart +++ b/lib/settings/models/app_settings.freezed.dart @@ -514,7 +514,10 @@ mixin _$PlayerSettings { List get speedOptions => throw _privateConstructorUsedError; SleepTimerSettings get sleepTimerSettings => throw _privateConstructorUsedError; + Duration get minimumPositionForReporting => + throw _privateConstructorUsedError; Duration get playbackReportInterval => throw _privateConstructorUsedError; + Duration get markCompleteWhenTimeLeft => throw _privateConstructorUsedError; bool get configurePlayerForEveryBook => throw _privateConstructorUsedError; /// Serializes this PlayerSettings to a JSON map. @@ -540,7 +543,9 @@ abstract class $PlayerSettingsCopyWith<$Res> { double preferredDefaultSpeed, List speedOptions, SleepTimerSettings sleepTimerSettings, + Duration minimumPositionForReporting, Duration playbackReportInterval, + Duration markCompleteWhenTimeLeft, bool configurePlayerForEveryBook}); $MinimizedPlayerSettingsCopyWith<$Res> get miniPlayerSettings; @@ -569,7 +574,9 @@ class _$PlayerSettingsCopyWithImpl<$Res, $Val extends PlayerSettings> Object? preferredDefaultSpeed = null, Object? speedOptions = null, Object? sleepTimerSettings = null, + Object? minimumPositionForReporting = null, Object? playbackReportInterval = null, + Object? markCompleteWhenTimeLeft = null, Object? configurePlayerForEveryBook = null, }) { return _then(_value.copyWith( @@ -597,10 +604,18 @@ class _$PlayerSettingsCopyWithImpl<$Res, $Val extends PlayerSettings> ? _value.sleepTimerSettings : sleepTimerSettings // ignore: cast_nullable_to_non_nullable as SleepTimerSettings, + minimumPositionForReporting: null == minimumPositionForReporting + ? _value.minimumPositionForReporting + : minimumPositionForReporting // ignore: cast_nullable_to_non_nullable + as Duration, playbackReportInterval: null == playbackReportInterval ? _value.playbackReportInterval : playbackReportInterval // ignore: cast_nullable_to_non_nullable as Duration, + markCompleteWhenTimeLeft: null == markCompleteWhenTimeLeft + ? _value.markCompleteWhenTimeLeft + : markCompleteWhenTimeLeft // ignore: cast_nullable_to_non_nullable + as Duration, configurePlayerForEveryBook: null == configurePlayerForEveryBook ? _value.configurePlayerForEveryBook : configurePlayerForEveryBook // ignore: cast_nullable_to_non_nullable @@ -657,7 +672,9 @@ abstract class _$$PlayerSettingsImplCopyWith<$Res> double preferredDefaultSpeed, List speedOptions, SleepTimerSettings sleepTimerSettings, + Duration minimumPositionForReporting, Duration playbackReportInterval, + Duration markCompleteWhenTimeLeft, bool configurePlayerForEveryBook}); @override @@ -687,7 +704,9 @@ class __$$PlayerSettingsImplCopyWithImpl<$Res> Object? preferredDefaultSpeed = null, Object? speedOptions = null, Object? sleepTimerSettings = null, + Object? minimumPositionForReporting = null, Object? playbackReportInterval = null, + Object? markCompleteWhenTimeLeft = null, Object? configurePlayerForEveryBook = null, }) { return _then(_$PlayerSettingsImpl( @@ -715,10 +734,18 @@ class __$$PlayerSettingsImplCopyWithImpl<$Res> ? _value.sleepTimerSettings : sleepTimerSettings // ignore: cast_nullable_to_non_nullable as SleepTimerSettings, + minimumPositionForReporting: null == minimumPositionForReporting + ? _value.minimumPositionForReporting + : minimumPositionForReporting // ignore: cast_nullable_to_non_nullable + as Duration, playbackReportInterval: null == playbackReportInterval ? _value.playbackReportInterval : playbackReportInterval // ignore: cast_nullable_to_non_nullable as Duration, + markCompleteWhenTimeLeft: null == markCompleteWhenTimeLeft + ? _value.markCompleteWhenTimeLeft + : markCompleteWhenTimeLeft // ignore: cast_nullable_to_non_nullable + as Duration, configurePlayerForEveryBook: null == configurePlayerForEveryBook ? _value.configurePlayerForEveryBook : configurePlayerForEveryBook // ignore: cast_nullable_to_non_nullable @@ -737,7 +764,9 @@ class _$PlayerSettingsImpl implements _PlayerSettings { this.preferredDefaultSpeed = 1, final List speedOptions = const [0.75, 1, 1.25, 1.5, 1.75, 2], this.sleepTimerSettings = const SleepTimerSettings(), + this.minimumPositionForReporting = const Duration(seconds: 10), this.playbackReportInterval = const Duration(seconds: 10), + this.markCompleteWhenTimeLeft = const Duration(seconds: 15), this.configurePlayerForEveryBook = true}) : _speedOptions = speedOptions; @@ -770,14 +799,20 @@ class _$PlayerSettingsImpl implements _PlayerSettings { final SleepTimerSettings sleepTimerSettings; @override @JsonKey() + final Duration minimumPositionForReporting; + @override + @JsonKey() final Duration playbackReportInterval; @override @JsonKey() + final Duration markCompleteWhenTimeLeft; + @override + @JsonKey() final bool configurePlayerForEveryBook; @override String toString() { - return 'PlayerSettings(miniPlayerSettings: $miniPlayerSettings, expandedPlayerSettings: $expandedPlayerSettings, preferredDefaultVolume: $preferredDefaultVolume, preferredDefaultSpeed: $preferredDefaultSpeed, speedOptions: $speedOptions, sleepTimerSettings: $sleepTimerSettings, playbackReportInterval: $playbackReportInterval, configurePlayerForEveryBook: $configurePlayerForEveryBook)'; + return 'PlayerSettings(miniPlayerSettings: $miniPlayerSettings, expandedPlayerSettings: $expandedPlayerSettings, preferredDefaultVolume: $preferredDefaultVolume, preferredDefaultSpeed: $preferredDefaultSpeed, speedOptions: $speedOptions, sleepTimerSettings: $sleepTimerSettings, minimumPositionForReporting: $minimumPositionForReporting, playbackReportInterval: $playbackReportInterval, markCompleteWhenTimeLeft: $markCompleteWhenTimeLeft, configurePlayerForEveryBook: $configurePlayerForEveryBook)'; } @override @@ -797,8 +832,15 @@ class _$PlayerSettingsImpl implements _PlayerSettings { .equals(other._speedOptions, _speedOptions) && (identical(other.sleepTimerSettings, sleepTimerSettings) || other.sleepTimerSettings == sleepTimerSettings) && + (identical(other.minimumPositionForReporting, + minimumPositionForReporting) || + other.minimumPositionForReporting == + minimumPositionForReporting) && (identical(other.playbackReportInterval, playbackReportInterval) || other.playbackReportInterval == playbackReportInterval) && + (identical( + other.markCompleteWhenTimeLeft, markCompleteWhenTimeLeft) || + other.markCompleteWhenTimeLeft == markCompleteWhenTimeLeft) && (identical(other.configurePlayerForEveryBook, configurePlayerForEveryBook) || other.configurePlayerForEveryBook == @@ -815,7 +857,9 @@ class _$PlayerSettingsImpl implements _PlayerSettings { preferredDefaultSpeed, const DeepCollectionEquality().hash(_speedOptions), sleepTimerSettings, + minimumPositionForReporting, playbackReportInterval, + markCompleteWhenTimeLeft, configurePlayerForEveryBook); /// Create a copy of PlayerSettings @@ -843,7 +887,9 @@ abstract class _PlayerSettings implements PlayerSettings { final double preferredDefaultSpeed, final List speedOptions, final SleepTimerSettings sleepTimerSettings, + final Duration minimumPositionForReporting, final Duration playbackReportInterval, + final Duration markCompleteWhenTimeLeft, final bool configurePlayerForEveryBook}) = _$PlayerSettingsImpl; factory _PlayerSettings.fromJson(Map json) = @@ -862,8 +908,12 @@ abstract class _PlayerSettings implements PlayerSettings { @override SleepTimerSettings get sleepTimerSettings; @override + Duration get minimumPositionForReporting; + @override Duration get playbackReportInterval; @override + Duration get markCompleteWhenTimeLeft; + @override bool get configurePlayerForEveryBook; /// Create a copy of PlayerSettings diff --git a/lib/settings/models/app_settings.g.dart b/lib/settings/models/app_settings.g.dart index 58aaad4..c1554c7 100644 --- a/lib/settings/models/app_settings.g.dart +++ b/lib/settings/models/app_settings.g.dart @@ -73,10 +73,19 @@ _$PlayerSettingsImpl _$$PlayerSettingsImplFromJson(Map json) => ? const SleepTimerSettings() : SleepTimerSettings.fromJson( json['sleepTimerSettings'] as Map), + minimumPositionForReporting: json['minimumPositionForReporting'] == null + ? const Duration(seconds: 10) + : Duration( + microseconds: + (json['minimumPositionForReporting'] as num).toInt()), playbackReportInterval: json['playbackReportInterval'] == null ? const Duration(seconds: 10) : Duration( microseconds: (json['playbackReportInterval'] as num).toInt()), + markCompleteWhenTimeLeft: json['markCompleteWhenTimeLeft'] == null + ? const Duration(seconds: 15) + : Duration( + microseconds: (json['markCompleteWhenTimeLeft'] as num).toInt()), configurePlayerForEveryBook: json['configurePlayerForEveryBook'] as bool? ?? true, ); @@ -90,7 +99,11 @@ Map _$$PlayerSettingsImplToJson( 'preferredDefaultSpeed': instance.preferredDefaultSpeed, 'speedOptions': instance.speedOptions, 'sleepTimerSettings': instance.sleepTimerSettings, + 'minimumPositionForReporting': + instance.minimumPositionForReporting.inMicroseconds, 'playbackReportInterval': instance.playbackReportInterval.inMicroseconds, + 'markCompleteWhenTimeLeft': + instance.markCompleteWhenTimeLeft.inMicroseconds, 'configurePlayerForEveryBook': instance.configurePlayerForEveryBook, }; From 150e5c9025953818dfbc82784ead1d277f3a22d3 Mon Sep 17 00:00:00 2001 From: "Dr.Blank" Date: Thu, 26 Sep 2024 04:30:51 -0400 Subject: [PATCH 16/92] feat: add player settings page and enhance settings UI (#33) --- .../core/playback_reporter.dart | 10 +- .../player/view/widgets/speed_selector.dart | 335 ++++++++------ lib/router/constants.dart | 5 + lib/router/router.dart | 7 + lib/settings/models/app_settings.dart | 3 + lib/settings/models/app_settings.freezed.dart | 71 ++- lib/settings/models/app_settings.g.dart | 6 + lib/settings/view/app_settings_page.dart | 10 + lib/settings/view/buttons.dart | 34 ++ .../view/notification_settings_page.dart | 25 +- lib/settings/view/player_settings_page.dart | 410 ++++++++++++++++++ lib/settings/view/simple_settings_page.dart | 2 + 12 files changed, 761 insertions(+), 157 deletions(-) create mode 100644 lib/settings/view/buttons.dart create mode 100644 lib/settings/view/player_settings_page.dart diff --git a/lib/features/playback_reporting/core/playback_reporter.dart b/lib/features/playback_reporting/core/playback_reporter.dart index 81c6265..faffb4d 100644 --- a/lib/features/playback_reporting/core/playback_reporter.dart +++ b/lib/features/playback_reporting/core/playback_reporter.dart @@ -166,7 +166,8 @@ class PlaybackReporter { return _session!; } if (player.book == null) { - throw NoAudiobookPlayingError(); + _logger.warning('No audiobook playing to start session'); + return null; } _session = await authenticatedApi.items.play( libraryItemId: player.book!.libraryItemId, @@ -204,8 +205,11 @@ class PlaybackReporter { } try { _session ??= await startSession(); - } on NoAudiobookPlayingError { - _logger.warning('No audiobook playing to sync position'); + } on Error catch (e) { + _logger.warning('Error starting session: $e'); + } + if (_session == null) { + _logger.warning('No session to sync position'); return; } final currentPosition = player.positionInBook; diff --git a/lib/features/player/view/widgets/speed_selector.dart b/lib/features/player/view/widgets/speed_selector.dart index a93550e..289b736 100644 --- a/lib/features/player/view/widgets/speed_selector.dart +++ b/lib/features/player/view/widgets/speed_selector.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -16,7 +18,8 @@ class SpeedSelector extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final appSettings = ref.watch(appSettingsProvider); - final speeds = appSettings.playerSettings.speedOptions; + final playerSettings = appSettings.playerSettings; + final speeds = playerSettings.speedOptions; final currentSpeed = ref.watch(audiobookPlayerProvider).speed; final speedState = useState(currentSpeed); @@ -30,10 +33,16 @@ class SpeedSelector extends HookConsumerWidget { ); // the speed options - const minSpeed = 0.1; - const maxSpeed = 4.0; - const speedIncrement = 0.05; - final availableSpeeds = ((maxSpeed - minSpeed) / speedIncrement).ceil(); + final minSpeed = min( + speeds.reduce((minSpeedSoFar, element) => min(minSpeedSoFar, element)), + playerSettings.minSpeed, + ); + final maxSpeed = max( + speeds.reduce((maxSpeedSoFar, element) => max(maxSpeedSoFar, element)), + playerSettings.maxSpeed, + ); + final speedIncrement = playerSettings.speedIncrement; + final availableSpeeds = ((maxSpeed - minSpeed) / speedIncrement).ceil() + 1; final availableSpeedsList = List.generate( availableSpeeds, (index) { @@ -52,154 +61,210 @@ class SpeedSelector extends HookConsumerWidget { padding: const EdgeInsets.all(8.0), child: Column( children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Center( - child: Text( - 'Playback Speed: ${speedState.value}x', - style: Theme.of(context).textTheme.titleLarge, - ), + // the title + Padding( + padding: const EdgeInsets.all(8.0), + child: Center( + child: Text( + 'Playback Speed: ${speedState.value}x', + style: Theme.of(context).textTheme.titleLarge, ), ), ), + + // the speed selector Flexible( - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - // a minus button to decrease the speed - IconButton.filledTonal( - icon: const Icon(Icons.remove), - onPressed: () { - // animate to index - 1 - final index = availableSpeedsList.indexOf(speedState.value); - if (index > 0) { - scrollController.animateToItem( - index - 1, - duration: const Duration(milliseconds: 300), - curve: Curves.easeInOut, - ); - } - }, - ), - Expanded( - child: ListWheelScrollViewX( - controller: scrollController, - scrollDirection: Axis.horizontal, - itemExtent: itemExtent, - diameterRatio: 1.5, squeeze: 1.2, - // useMagnifier: true, - // magnification: 1.5, - physics: const FixedExtentScrollPhysics(), - children: availableSpeedsList - .map( - (speed) => Column( - children: [ - // a vertical line - Container( - height: itemExtent * 2, - // thick if multiple of 1, thin if multiple of 0.5 and transparent if multiple of 0.05 - width: speed % 0.5 == 0 - ? 3 - : speed % 0.25 == 0 - ? 2 - : 0.5, - color: - Theme.of(context).colorScheme.onSurface, - ), - // the speed text but only at .5 increments of speed - if (speed % 0.25 == 0) - Text( - speed.toString(), - style: TextStyle( - color: Theme.of(context) - .colorScheme - .onSurface, - ), - ), - ], - ), - ) - .toList(), - onSelectedItemChanged: (index) { - speedState.value = availableSpeedsList[index]; - // onSpeedSelected(availableSpeedsList[index]); - // call after 500ms to avoid the scrollview from scrolling to the selected speed - // Future.delayed( - // const Duration(milliseconds: 100), - // () => onSpeedSelected(availableSpeedsList[index]), - // ); - }, - ), - ), - // a plus button to increase the speed - IconButton.filledTonal( - icon: const Icon(Icons.add), - onPressed: () { - // animate to index + 1 - final index = availableSpeedsList.indexOf(speedState.value); - if (index < availableSpeedsList.length - 1) { - scrollController.animateToItem( - index + 1, - duration: const Duration(milliseconds: 300), - curve: Curves.easeInOut, - ); - } - }, - ), - ], + child: SpeedWheel( + availableSpeedsList: availableSpeedsList, + speedState: speedState, + scrollController: scrollController, + itemExtent: itemExtent, ), ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + + // the speed buttons + Wrap( + spacing: 8.0, + alignment: WrapAlignment.center, + runAlignment: WrapAlignment.center, + crossAxisAlignment: WrapCrossAlignment.center, children: speeds .map( - (speed) => Flexible( - // the text button should be highlighted if the speed is selected - child: TextButton( - style: speed == speedState.value - ? TextButton.styleFrom( - backgroundColor: Theme.of(context) + (speed) => TextButton( + style: speed == speedState.value + ? TextButton.styleFrom( + backgroundColor: + Theme.of(context).colorScheme.primaryContainer, + foregroundColor: Theme.of(context) + .colorScheme + .onPrimaryContainer, + ) + // border if not selected + : TextButton.styleFrom( + side: BorderSide( + color: Theme.of(context) .colorScheme .primaryContainer, - foregroundColor: Theme.of(context) - .colorScheme - .onPrimaryContainer, - ) - : null, - onPressed: () async { - // animate the wheel to the selected speed - var index = availableSpeedsList.indexOf(speed); - // if the speed is not in the list - if (index == -1) { - // find the nearest speed - final nearestSpeed = availableSpeedsList.firstWhere( - (element) => element > speed, - orElse: () => availableSpeedsList.last, - ); - index = availableSpeedsList.indexOf(nearestSpeed); - } - await scrollController.animateToItem( - index, - duration: const Duration(milliseconds: 300), - curve: Curves.easeInOut, + ), + ), + onPressed: () async { + // animate the wheel to the selected speed + var index = availableSpeedsList.indexOf(speed); + // if the speed is not in the list + if (index == -1) { + // find the nearest speed + final nearestSpeed = availableSpeedsList.firstWhere( + (element) => element > speed, + orElse: () => availableSpeedsList.last, ); + index = availableSpeedsList.indexOf(nearestSpeed); + } + await scrollController.animateToItem( + index, + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOut, + ); - // call the onSpeedSelected function - speedState.value = speed; - }, - child: Text('$speed'), - ), + // call the onSpeedSelected function + speedState.value = speed; + }, + child: Text('$speed'), ), ) .toList(), ), - const SizedBox( - height: 8, - ), ], ), ); } } + +class SpeedWheel extends StatelessWidget { + const SpeedWheel({ + super.key, + required this.availableSpeedsList, + required this.speedState, + required this.scrollController, + required this.itemExtent, + this.showIncrementButtons = true, + }); + + final List availableSpeedsList; + final ValueNotifier speedState; + final FixedExtentScrollController scrollController; + final double itemExtent; + final bool showIncrementButtons; + + @override + Widget build(BuildContext context) { + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // a minus button to decrease the speed + if (showIncrementButtons) + IconButton.filledTonal( + icon: const Icon(Icons.remove), + onPressed: () { + // animate to index - 1 + final index = availableSpeedsList.indexOf(speedState.value); + if (index > 0) { + scrollController.animateToItem( + index - 1, + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOut, + ); + } + }, + ), + // the speed selector wheel + Expanded( + child: ListWheelScrollViewX( + controller: scrollController, + scrollDirection: Axis.horizontal, + itemExtent: itemExtent, + diameterRatio: 1.5, squeeze: 1.2, + // useMagnifier: true, + // magnification: 1.5, + physics: const FixedExtentScrollPhysics(), + children: availableSpeedsList + .map( + (speed) => Expanded( + child: SpeedLine(itemExtent: itemExtent, speed: speed), + ), + ) + .toList(), + onSelectedItemChanged: (index) { + speedState.value = availableSpeedsList[index]; + }, + ), + ), + + if (showIncrementButtons) + // a plus button to increase the speed + IconButton.filledTonal( + icon: const Icon(Icons.add), + onPressed: () { + // animate to index + 1 + final index = availableSpeedsList.indexOf(speedState.value); + if (index < availableSpeedsList.length - 1) { + scrollController.animateToItem( + index + 1, + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOut, + ); + } + }, + ), + ], + ); + } +} + +class SpeedLine extends StatelessWidget { + const SpeedLine({ + super.key, + required this.itemExtent, + required this.speed, + }); + + final double itemExtent; + final double speed; + + @override + Widget build(BuildContext context) { + return Column( + children: [ + // a vertical line + Container( + height: itemExtent * 2, + // thick if multiple of 1, thin if multiple of 0.5 and transparent if multiple of 0.05 + width: speed % 0.5 == 0 + ? 3 + : speed % 0.25 == 0 + ? 2 + : 0.5, + color: Theme.of(context).colorScheme.onSurface, + ), + // the speed text but only at .5 increments of speed + if (speed % 0.25 == 0) + Expanded( + child: Text.rich( + TextSpan( + text: speed.floor().toString(), + children: [ + TextSpan( + text: '.${speed.toStringAsFixed(2).split('.').last}', + style: TextStyle( + fontSize: + Theme.of(context).textTheme.labelSmall?.fontSize, + ), + ), + ], + ), + ), + ), + ], + ); + } +} diff --git a/lib/router/constants.dart b/lib/router/constants.dart index 9dd15ad..71bb446 100644 --- a/lib/router/constants.dart +++ b/lib/router/constants.dart @@ -37,6 +37,11 @@ class Routes { name: 'notificationSettings', parentRoute: settings, ); + static const playerSettings = _SimpleRoute( + pathName: 'player', + name: 'playerSettings', + parentRoute: settings, + ); // search and explore static const search = _SimpleRoute( diff --git a/lib/router/router.dart b/lib/router/router.dart index 8781e6f..edf9433 100644 --- a/lib/router/router.dart +++ b/lib/router/router.dart @@ -13,6 +13,7 @@ import 'package:vaani/pages/home_page.dart'; import 'package:vaani/settings/view/app_settings_page.dart'; import 'package:vaani/settings/view/auto_sleep_timer_settings_page.dart'; import 'package:vaani/settings/view/notification_settings_page.dart'; +import 'package:vaani/settings/view/player_settings_page.dart'; import 'scaffold_with_nav_bar.dart'; import 'transitions/slide.dart'; @@ -188,6 +189,12 @@ class MyAppRouter { const NotificationSettingsPage(), ), ), + GoRoute( + path: Routes.playerSettings.pathName, + name: Routes.playerSettings.name, + pageBuilder: + defaultPageBuilder(const PlayerSettingsPage()), + ), ], ), GoRoute( diff --git a/lib/settings/models/app_settings.dart b/lib/settings/models/app_settings.dart index 8ccb320..4b70f64 100644 --- a/lib/settings/models/app_settings.dart +++ b/lib/settings/models/app_settings.dart @@ -44,6 +44,9 @@ class PlayerSettings with _$PlayerSettings { @Default(1) double preferredDefaultVolume, @Default(1) double preferredDefaultSpeed, @Default([0.75, 1, 1.25, 1.5, 1.75, 2]) List speedOptions, + @Default(0.05) double speedIncrement, + @Default(0.1) double minSpeed, + @Default(4) double maxSpeed, @Default(SleepTimerSettings()) SleepTimerSettings sleepTimerSettings, @Default(Duration(seconds: 10)) Duration minimumPositionForReporting, @Default(Duration(seconds: 10)) Duration playbackReportInterval, diff --git a/lib/settings/models/app_settings.freezed.dart b/lib/settings/models/app_settings.freezed.dart index b07b684..415a60a 100644 --- a/lib/settings/models/app_settings.freezed.dart +++ b/lib/settings/models/app_settings.freezed.dart @@ -512,6 +512,9 @@ mixin _$PlayerSettings { double get preferredDefaultVolume => throw _privateConstructorUsedError; double get preferredDefaultSpeed => throw _privateConstructorUsedError; List get speedOptions => throw _privateConstructorUsedError; + double get speedIncrement => throw _privateConstructorUsedError; + double get minSpeed => throw _privateConstructorUsedError; + double get maxSpeed => throw _privateConstructorUsedError; SleepTimerSettings get sleepTimerSettings => throw _privateConstructorUsedError; Duration get minimumPositionForReporting => @@ -542,6 +545,9 @@ abstract class $PlayerSettingsCopyWith<$Res> { double preferredDefaultVolume, double preferredDefaultSpeed, List speedOptions, + double speedIncrement, + double minSpeed, + double maxSpeed, SleepTimerSettings sleepTimerSettings, Duration minimumPositionForReporting, Duration playbackReportInterval, @@ -573,6 +579,9 @@ class _$PlayerSettingsCopyWithImpl<$Res, $Val extends PlayerSettings> Object? preferredDefaultVolume = null, Object? preferredDefaultSpeed = null, Object? speedOptions = null, + Object? speedIncrement = null, + Object? minSpeed = null, + Object? maxSpeed = null, Object? sleepTimerSettings = null, Object? minimumPositionForReporting = null, Object? playbackReportInterval = null, @@ -600,6 +609,18 @@ class _$PlayerSettingsCopyWithImpl<$Res, $Val extends PlayerSettings> ? _value.speedOptions : speedOptions // ignore: cast_nullable_to_non_nullable as List, + speedIncrement: null == speedIncrement + ? _value.speedIncrement + : speedIncrement // ignore: cast_nullable_to_non_nullable + as double, + minSpeed: null == minSpeed + ? _value.minSpeed + : minSpeed // ignore: cast_nullable_to_non_nullable + as double, + maxSpeed: null == maxSpeed + ? _value.maxSpeed + : maxSpeed // ignore: cast_nullable_to_non_nullable + as double, sleepTimerSettings: null == sleepTimerSettings ? _value.sleepTimerSettings : sleepTimerSettings // ignore: cast_nullable_to_non_nullable @@ -671,6 +692,9 @@ abstract class _$$PlayerSettingsImplCopyWith<$Res> double preferredDefaultVolume, double preferredDefaultSpeed, List speedOptions, + double speedIncrement, + double minSpeed, + double maxSpeed, SleepTimerSettings sleepTimerSettings, Duration minimumPositionForReporting, Duration playbackReportInterval, @@ -703,6 +727,9 @@ class __$$PlayerSettingsImplCopyWithImpl<$Res> Object? preferredDefaultVolume = null, Object? preferredDefaultSpeed = null, Object? speedOptions = null, + Object? speedIncrement = null, + Object? minSpeed = null, + Object? maxSpeed = null, Object? sleepTimerSettings = null, Object? minimumPositionForReporting = null, Object? playbackReportInterval = null, @@ -730,6 +757,18 @@ class __$$PlayerSettingsImplCopyWithImpl<$Res> ? _value._speedOptions : speedOptions // ignore: cast_nullable_to_non_nullable as List, + speedIncrement: null == speedIncrement + ? _value.speedIncrement + : speedIncrement // ignore: cast_nullable_to_non_nullable + as double, + minSpeed: null == minSpeed + ? _value.minSpeed + : minSpeed // ignore: cast_nullable_to_non_nullable + as double, + maxSpeed: null == maxSpeed + ? _value.maxSpeed + : maxSpeed // ignore: cast_nullable_to_non_nullable + as double, sleepTimerSettings: null == sleepTimerSettings ? _value.sleepTimerSettings : sleepTimerSettings // ignore: cast_nullable_to_non_nullable @@ -763,6 +802,9 @@ class _$PlayerSettingsImpl implements _PlayerSettings { this.preferredDefaultVolume = 1, this.preferredDefaultSpeed = 1, final List speedOptions = const [0.75, 1, 1.25, 1.5, 1.75, 2], + this.speedIncrement = 0.05, + this.minSpeed = 0.1, + this.maxSpeed = 4, this.sleepTimerSettings = const SleepTimerSettings(), this.minimumPositionForReporting = const Duration(seconds: 10), this.playbackReportInterval = const Duration(seconds: 10), @@ -794,6 +836,15 @@ class _$PlayerSettingsImpl implements _PlayerSettings { return EqualUnmodifiableListView(_speedOptions); } + @override + @JsonKey() + final double speedIncrement; + @override + @JsonKey() + final double minSpeed; + @override + @JsonKey() + final double maxSpeed; @override @JsonKey() final SleepTimerSettings sleepTimerSettings; @@ -812,7 +863,7 @@ class _$PlayerSettingsImpl implements _PlayerSettings { @override String toString() { - return 'PlayerSettings(miniPlayerSettings: $miniPlayerSettings, expandedPlayerSettings: $expandedPlayerSettings, preferredDefaultVolume: $preferredDefaultVolume, preferredDefaultSpeed: $preferredDefaultSpeed, speedOptions: $speedOptions, sleepTimerSettings: $sleepTimerSettings, minimumPositionForReporting: $minimumPositionForReporting, playbackReportInterval: $playbackReportInterval, markCompleteWhenTimeLeft: $markCompleteWhenTimeLeft, configurePlayerForEveryBook: $configurePlayerForEveryBook)'; + return 'PlayerSettings(miniPlayerSettings: $miniPlayerSettings, expandedPlayerSettings: $expandedPlayerSettings, preferredDefaultVolume: $preferredDefaultVolume, preferredDefaultSpeed: $preferredDefaultSpeed, speedOptions: $speedOptions, speedIncrement: $speedIncrement, minSpeed: $minSpeed, maxSpeed: $maxSpeed, sleepTimerSettings: $sleepTimerSettings, minimumPositionForReporting: $minimumPositionForReporting, playbackReportInterval: $playbackReportInterval, markCompleteWhenTimeLeft: $markCompleteWhenTimeLeft, configurePlayerForEveryBook: $configurePlayerForEveryBook)'; } @override @@ -830,6 +881,12 @@ class _$PlayerSettingsImpl implements _PlayerSettings { other.preferredDefaultSpeed == preferredDefaultSpeed) && const DeepCollectionEquality() .equals(other._speedOptions, _speedOptions) && + (identical(other.speedIncrement, speedIncrement) || + other.speedIncrement == speedIncrement) && + (identical(other.minSpeed, minSpeed) || + other.minSpeed == minSpeed) && + (identical(other.maxSpeed, maxSpeed) || + other.maxSpeed == maxSpeed) && (identical(other.sleepTimerSettings, sleepTimerSettings) || other.sleepTimerSettings == sleepTimerSettings) && (identical(other.minimumPositionForReporting, @@ -856,6 +913,9 @@ class _$PlayerSettingsImpl implements _PlayerSettings { preferredDefaultVolume, preferredDefaultSpeed, const DeepCollectionEquality().hash(_speedOptions), + speedIncrement, + minSpeed, + maxSpeed, sleepTimerSettings, minimumPositionForReporting, playbackReportInterval, @@ -886,6 +946,9 @@ abstract class _PlayerSettings implements PlayerSettings { final double preferredDefaultVolume, final double preferredDefaultSpeed, final List speedOptions, + final double speedIncrement, + final double minSpeed, + final double maxSpeed, final SleepTimerSettings sleepTimerSettings, final Duration minimumPositionForReporting, final Duration playbackReportInterval, @@ -906,6 +969,12 @@ abstract class _PlayerSettings implements PlayerSettings { @override List get speedOptions; @override + double get speedIncrement; + @override + double get minSpeed; + @override + double get maxSpeed; + @override SleepTimerSettings get sleepTimerSettings; @override Duration get minimumPositionForReporting; diff --git a/lib/settings/models/app_settings.g.dart b/lib/settings/models/app_settings.g.dart index c1554c7..c01610a 100644 --- a/lib/settings/models/app_settings.g.dart +++ b/lib/settings/models/app_settings.g.dart @@ -69,6 +69,9 @@ _$PlayerSettingsImpl _$$PlayerSettingsImplFromJson(Map json) => ?.map((e) => (e as num).toDouble()) .toList() ?? const [0.75, 1, 1.25, 1.5, 1.75, 2], + speedIncrement: (json['speedIncrement'] as num?)?.toDouble() ?? 0.05, + minSpeed: (json['minSpeed'] as num?)?.toDouble() ?? 0.1, + maxSpeed: (json['maxSpeed'] as num?)?.toDouble() ?? 4, sleepTimerSettings: json['sleepTimerSettings'] == null ? const SleepTimerSettings() : SleepTimerSettings.fromJson( @@ -98,6 +101,9 @@ Map _$$PlayerSettingsImplToJson( 'preferredDefaultVolume': instance.preferredDefaultVolume, 'preferredDefaultSpeed': instance.preferredDefaultSpeed, 'speedOptions': instance.speedOptions, + 'speedIncrement': instance.speedIncrement, + 'minSpeed': instance.minSpeed, + 'maxSpeed': instance.maxSpeed, 'sleepTimerSettings': instance.sleepTimerSettings, 'minimumPositionForReporting': instance.minimumPositionForReporting.inMicroseconds, diff --git a/lib/settings/view/app_settings_page.dart b/lib/settings/view/app_settings_page.dart index bca69fe..bbdf1a3 100644 --- a/lib/settings/view/app_settings_page.dart +++ b/lib/settings/view/app_settings_page.dart @@ -51,6 +51,16 @@ class AppSettingsPage extends HookConsumerWidget { context.pushNamed(Routes.notificationSettings.name); }, ), + SettingsTile( + title: const Text('Player Settings'), + leading: const Icon(Icons.play_arrow), + description: const Text( + 'Customize the player settings', + ), + onPressed: (context) { + context.pushNamed(Routes.playerSettings.name); + }, + ), ], ), // Appearance section diff --git a/lib/settings/view/buttons.dart b/lib/settings/view/buttons.dart new file mode 100644 index 0000000..0dea11f --- /dev/null +++ b/lib/settings/view/buttons.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; + +class OkButton extends StatelessWidget { + const OkButton({ + super.key, + this.onPressed, + }); + + final void Function()? onPressed; + + @override + Widget build(BuildContext context) { + return TextButton( + onPressed: onPressed, + child: const Text('OK'), + ); + } +} + +class CancelButton extends StatelessWidget { + const CancelButton({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text('Cancel'), + ); + } +} diff --git a/lib/settings/view/notification_settings_page.dart b/lib/settings/view/notification_settings_page.dart index df1c5e5..b673add 100644 --- a/lib/settings/view/notification_settings_page.dart +++ b/lib/settings/view/notification_settings_page.dart @@ -4,6 +4,7 @@ import 'package:flutter_settings_ui/flutter_settings_ui.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:vaani/settings/app_settings_provider.dart'; import 'package:vaani/settings/models/app_settings.dart'; +import 'package:vaani/settings/view/buttons.dart'; import 'package:vaani/settings/view/simple_settings_page.dart'; class NotificationSettingsPage extends HookConsumerWidget { @@ -220,17 +221,11 @@ class MediaControlsPicker extends HookConsumerWidget { return AlertDialog( title: const Text('Media Controls'), actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: const Text('Cancel'), - ), - TextButton( + const CancelButton(), + OkButton( onPressed: () { Navigator.of(context).pop(selectedMediaControls.value); - }, - child: const Text('OK'), + } ), ], // a list of chips to easily select the media controls to display @@ -333,17 +328,11 @@ class NotificationTitlePicker extends HookConsumerWidget { return AlertDialog( title: Text(title), actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: const Text('Cancel'), - ), - TextButton( + const CancelButton(), + OkButton( onPressed: () { Navigator.of(context).pop(selectedTitle.value); - }, - child: const Text('OK'), + } ), ], // a list of chips to easily insert available fields into the text field diff --git a/lib/settings/view/player_settings_page.dart b/lib/settings/view/player_settings_page.dart new file mode 100644 index 0000000..c07f8cf --- /dev/null +++ b/lib/settings/view/player_settings_page.dart @@ -0,0 +1,410 @@ +import 'package:duration_picker/duration_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:flutter_settings_ui/flutter_settings_ui.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:vaani/settings/app_settings_provider.dart'; +import 'package:vaani/settings/view/buttons.dart'; +import 'package:vaani/settings/view/simple_settings_page.dart'; +import 'package:vaani/shared/extensions/duration_format.dart'; + +class PlayerSettingsPage extends HookConsumerWidget { + const PlayerSettingsPage({ + super.key, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final appSettings = ref.watch(appSettingsProvider); + final playerSettings = appSettings.playerSettings; + + return SimpleSettingsPage( + title: const Text('Player Settings'), + sections: [ + SettingsSection( + margin: const EdgeInsetsDirectional.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + tiles: [ + // preferred settings for every book + SettingsTile.switchTile( + title: const Text('Remember Player Settings for Every Book'), + leading: const Icon(Icons.settings_applications), + description: const Text( + 'Settings like speed, loudness, etc. will be remembered for every book', + ), + initialValue: playerSettings.configurePlayerForEveryBook, + onToggle: (value) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.playerSettings( + configurePlayerForEveryBook: value, + ), + ); + }, + ), + + // preferred default speed + SettingsTile( + title: const Text('Default Speed'), + description: Text('${playerSettings.preferredDefaultSpeed}x'), + leading: const Icon(Icons.speed), + onPressed: (context) async { + final newSpeed = await showDialog( + context: context, + builder: (context) => SpeedPicker( + initialValue: playerSettings.preferredDefaultSpeed, + ), + ); + if (newSpeed != null) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.playerSettings( + preferredDefaultSpeed: newSpeed, + ), + ); + } + }, + ), + // preferred speed options + SettingsTile( + title: const Text('Speed Options'), + description: Text( + playerSettings.speedOptions.map((e) => '${e}x').join(', '), + ), + leading: const Icon(Icons.speed), + onPressed: (context) async { + final newSpeedOptions = await showDialog?>( + context: context, + builder: (context) => SpeedOptionsPicker( + initialValue: playerSettings.speedOptions, + ), + ); + if (newSpeedOptions != null) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.playerSettings( + speedOptions: newSpeedOptions..sort(), + ), + ); + } + }, + ), + ], + ), + + // Playback Reporting + SettingsSection( + title: const Text('Playback Reporting'), + tiles: [ + SettingsTile( + title: const Text('Minimum Position to Report'), + description: Text.rich( + TextSpan( + text: 'Do not report playback for the first ', + children: [ + TextSpan( + text: playerSettings + .minimumPositionForReporting.smartBinaryFormat, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + const TextSpan(text: ' of the book'), + ], + ), + ), + leading: const Icon(Icons.timer), + onPressed: (context) async { + final newDuration = await showDialog( + context: context, + builder: (context) { + return TimeDurationSelector( + title: const Text('Ignore Playback Position Less Than'), + baseUnit: BaseUnit.second, + initialValue: playerSettings.minimumPositionForReporting, + ); + }, + ); + if (newDuration != null) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.playerSettings( + minimumPositionForReporting: newDuration, + ), + ); + } + }, + ), + // when to mark complete + SettingsTile( + title: const Text('Mark Complete When Time Left'), + description: Text.rich( + TextSpan( + text: 'Mark complete when less than ', + children: [ + TextSpan( + text: playerSettings + .markCompleteWhenTimeLeft.smartBinaryFormat, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + const TextSpan(text: ' left in the book'), + ], + ), + ), + leading: const Icon(Icons.cloud_done), + onPressed: (context) async { + final newDuration = await showDialog( + context: context, + builder: (context) { + return TimeDurationSelector( + title: const Text('Mark Complete When Time Left'), + baseUnit: BaseUnit.second, + initialValue: playerSettings.markCompleteWhenTimeLeft, + ); + }, + ); + if (newDuration != null) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.playerSettings( + markCompleteWhenTimeLeft: newDuration, + ), + ); + } + }, + ), + // playback report interval + SettingsTile( + title: const Text('Playback Report Interval'), + description: Text.rich( + TextSpan( + text: 'Report progress every ', + children: [ + TextSpan( + text: playerSettings + .playbackReportInterval.smartBinaryFormat, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + const TextSpan(text: ' to the server'), + ], + ), + ), + leading: const Icon(Icons.change_circle_outlined), + onPressed: (context) async { + final newDuration = await showDialog( + context: context, + builder: (context) { + return TimeDurationSelector( + title: const Text('Playback Report Interval'), + baseUnit: BaseUnit.second, + initialValue: playerSettings.playbackReportInterval, + ); + }, + ); + if (newDuration != null) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.playerSettings( + playbackReportInterval: newDuration, + ), + ); + } + }, + ), + ], + ), + // Display Settings + SettingsSection( + title: const Text('Display Settings'), + tiles: [ + // show total progress + SettingsTile.switchTile( + title: const Text('Show Total Progress'), + leading: const Icon(Icons.show_chart), + description: const Text( + 'Show the total progress of the book in the player', + ), + initialValue: + playerSettings.expandedPlayerSettings.showTotalProgress, + onToggle: (value) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.playerSettings + .expandedPlayerSettings(showTotalProgress: value), + ); + }, + ), + // show chapter progress + SettingsTile.switchTile( + title: const Text('Show Chapter Progress'), + leading: const Icon(Icons.show_chart), + description: const Text( + 'Show the progress of the current chapter in the player', + ), + initialValue: + playerSettings.expandedPlayerSettings.showChapterProgress, + onToggle: (value) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.playerSettings( + expandedPlayerSettings: playerSettings + .expandedPlayerSettings + .copyWith(showChapterProgress: value), + ), + ); + }, + ), + ], + ), + ], + ); + } +} + +class TimeDurationSelector extends HookConsumerWidget { + const TimeDurationSelector({ + super.key, + this.title = const Text('Select Duration'), + this.baseUnit = BaseUnit.second, + this.initialValue = Duration.zero, + }); + + final Widget title; + final BaseUnit baseUnit; + final Duration initialValue; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final duration = useState(initialValue); + return AlertDialog( + title: title, + content: DurationPicker( + duration: duration.value, + baseUnit: baseUnit, + onChange: (value) { + duration.value = value; + }, + ), + actions: [ + const CancelButton(), + OkButton( + onPressed: () { + Navigator.of(context).pop(duration.value); + }, + ), + ], + ); + } +} + +class SpeedPicker extends HookConsumerWidget { + const SpeedPicker({ + super.key, + this.initialValue = 1, + }); + + final double initialValue; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final speedController = + useTextEditingController(text: initialValue.toString()); + final speed = useState(initialValue); + return AlertDialog( + title: const Text('Select Speed'), + content: TextField( + controller: speedController, + onChanged: (value) => speed.value = double.tryParse(value), + onSubmitted: (value) { + Navigator.of(context).pop(speed.value); + }, + autofocus: true, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + labelText: 'Speed', + helper: Text( + 'Enter the speed you want to set when playing for the first time', + ), + ), + ), + actions: [ + const CancelButton(), + OkButton( + onPressed: () { + Navigator.of(context).pop(speed.value); + }, + ), + ], + ); + } +} + +class SpeedOptionsPicker extends HookConsumerWidget { + const SpeedOptionsPicker({ + super.key, + this.initialValue = const [0.75, 1, 1.25, 1.5, 1.75, 2], + }); + + final List initialValue; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final speedOptionAddController = useTextEditingController(); + final speedOptions = useState>(initialValue); + final focusNode = useFocusNode(); + return AlertDialog( + title: const Text('Select Speed Options'), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Wrap( + spacing: 8.0, + runSpacing: 8.0, + children: speedOptions.value + .map( + (speed) => Chip( + label: Text('${speed}x'), + onDeleted: speed == 1 + ? null + : () { + speedOptions.value = + speedOptions.value.where((element) { + // speed option 1 can't be removed + return element != speed; + }).toList(); + }, + ), + ) + .toList() + ..sort((a, b) { + // if (a.label == const Text('1x')) { + // return -1; + // } else if (b.label == const Text('1x')) { + // return 1; + // } + return a.label.toString().compareTo(b.label.toString()); + }), + ), + TextField( + focusNode: focusNode, + autofocus: true, + controller: speedOptionAddController, + onSubmitted: (value) { + final newSpeed = double.tryParse(value); + if (newSpeed != null && !speedOptions.value.contains(newSpeed)) { + speedOptions.value = [...speedOptions.value, newSpeed]; + } + speedOptionAddController.clear(); + focusNode.requestFocus(); + }, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + labelText: 'Add Speed Option', + helper: Text('Enter a new speed option to add'), + ), + ), + ], + ), + actions: [ + const CancelButton(), + OkButton( + onPressed: () { + Navigator.of(context).pop(speedOptions.value); + }, + ), + ], + ); + } +} diff --git a/lib/settings/view/simple_settings_page.dart b/lib/settings/view/simple_settings_page.dart index 586e986..471b022 100644 --- a/lib/settings/view/simple_settings_page.dart +++ b/lib/settings/view/simple_settings_page.dart @@ -46,6 +46,8 @@ class SimpleSettingsPage extends HookConsumerWidget { ], ), ), + // some padding at the bottom + const SliverPadding(padding: EdgeInsets.only(bottom: 20)), ], ), ); From 2e3b1de52943a16ada45396f76834a206a93cbad Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Thu, 26 Sep 2024 04:48:10 -0400 Subject: [PATCH 17/92] chore: bump version to 0.0.7+1 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 11f5621..11eddba 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.0.6+1 +version: 0.0.7+1 environment: sdk: ">=3.3.4 <4.0.0" From b229c4f2f51318dcba17d7e194eb6ec7ba725162 Mon Sep 17 00:00:00 2001 From: "Dr.Blank" Date: Sat, 28 Sep 2024 01:27:56 -0400 Subject: [PATCH 18/92] feat: add shake detection functionality (#36) * feat: add shake detection functionality and integrate vibration support * feat: add shake detector settings page --- android/app/src/main/AndroidManifest.xml | 1 + assets/sounds/beep.mp3 | Bin 0 -> 6688 bytes .../player/core/audiobook_player.dart | 2 +- .../player/view/player_when_expanded.dart | 19 +- .../shake_detection/core/shake_detector.dart | 79 ++++ .../providers/shake_detector.dart | 138 ++++++ .../providers/shake_detector.g.dart | 26 ++ .../sleep_timer/core/sleep_timer.dart | 30 +- .../providers/sleep_timer_provider.dart | 10 +- .../providers/sleep_timer_provider.g.dart | 2 +- lib/main.dart | 2 + lib/router/constants.dart | 5 + lib/router/router.dart | 8 + lib/settings/models/app_settings.dart | 58 ++- lib/settings/models/app_settings.freezed.dart | 425 +++++++++++++++++- lib/settings/models/app_settings.g.dart | 65 +++ lib/settings/view/app_settings_page.dart | 115 +++-- .../view/notification_settings_page.dart | 68 ++- lib/settings/view/player_settings_page.dart | 24 +- .../view/shake_detector_settings_page.dart | 395 ++++++++++++++++ .../widgets/navigation_with_switch_tile.dart | 56 +++ lib/shared/extensions/duration_format.dart | 10 + lib/shared/extensions/enum.dart | 25 ++ pubspec.lock | 16 + pubspec.yaml | 2 + 25 files changed, 1423 insertions(+), 158 deletions(-) create mode 100644 assets/sounds/beep.mp3 create mode 100644 lib/features/shake_detection/core/shake_detector.dart create mode 100644 lib/features/shake_detection/providers/shake_detector.dart create mode 100644 lib/features/shake_detection/providers/shake_detector.g.dart create mode 100644 lib/settings/view/shake_detector_settings_page.dart create mode 100644 lib/settings/view/widgets/navigation_with_switch_tile.dart create mode 100644 lib/shared/extensions/enum.dart diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 41b686e..cb0a2a5 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -6,6 +6,7 @@ + p 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 a&DMneKNAf2r?3Ai^iMajcHaL^0Q?F6DgG}2 literal 0 HcmV?d00001 diff --git a/lib/features/player/core/audiobook_player.dart b/lib/features/player/core/audiobook_player.dart index 6fe3bfa..726e91d 100644 --- a/lib/features/player/core/audiobook_player.dart +++ b/lib/features/player/core/audiobook_player.dart @@ -281,7 +281,7 @@ extension FormatNotificationTitle on String { (match) { final type = match.group(1); return NotificationTitleType.values - .firstWhere((element) => element.stringValue == type) + .firstWhere((element) => element.name == type) .extractFrom(book) ?? match.group(0) ?? ''; diff --git a/lib/features/player/view/player_when_expanded.dart b/lib/features/player/view/player_when_expanded.dart index 3c8ee41..933121c 100644 --- a/lib/features/player/view/player_when_expanded.dart +++ b/lib/features/player/view/player_when_expanded.dart @@ -11,6 +11,7 @@ import 'package:vaani/features/sleep_timer/core/sleep_timer.dart'; import 'package:vaani/features/sleep_timer/providers/sleep_timer_provider.dart' show sleepTimerProvider; import 'package:vaani/settings/app_settings_provider.dart'; +import 'package:vaani/shared/extensions/duration_format.dart'; import 'package:vaani/shared/extensions/inverse_lerp.dart'; import 'package:vaani/shared/widgets/not_implemented.dart'; @@ -376,8 +377,8 @@ class RemainingSleepTimeDisplay extends HookConsumerWidget { ), child: Text( timer.timer == null - ? timer.duration.formatSingleLargestUnit() - : remainingTime?.formatSingleLargestUnit() ?? '', + ? timer.duration.smartBinaryFormat + : remainingTime?.smartBinaryFormat ?? '', style: Theme.of(context).textTheme.bodyMedium!.copyWith( color: Theme.of(context).colorScheme.onPrimary, ), @@ -385,17 +386,3 @@ class RemainingSleepTimeDisplay extends HookConsumerWidget { ); } } - -extension DurationFormat on Duration { - /// will return a number followed by h, m, or s depending on the duration - /// only the largest unit will be shown - String formatSingleLargestUnit() { - if (inHours > 0) { - return '${inHours}h'; - } else if (inMinutes > 0) { - return '${inMinutes}m'; - } else { - return '${inSeconds}s'; - } - } -} diff --git a/lib/features/shake_detection/core/shake_detector.dart b/lib/features/shake_detection/core/shake_detector.dart new file mode 100644 index 0000000..4b7b719 --- /dev/null +++ b/lib/features/shake_detection/core/shake_detector.dart @@ -0,0 +1,79 @@ +import 'dart:async'; +import 'dart:math'; + +import 'package:logging/logging.dart'; +import 'package:sensors_plus/sensors_plus.dart'; +import 'package:vaani/settings/models/app_settings.dart'; + +final _logger = Logger('ShakeDetector'); + +class ShakeDetector { + final ShakeDetectionSettings _settings; + final Function()? onShakeDetected; + + ShakeDetector( + this._settings, + this.onShakeDetected, { + startImmediately = true, + }) { + _logger.fine('ShakeDetector created with settings: $_settings'); + if (startImmediately) { + start(); + } + } + + StreamSubscription? _accelerometerSubscription; + + int _currentShakeCount = 0; + + DateTime _lastShakeTime = DateTime.now(); + + void start() { + if (_accelerometerSubscription != null) { + _logger.warning('ShakeDetector is already running'); + return; + } + _accelerometerSubscription = + userAccelerometerEventStream(samplingPeriod: _settings.samplingPeriod) + .listen((event) { + if (event.rms > _settings.threshold) { + _currentShakeCount++; + + if (_currentShakeCount >= _settings.shakeTriggerCount && + !isCoolDownNeeded()) { + _logger.fine('Shake detected $_currentShakeCount times'); + + onShakeDetected?.call(); + + _lastShakeTime = DateTime.now(); + _currentShakeCount = 0; + } + } else { + _currentShakeCount = 0; + } + }); + + _logger.fine('ShakeDetector started'); + } + + void stop() { + _currentShakeCount = 0; + _accelerometerSubscription?.cancel(); + _accelerometerSubscription = null; + _logger.fine('ShakeDetector stopped'); + } + + void dispose() { + stop(); + } + + bool isCoolDownNeeded() { + return _lastShakeTime + .add(_settings.shakeTriggerCoolDown) + .isAfter(DateTime.now()); + } +} + +extension UserAccelerometerEventRMS on UserAccelerometerEvent { + double get rms => sqrt(x * x + y * y + z * z); +} diff --git a/lib/features/shake_detection/providers/shake_detector.dart b/lib/features/shake_detection/providers/shake_detector.dart new file mode 100644 index 0000000..956fc16 --- /dev/null +++ b/lib/features/shake_detection/providers/shake_detector.dart @@ -0,0 +1,138 @@ +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:just_audio/just_audio.dart'; +import 'package:logging/logging.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:vaani/features/player/providers/audiobook_player.dart' + show audiobookPlayerProvider, simpleAudiobookPlayerProvider; +import 'package:vaani/features/sleep_timer/providers/sleep_timer_provider.dart' + show sleepTimerProvider; +import 'package:vaani/settings/app_settings_provider.dart' + show appSettingsProvider; +import 'package:vaani/settings/models/app_settings.dart'; +import 'package:vibration/vibration.dart'; + +import '../core/shake_detector.dart' as core; + +part 'shake_detector.g.dart'; + +Logger _logger = Logger('ShakeDetector'); + +@riverpod +class ShakeDetector extends _$ShakeDetector { + @override + core.ShakeDetector? build() { + final appSettings = ref.watch(appSettingsProvider); + final shakeDetectionSettings = appSettings.shakeDetectionSettings; + + if (!shakeDetectionSettings.isEnabled) { + _logger.fine('Shake detection is disabled'); + return null; + } + final player = ref.watch(audiobookPlayerProvider); + if (!player.playing && !shakeDetectionSettings.isActiveWhenPaused) { + _logger.fine( + 'Shake detection is disabled when paused and player is not playing', + ); + return null; + } + // if sleep timer is not enabled, shake detection should not be enabled + final sleepTimer = ref.watch(sleepTimerProvider); + if (!shakeDetectionSettings.isPlaybackManagementEnabled && + sleepTimer == null) { + _logger.fine('No playback management is enabled and sleep timer is off, ' + 'so shake detection is disabled'); + return null; + } + + _logger.fine('Creating shake detector'); + final detector = core.ShakeDetector( + shakeDetectionSettings, + () { + doShakeAction( + shakeDetectionSettings.shakeAction, + ref: ref, + ); + shakeDetectionSettings.feedback.forEach(postShakeFeedback); + }, + ); + ref.onDispose(detector.dispose); + return detector; + } + + void doShakeAction( + ShakeAction shakeAction, { + required Ref ref, + }) { + final player = ref.watch(simpleAudiobookPlayerProvider); + switch (shakeAction) { + case ShakeAction.resetSleepTimer: + _logger.fine('Resetting sleep timer'); + ref.read(sleepTimerProvider.notifier).restartTimer(); + break; + case ShakeAction.fastForward: + _logger.fine('Fast forwarding'); + player.seek(player.position + const Duration(seconds: 30)); + break; + case ShakeAction.rewind: + _logger.fine('Rewinding'); + player.seek(player.position - const Duration(seconds: 30)); + break; + case ShakeAction.playPause: + if (player.book == null) { + _logger.warning('No book is loaded'); + break; + } + player.togglePlayPause(); + break; + default: + break; + } + } + + Future postShakeFeedback(ShakeDetectedFeedback feedback) async { + switch (feedback) { + case ShakeDetectedFeedback.vibrate: + _logger.fine('Vibrating'); + + if (await Vibration.hasAmplitudeControl() ?? false) { + Vibration.vibrate(amplitude: 128, duration: 200); + break; + } + + if (await Vibration.hasVibrator() ?? false) { + Vibration.vibrate(); + break; + } + + _logger.warning('No vibration support'); + + break; + case ShakeDetectedFeedback.beep: + _logger.fine('Beeping'); + final player = AudioPlayer(); + await player.setAsset('assets/sounds/beep.mp3'); + await player.setVolume(0.5); + await player.play(); + await player.dispose(); + break; + default: + break; + } + } +} + +extension on ShakeDetectionSettings { + bool get isActiveWhenPaused { + // If the shake action is play/pause, it should be required when not playing + return shakeAction == ShakeAction.playPause; + } + + bool get isPlaybackManagementEnabled { + return {ShakeAction.playPause, ShakeAction.fastForward, ShakeAction.rewind} + .contains(shakeAction); + } + + bool get shouldActOnSleepTimer { + return {ShakeAction.resetSleepTimer}.contains(shakeAction); + } +} diff --git a/lib/features/shake_detection/providers/shake_detector.g.dart b/lib/features/shake_detection/providers/shake_detector.g.dart new file mode 100644 index 0000000..c3035b8 --- /dev/null +++ b/lib/features/shake_detection/providers/shake_detector.g.dart @@ -0,0 +1,26 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'shake_detector.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$shakeDetectorHash() => r'7bfbdd22f2f43ef3e3858d226d1eb78923e8114d'; + +/// See also [ShakeDetector]. +@ProviderFor(ShakeDetector) +final shakeDetectorProvider = + AutoDisposeNotifierProvider.internal( + ShakeDetector.new, + name: r'shakeDetectorProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$shakeDetectorHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$ShakeDetector = AutoDisposeNotifier; +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/features/sleep_timer/core/sleep_timer.dart b/lib/features/sleep_timer/core/sleep_timer.dart index fb38e0f..728cec1 100644 --- a/lib/features/sleep_timer/core/sleep_timer.dart +++ b/lib/features/sleep_timer/core/sleep_timer.dart @@ -19,7 +19,7 @@ class SleepTimer { set duration(Duration value) { _duration = value; - reset(); + clearCountDownTimer(); } /// The player to be paused @@ -40,7 +40,7 @@ class SleepTimer { player.playbackEventStream.listen((event) { if (event.processingState == ProcessingState.completed || event.processingState == ProcessingState.idle) { - reset(); + clearCountDownTimer(); } }), ); @@ -49,9 +49,9 @@ class SleepTimer { _subscriptions.add( player.playerStateStream.listen((state) { if (state.playing && timer == null) { - startTimer(); + startCountDown(); } else if (!state.playing) { - reset(); + clearCountDownTimer(); } }), ); @@ -59,8 +59,8 @@ class SleepTimer { _logger.fine('created with duration: $duration'); } - /// resets the timer - void reset() { + /// resets the timer and stops it + void clearCountDownTimer() { if (timer != null) { timer!.cancel(); _logger.fine( @@ -70,15 +70,25 @@ class SleepTimer { } } + /// refills the timer with the default duration and starts it if the player is playing + /// if the player is not playing, the timer is stopped + void restartTimer() { + clearCountDownTimer(); + if (player.playing) { + startCountDown(); + } + _logger.fine('restarted timer'); + } + /// starts the timer with the given duration or the default duration - void startTimer([ + void startCountDown([ Duration? forDuration, ]) { - reset(); + clearCountDownTimer(); duration = forDuration ?? duration; timer = Timer(duration, () { player.pause(); - reset(); + clearCountDownTimer(); _logger.fine('paused player after $duration'); }); startedAt = DateTime.now(); @@ -103,7 +113,7 @@ class SleepTimer { /// dispose the timer void dispose() { - reset(); + clearCountDownTimer(); for (var sub in _subscriptions) { sub.cancel(); } diff --git a/lib/features/sleep_timer/providers/sleep_timer_provider.dart b/lib/features/sleep_timer/providers/sleep_timer_provider.dart index 563c34e..6f1b1b7 100644 --- a/lib/features/sleep_timer/providers/sleep_timer_provider.dart +++ b/lib/features/sleep_timer/providers/sleep_timer_provider.dart @@ -1,8 +1,7 @@ import 'package:flutter/material.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:vaani/features/player/providers/audiobook_player.dart'; -import 'package:vaani/features/sleep_timer/core/sleep_timer.dart' - as core; +import 'package:vaani/features/sleep_timer/core/sleep_timer.dart' as core; import 'package:vaani/settings/app_settings_provider.dart'; import 'package:vaani/shared/extensions/time_of_day.dart'; @@ -48,9 +47,16 @@ class SleepTimer extends _$SleepTimer { ); ref.onDispose(timer.dispose); state = timer; + state!.startCountDown(); } } + void restartTimer() { + state?.restartTimer(); + + ref.notifyListeners(); + } + void cancelTimer() { state?.dispose(); state = null; diff --git a/lib/features/sleep_timer/providers/sleep_timer_provider.g.dart b/lib/features/sleep_timer/providers/sleep_timer_provider.g.dart index ef930bf..fe74010 100644 --- a/lib/features/sleep_timer/providers/sleep_timer_provider.g.dart +++ b/lib/features/sleep_timer/providers/sleep_timer_provider.g.dart @@ -6,7 +6,7 @@ part of 'sleep_timer_provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$sleepTimerHash() => r'ad77e82c1b513bbc62815c64ce1ed403f92fc055'; +String _$sleepTimerHash() => r'9d9f20267da91e5483151b58b7d4d7c0762c3ca7'; /// See also [SleepTimer]. @ProviderFor(SleepTimer) diff --git a/lib/main.dart b/lib/main.dart index cea6f7f..3228a8a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,6 +7,7 @@ import 'package:vaani/features/downloads/providers/download_manager.dart'; import 'package:vaani/features/playback_reporting/providers/playback_reporter_provider.dart'; import 'package:vaani/features/player/core/init.dart'; import 'package:vaani/features/player/providers/audiobook_player.dart'; +import 'package:vaani/features/shake_detection/providers/shake_detector.dart'; import 'package:vaani/features/sleep_timer/providers/sleep_timer_provider.dart'; import 'package:vaani/router/router.dart'; import 'package:vaani/settings/api_settings_provider.dart'; @@ -93,6 +94,7 @@ class _EagerInitialization extends ConsumerWidget { ref.watch(sleepTimerProvider); ref.watch(playbackReporterProvider); ref.watch(simpleDownloadManagerProvider); + ref.watch(shakeDetectorProvider); } catch (e) { debugPrintStack(stackTrace: StackTrace.current, label: e.toString()); } diff --git a/lib/router/constants.dart b/lib/router/constants.dart index 71bb446..4d8e7c1 100644 --- a/lib/router/constants.dart +++ b/lib/router/constants.dart @@ -42,6 +42,11 @@ class Routes { name: 'playerSettings', parentRoute: settings, ); + static const shakeDetectorSettings = _SimpleRoute( + pathName: 'shakeDetector', + name: 'shakeDetectorSettings', + parentRoute: settings, + ); // search and explore static const search = _SimpleRoute( diff --git a/lib/router/router.dart b/lib/router/router.dart index edf9433..8910fc3 100644 --- a/lib/router/router.dart +++ b/lib/router/router.dart @@ -14,6 +14,7 @@ import 'package:vaani/settings/view/app_settings_page.dart'; import 'package:vaani/settings/view/auto_sleep_timer_settings_page.dart'; import 'package:vaani/settings/view/notification_settings_page.dart'; import 'package:vaani/settings/view/player_settings_page.dart'; +import 'package:vaani/settings/view/shake_detector_settings_page.dart'; import 'scaffold_with_nav_bar.dart'; import 'transitions/slide.dart'; @@ -195,6 +196,13 @@ class MyAppRouter { pageBuilder: defaultPageBuilder(const PlayerSettingsPage()), ), + GoRoute( + path: Routes.shakeDetectorSettings.pathName, + name: Routes.shakeDetectorSettings.name, + pageBuilder: defaultPageBuilder( + const ShakeDetectorSettingsPage(), + ), + ), ], ), GoRoute( diff --git a/lib/settings/models/app_settings.dart b/lib/settings/models/app_settings.dart index 4b70f64..09a07e2 100644 --- a/lib/settings/models/app_settings.dart +++ b/lib/settings/models/app_settings.dart @@ -16,6 +16,8 @@ class AppSettings with _$AppSettings { @Default(PlayerSettings()) PlayerSettings playerSettings, @Default(DownloadSettings()) DownloadSettings downloadSettings, @Default(NotificationSettings()) NotificationSettings notificationSettings, + @Default(ShakeDetectionSettings()) + ShakeDetectionSettings shakeDetectionSettings, }) = _AppSettings; factory AppSettings.fromJson(Map json) => @@ -165,17 +167,13 @@ class NotificationSettings with _$NotificationSettings { } enum NotificationTitleType { - chapterTitle('chapterTitle'), - bookTitle('bookTitle'), - author('author'), - subtitle('subtitle'), - series('series'), - narrator('narrator'), - year('year'); - - const NotificationTitleType(this.stringValue); - - final String stringValue; + chapterTitle, + bookTitle, + author, + subtitle, + series, + narrator, + year, } enum NotificationMediaControl { @@ -190,3 +188,41 @@ enum NotificationMediaControl { final IconData icon; } + +/// Shake Detection Settings +@freezed +class ShakeDetectionSettings with _$ShakeDetectionSettings { + const factory ShakeDetectionSettings({ + @Default(true) bool isEnabled, + @Default(ShakeDirection.horizontal) ShakeDirection direction, + @Default(5) double threshold, + @Default(ShakeAction.resetSleepTimer) ShakeAction shakeAction, + @Default({ShakeDetectedFeedback.vibrate, ShakeDetectedFeedback.beep}) + Set feedback, + @Default(0.5) double beepVolume, + + /// the duration to wait before the shake detection is enabled again + @Default(Duration(seconds: 5)) Duration shakeTriggerCoolDown, + + /// the number of shakes required to trigger the action + @Default(2) int shakeTriggerCount, + + /// acceleration sampling interval + @Default(Duration(milliseconds: 100)) Duration samplingPeriod, + }) = _ShakeDetectionSettings; + + factory ShakeDetectionSettings.fromJson(Map json) => + _$ShakeDetectionSettingsFromJson(json); +} + +enum ShakeDirection { horizontal, vertical } + +enum ShakeAction { + none, + playPause, + resetSleepTimer, + fastForward, + rewind, +} + +enum ShakeDetectedFeedback { vibrate, beep } diff --git a/lib/settings/models/app_settings.freezed.dart b/lib/settings/models/app_settings.freezed.dart index 415a60a..3c1d9f4 100644 --- a/lib/settings/models/app_settings.freezed.dart +++ b/lib/settings/models/app_settings.freezed.dart @@ -25,6 +25,8 @@ mixin _$AppSettings { DownloadSettings get downloadSettings => throw _privateConstructorUsedError; NotificationSettings get notificationSettings => throw _privateConstructorUsedError; + ShakeDetectionSettings get shakeDetectionSettings => + throw _privateConstructorUsedError; /// Serializes this AppSettings to a JSON map. Map toJson() => throw _privateConstructorUsedError; @@ -46,12 +48,14 @@ abstract class $AppSettingsCopyWith<$Res> { {ThemeSettings themeSettings, PlayerSettings playerSettings, DownloadSettings downloadSettings, - NotificationSettings notificationSettings}); + NotificationSettings notificationSettings, + ShakeDetectionSettings shakeDetectionSettings}); $ThemeSettingsCopyWith<$Res> get themeSettings; $PlayerSettingsCopyWith<$Res> get playerSettings; $DownloadSettingsCopyWith<$Res> get downloadSettings; $NotificationSettingsCopyWith<$Res> get notificationSettings; + $ShakeDetectionSettingsCopyWith<$Res> get shakeDetectionSettings; } /// @nodoc @@ -73,6 +77,7 @@ class _$AppSettingsCopyWithImpl<$Res, $Val extends AppSettings> Object? playerSettings = null, Object? downloadSettings = null, Object? notificationSettings = null, + Object? shakeDetectionSettings = null, }) { return _then(_value.copyWith( themeSettings: null == themeSettings @@ -91,6 +96,10 @@ class _$AppSettingsCopyWithImpl<$Res, $Val extends AppSettings> ? _value.notificationSettings : notificationSettings // ignore: cast_nullable_to_non_nullable as NotificationSettings, + shakeDetectionSettings: null == shakeDetectionSettings + ? _value.shakeDetectionSettings + : shakeDetectionSettings // ignore: cast_nullable_to_non_nullable + as ShakeDetectionSettings, ) as $Val); } @@ -134,6 +143,17 @@ class _$AppSettingsCopyWithImpl<$Res, $Val extends AppSettings> return _then(_value.copyWith(notificationSettings: value) as $Val); }); } + + /// Create a copy of AppSettings + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ShakeDetectionSettingsCopyWith<$Res> get shakeDetectionSettings { + return $ShakeDetectionSettingsCopyWith<$Res>(_value.shakeDetectionSettings, + (value) { + return _then(_value.copyWith(shakeDetectionSettings: value) as $Val); + }); + } } /// @nodoc @@ -148,7 +168,8 @@ abstract class _$$AppSettingsImplCopyWith<$Res> {ThemeSettings themeSettings, PlayerSettings playerSettings, DownloadSettings downloadSettings, - NotificationSettings notificationSettings}); + NotificationSettings notificationSettings, + ShakeDetectionSettings shakeDetectionSettings}); @override $ThemeSettingsCopyWith<$Res> get themeSettings; @@ -158,6 +179,8 @@ abstract class _$$AppSettingsImplCopyWith<$Res> $DownloadSettingsCopyWith<$Res> get downloadSettings; @override $NotificationSettingsCopyWith<$Res> get notificationSettings; + @override + $ShakeDetectionSettingsCopyWith<$Res> get shakeDetectionSettings; } /// @nodoc @@ -177,6 +200,7 @@ class __$$AppSettingsImplCopyWithImpl<$Res> Object? playerSettings = null, Object? downloadSettings = null, Object? notificationSettings = null, + Object? shakeDetectionSettings = null, }) { return _then(_$AppSettingsImpl( themeSettings: null == themeSettings @@ -195,6 +219,10 @@ class __$$AppSettingsImplCopyWithImpl<$Res> ? _value.notificationSettings : notificationSettings // ignore: cast_nullable_to_non_nullable as NotificationSettings, + shakeDetectionSettings: null == shakeDetectionSettings + ? _value.shakeDetectionSettings + : shakeDetectionSettings // ignore: cast_nullable_to_non_nullable + as ShakeDetectionSettings, )); } } @@ -206,7 +234,8 @@ class _$AppSettingsImpl implements _AppSettings { {this.themeSettings = const ThemeSettings(), this.playerSettings = const PlayerSettings(), this.downloadSettings = const DownloadSettings(), - this.notificationSettings = const NotificationSettings()}); + this.notificationSettings = const NotificationSettings(), + this.shakeDetectionSettings = const ShakeDetectionSettings()}); factory _$AppSettingsImpl.fromJson(Map json) => _$$AppSettingsImplFromJson(json); @@ -223,10 +252,13 @@ class _$AppSettingsImpl implements _AppSettings { @override @JsonKey() final NotificationSettings notificationSettings; + @override + @JsonKey() + final ShakeDetectionSettings shakeDetectionSettings; @override String toString() { - return 'AppSettings(themeSettings: $themeSettings, playerSettings: $playerSettings, downloadSettings: $downloadSettings, notificationSettings: $notificationSettings)'; + return 'AppSettings(themeSettings: $themeSettings, playerSettings: $playerSettings, downloadSettings: $downloadSettings, notificationSettings: $notificationSettings, shakeDetectionSettings: $shakeDetectionSettings)'; } @override @@ -241,13 +273,15 @@ class _$AppSettingsImpl implements _AppSettings { (identical(other.downloadSettings, downloadSettings) || other.downloadSettings == downloadSettings) && (identical(other.notificationSettings, notificationSettings) || - other.notificationSettings == notificationSettings)); + other.notificationSettings == notificationSettings) && + (identical(other.shakeDetectionSettings, shakeDetectionSettings) || + other.shakeDetectionSettings == shakeDetectionSettings)); } @JsonKey(includeFromJson: false, includeToJson: false) @override int get hashCode => Object.hash(runtimeType, themeSettings, playerSettings, - downloadSettings, notificationSettings); + downloadSettings, notificationSettings, shakeDetectionSettings); /// Create a copy of AppSettings /// with the given fields replaced by the non-null parameter values. @@ -270,7 +304,8 @@ abstract class _AppSettings implements AppSettings { {final ThemeSettings themeSettings, final PlayerSettings playerSettings, final DownloadSettings downloadSettings, - final NotificationSettings notificationSettings}) = _$AppSettingsImpl; + final NotificationSettings notificationSettings, + final ShakeDetectionSettings shakeDetectionSettings}) = _$AppSettingsImpl; factory _AppSettings.fromJson(Map json) = _$AppSettingsImpl.fromJson; @@ -283,6 +318,8 @@ abstract class _AppSettings implements AppSettings { DownloadSettings get downloadSettings; @override NotificationSettings get notificationSettings; + @override + ShakeDetectionSettings get shakeDetectionSettings; /// Create a copy of AppSettings /// with the given fields replaced by the non-null parameter values. @@ -2381,3 +2418,377 @@ abstract class _NotificationSettings implements NotificationSettings { _$$NotificationSettingsImplCopyWith<_$NotificationSettingsImpl> get copyWith => throw _privateConstructorUsedError; } + +ShakeDetectionSettings _$ShakeDetectionSettingsFromJson( + Map json) { + return _ShakeDetectionSettings.fromJson(json); +} + +/// @nodoc +mixin _$ShakeDetectionSettings { + bool get isEnabled => throw _privateConstructorUsedError; + ShakeDirection get direction => throw _privateConstructorUsedError; + double get threshold => throw _privateConstructorUsedError; + ShakeAction get shakeAction => throw _privateConstructorUsedError; + Set get feedback => throw _privateConstructorUsedError; + double get beepVolume => throw _privateConstructorUsedError; + + /// the duration to wait before the shake detection is enabled again + Duration get shakeTriggerCoolDown => throw _privateConstructorUsedError; + + /// the number of shakes required to trigger the action + int get shakeTriggerCount => throw _privateConstructorUsedError; + + /// acceleration sampling interval + Duration get samplingPeriod => throw _privateConstructorUsedError; + + /// Serializes this ShakeDetectionSettings to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of ShakeDetectionSettings + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ShakeDetectionSettingsCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ShakeDetectionSettingsCopyWith<$Res> { + factory $ShakeDetectionSettingsCopyWith(ShakeDetectionSettings value, + $Res Function(ShakeDetectionSettings) then) = + _$ShakeDetectionSettingsCopyWithImpl<$Res, ShakeDetectionSettings>; + @useResult + $Res call( + {bool isEnabled, + ShakeDirection direction, + double threshold, + ShakeAction shakeAction, + Set feedback, + double beepVolume, + Duration shakeTriggerCoolDown, + int shakeTriggerCount, + Duration samplingPeriod}); +} + +/// @nodoc +class _$ShakeDetectionSettingsCopyWithImpl<$Res, + $Val extends ShakeDetectionSettings> + implements $ShakeDetectionSettingsCopyWith<$Res> { + _$ShakeDetectionSettingsCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ShakeDetectionSettings + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? isEnabled = null, + Object? direction = null, + Object? threshold = null, + Object? shakeAction = null, + Object? feedback = null, + Object? beepVolume = null, + Object? shakeTriggerCoolDown = null, + Object? shakeTriggerCount = null, + Object? samplingPeriod = null, + }) { + return _then(_value.copyWith( + isEnabled: null == isEnabled + ? _value.isEnabled + : isEnabled // ignore: cast_nullable_to_non_nullable + as bool, + direction: null == direction + ? _value.direction + : direction // ignore: cast_nullable_to_non_nullable + as ShakeDirection, + threshold: null == threshold + ? _value.threshold + : threshold // ignore: cast_nullable_to_non_nullable + as double, + shakeAction: null == shakeAction + ? _value.shakeAction + : shakeAction // ignore: cast_nullable_to_non_nullable + as ShakeAction, + feedback: null == feedback + ? _value.feedback + : feedback // ignore: cast_nullable_to_non_nullable + as Set, + beepVolume: null == beepVolume + ? _value.beepVolume + : beepVolume // ignore: cast_nullable_to_non_nullable + as double, + shakeTriggerCoolDown: null == shakeTriggerCoolDown + ? _value.shakeTriggerCoolDown + : shakeTriggerCoolDown // ignore: cast_nullable_to_non_nullable + as Duration, + shakeTriggerCount: null == shakeTriggerCount + ? _value.shakeTriggerCount + : shakeTriggerCount // ignore: cast_nullable_to_non_nullable + as int, + samplingPeriod: null == samplingPeriod + ? _value.samplingPeriod + : samplingPeriod // ignore: cast_nullable_to_non_nullable + as Duration, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$ShakeDetectionSettingsImplCopyWith<$Res> + implements $ShakeDetectionSettingsCopyWith<$Res> { + factory _$$ShakeDetectionSettingsImplCopyWith( + _$ShakeDetectionSettingsImpl value, + $Res Function(_$ShakeDetectionSettingsImpl) then) = + __$$ShakeDetectionSettingsImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {bool isEnabled, + ShakeDirection direction, + double threshold, + ShakeAction shakeAction, + Set feedback, + double beepVolume, + Duration shakeTriggerCoolDown, + int shakeTriggerCount, + Duration samplingPeriod}); +} + +/// @nodoc +class __$$ShakeDetectionSettingsImplCopyWithImpl<$Res> + extends _$ShakeDetectionSettingsCopyWithImpl<$Res, + _$ShakeDetectionSettingsImpl> + implements _$$ShakeDetectionSettingsImplCopyWith<$Res> { + __$$ShakeDetectionSettingsImplCopyWithImpl( + _$ShakeDetectionSettingsImpl _value, + $Res Function(_$ShakeDetectionSettingsImpl) _then) + : super(_value, _then); + + /// Create a copy of ShakeDetectionSettings + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? isEnabled = null, + Object? direction = null, + Object? threshold = null, + Object? shakeAction = null, + Object? feedback = null, + Object? beepVolume = null, + Object? shakeTriggerCoolDown = null, + Object? shakeTriggerCount = null, + Object? samplingPeriod = null, + }) { + return _then(_$ShakeDetectionSettingsImpl( + isEnabled: null == isEnabled + ? _value.isEnabled + : isEnabled // ignore: cast_nullable_to_non_nullable + as bool, + direction: null == direction + ? _value.direction + : direction // ignore: cast_nullable_to_non_nullable + as ShakeDirection, + threshold: null == threshold + ? _value.threshold + : threshold // ignore: cast_nullable_to_non_nullable + as double, + shakeAction: null == shakeAction + ? _value.shakeAction + : shakeAction // ignore: cast_nullable_to_non_nullable + as ShakeAction, + feedback: null == feedback + ? _value._feedback + : feedback // ignore: cast_nullable_to_non_nullable + as Set, + beepVolume: null == beepVolume + ? _value.beepVolume + : beepVolume // ignore: cast_nullable_to_non_nullable + as double, + shakeTriggerCoolDown: null == shakeTriggerCoolDown + ? _value.shakeTriggerCoolDown + : shakeTriggerCoolDown // ignore: cast_nullable_to_non_nullable + as Duration, + shakeTriggerCount: null == shakeTriggerCount + ? _value.shakeTriggerCount + : shakeTriggerCount // ignore: cast_nullable_to_non_nullable + as int, + samplingPeriod: null == samplingPeriod + ? _value.samplingPeriod + : samplingPeriod // ignore: cast_nullable_to_non_nullable + as Duration, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$ShakeDetectionSettingsImpl implements _ShakeDetectionSettings { + const _$ShakeDetectionSettingsImpl( + {this.isEnabled = true, + this.direction = ShakeDirection.horizontal, + this.threshold = 5, + this.shakeAction = ShakeAction.resetSleepTimer, + final Set feedback = const { + ShakeDetectedFeedback.vibrate, + ShakeDetectedFeedback.beep + }, + this.beepVolume = 0.5, + this.shakeTriggerCoolDown = const Duration(seconds: 5), + this.shakeTriggerCount = 2, + this.samplingPeriod = const Duration(milliseconds: 100)}) + : _feedback = feedback; + + factory _$ShakeDetectionSettingsImpl.fromJson(Map json) => + _$$ShakeDetectionSettingsImplFromJson(json); + + @override + @JsonKey() + final bool isEnabled; + @override + @JsonKey() + final ShakeDirection direction; + @override + @JsonKey() + final double threshold; + @override + @JsonKey() + final ShakeAction shakeAction; + final Set _feedback; + @override + @JsonKey() + Set get feedback { + if (_feedback is EqualUnmodifiableSetView) return _feedback; + // ignore: implicit_dynamic_type + return EqualUnmodifiableSetView(_feedback); + } + + @override + @JsonKey() + final double beepVolume; + + /// the duration to wait before the shake detection is enabled again + @override + @JsonKey() + final Duration shakeTriggerCoolDown; + + /// the number of shakes required to trigger the action + @override + @JsonKey() + final int shakeTriggerCount; + + /// acceleration sampling interval + @override + @JsonKey() + final Duration samplingPeriod; + + @override + String toString() { + return 'ShakeDetectionSettings(isEnabled: $isEnabled, direction: $direction, threshold: $threshold, shakeAction: $shakeAction, feedback: $feedback, beepVolume: $beepVolume, shakeTriggerCoolDown: $shakeTriggerCoolDown, shakeTriggerCount: $shakeTriggerCount, samplingPeriod: $samplingPeriod)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ShakeDetectionSettingsImpl && + (identical(other.isEnabled, isEnabled) || + other.isEnabled == isEnabled) && + (identical(other.direction, direction) || + other.direction == direction) && + (identical(other.threshold, threshold) || + other.threshold == threshold) && + (identical(other.shakeAction, shakeAction) || + other.shakeAction == shakeAction) && + const DeepCollectionEquality().equals(other._feedback, _feedback) && + (identical(other.beepVolume, beepVolume) || + other.beepVolume == beepVolume) && + (identical(other.shakeTriggerCoolDown, shakeTriggerCoolDown) || + other.shakeTriggerCoolDown == shakeTriggerCoolDown) && + (identical(other.shakeTriggerCount, shakeTriggerCount) || + other.shakeTriggerCount == shakeTriggerCount) && + (identical(other.samplingPeriod, samplingPeriod) || + other.samplingPeriod == samplingPeriod)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + isEnabled, + direction, + threshold, + shakeAction, + const DeepCollectionEquality().hash(_feedback), + beepVolume, + shakeTriggerCoolDown, + shakeTriggerCount, + samplingPeriod); + + /// Create a copy of ShakeDetectionSettings + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ShakeDetectionSettingsImplCopyWith<_$ShakeDetectionSettingsImpl> + get copyWith => __$$ShakeDetectionSettingsImplCopyWithImpl< + _$ShakeDetectionSettingsImpl>(this, _$identity); + + @override + Map toJson() { + return _$$ShakeDetectionSettingsImplToJson( + this, + ); + } +} + +abstract class _ShakeDetectionSettings implements ShakeDetectionSettings { + const factory _ShakeDetectionSettings( + {final bool isEnabled, + final ShakeDirection direction, + final double threshold, + final ShakeAction shakeAction, + final Set feedback, + final double beepVolume, + final Duration shakeTriggerCoolDown, + final int shakeTriggerCount, + final Duration samplingPeriod}) = _$ShakeDetectionSettingsImpl; + + factory _ShakeDetectionSettings.fromJson(Map json) = + _$ShakeDetectionSettingsImpl.fromJson; + + @override + bool get isEnabled; + @override + ShakeDirection get direction; + @override + double get threshold; + @override + ShakeAction get shakeAction; + @override + Set get feedback; + @override + double get beepVolume; + + /// the duration to wait before the shake detection is enabled again + @override + Duration get shakeTriggerCoolDown; + + /// the number of shakes required to trigger the action + @override + int get shakeTriggerCount; + + /// acceleration sampling interval + @override + Duration get samplingPeriod; + + /// Create a copy of ShakeDetectionSettings + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ShakeDetectionSettingsImplCopyWith<_$ShakeDetectionSettingsImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/settings/models/app_settings.g.dart b/lib/settings/models/app_settings.g.dart index c01610a..3b0784f 100644 --- a/lib/settings/models/app_settings.g.dart +++ b/lib/settings/models/app_settings.g.dart @@ -24,6 +24,10 @@ _$AppSettingsImpl _$$AppSettingsImplFromJson(Map json) => ? const NotificationSettings() : NotificationSettings.fromJson( json['notificationSettings'] as Map), + shakeDetectionSettings: json['shakeDetectionSettings'] == null + ? const ShakeDetectionSettings() + : ShakeDetectionSettings.fromJson( + json['shakeDetectionSettings'] as Map), ); Map _$$AppSettingsImplToJson(_$AppSettingsImpl instance) => @@ -32,6 +36,7 @@ Map _$$AppSettingsImplToJson(_$AppSettingsImpl instance) => 'playerSettings': instance.playerSettings, 'downloadSettings': instance.downloadSettings, 'notificationSettings': instance.notificationSettings, + 'shakeDetectionSettings': instance.shakeDetectionSettings, }; _$ThemeSettingsImpl _$$ThemeSettingsImplFromJson(Map json) => @@ -274,3 +279,63 @@ const _$NotificationMediaControlEnumMap = { NotificationMediaControl.skipToNextChapter: 'skipToNextChapter', NotificationMediaControl.skipToPreviousChapter: 'skipToPreviousChapter', }; + +_$ShakeDetectionSettingsImpl _$$ShakeDetectionSettingsImplFromJson( + Map json) => + _$ShakeDetectionSettingsImpl( + isEnabled: json['isEnabled'] as bool? ?? true, + direction: + $enumDecodeNullable(_$ShakeDirectionEnumMap, json['direction']) ?? + ShakeDirection.horizontal, + threshold: (json['threshold'] as num?)?.toDouble() ?? 5, + shakeAction: + $enumDecodeNullable(_$ShakeActionEnumMap, json['shakeAction']) ?? + ShakeAction.resetSleepTimer, + feedback: (json['feedback'] as List?) + ?.map((e) => $enumDecode(_$ShakeDetectedFeedbackEnumMap, e)) + .toSet() ?? + const {ShakeDetectedFeedback.vibrate, ShakeDetectedFeedback.beep}, + beepVolume: (json['beepVolume'] as num?)?.toDouble() ?? 0.5, + shakeTriggerCoolDown: json['shakeTriggerCoolDown'] == null + ? const Duration(seconds: 5) + : Duration( + microseconds: (json['shakeTriggerCoolDown'] as num).toInt()), + shakeTriggerCount: (json['shakeTriggerCount'] as num?)?.toInt() ?? 2, + samplingPeriod: json['samplingPeriod'] == null + ? const Duration(milliseconds: 100) + : Duration(microseconds: (json['samplingPeriod'] as num).toInt()), + ); + +Map _$$ShakeDetectionSettingsImplToJson( + _$ShakeDetectionSettingsImpl instance) => + { + 'isEnabled': instance.isEnabled, + 'direction': _$ShakeDirectionEnumMap[instance.direction]!, + 'threshold': instance.threshold, + 'shakeAction': _$ShakeActionEnumMap[instance.shakeAction]!, + 'feedback': instance.feedback + .map((e) => _$ShakeDetectedFeedbackEnumMap[e]!) + .toList(), + 'beepVolume': instance.beepVolume, + 'shakeTriggerCoolDown': instance.shakeTriggerCoolDown.inMicroseconds, + 'shakeTriggerCount': instance.shakeTriggerCount, + 'samplingPeriod': instance.samplingPeriod.inMicroseconds, + }; + +const _$ShakeDirectionEnumMap = { + ShakeDirection.horizontal: 'horizontal', + ShakeDirection.vertical: 'vertical', +}; + +const _$ShakeActionEnumMap = { + ShakeAction.none: 'none', + ShakeAction.playPause: 'playPause', + ShakeAction.resetSleepTimer: 'resetSleepTimer', + ShakeAction.fastForward: 'fastForward', + ShakeAction.rewind: 'rewind', +}; + +const _$ShakeDetectedFeedbackEnumMap = { + ShakeDetectedFeedback.vibrate: 'vibrate', + ShakeDetectedFeedback.beep: 'beep', +}; diff --git a/lib/settings/view/app_settings_page.dart b/lib/settings/view/app_settings_page.dart index bbdf1a3..58754c6 100644 --- a/lib/settings/view/app_settings_page.dart +++ b/lib/settings/view/app_settings_page.dart @@ -12,6 +12,7 @@ import 'package:vaani/router/router.dart'; import 'package:vaani/settings/app_settings_provider.dart'; import 'package:vaani/settings/models/app_settings.dart' as model; import 'package:vaani/settings/view/simple_settings_page.dart'; +import 'package:vaani/settings/view/widgets/navigation_with_switch_tile.dart'; class AppSettingsPage extends HookConsumerWidget { const AppSettingsPage({ @@ -30,39 +31,6 @@ class AppSettingsPage extends HookConsumerWidget { return SimpleSettingsPage( title: const Text('App Settings'), sections: [ - // General section - SettingsSection( - margin: const EdgeInsetsDirectional.symmetric( - horizontal: 16.0, - vertical: 8.0, - ), - title: Text( - 'General', - style: Theme.of(context).textTheme.titleLarge, - ), - tiles: [ - SettingsTile( - title: const Text('Notification Media Player'), - leading: const Icon(Icons.play_lesson), - description: const Text( - 'Customize the media player in notifications', - ), - onPressed: (context) { - context.pushNamed(Routes.notificationSettings.name); - }, - ), - SettingsTile( - title: const Text('Player Settings'), - leading: const Icon(Icons.play_arrow), - description: const Text( - 'Customize the player settings', - ), - onPressed: (context) { - context.pushNamed(Routes.playerSettings.name); - }, - ), - ], - ), // Appearance section SettingsSection( margin: const EdgeInsetsDirectional.symmetric( @@ -106,20 +74,19 @@ class AppSettingsPage extends HookConsumerWidget { ], ), - // Sleep Timer section + // General section SettingsSection( margin: const EdgeInsetsDirectional.symmetric( horizontal: 16.0, vertical: 8.0, ), title: Text( - 'Sleep Timer', + 'General', style: Theme.of(context).textTheme.titleLarge, ), tiles: [ - SettingsTile.navigation( - // initialValue: sleepTimerSettings.autoTurnOnTimer, - title: const Text('Auto Turn On Timer'), + NavigationWithSwitchTile( + title: const Text('Auto Turn On Sleep Timer'), description: const Text( 'Automatically turn on the sleep timer based on the time of day', ), @@ -127,39 +94,57 @@ class AppSettingsPage extends HookConsumerWidget { ? const Icon(Icons.timer) : const Icon(Icons.timer_off), onPressed: (context) { - // push the sleep timer settings page context.pushNamed(Routes.autoSleepTimerSettings.name); }, - // a switch to enable or disable the auto turn off time - trailing: IntrinsicHeight( - child: Row( - children: [ - VerticalDivider( - color: Theme.of(context).dividerColor.withOpacity(0.5), - indent: 8.0, - endIndent: 8.0, - // width: 8.0, - // thickness: 2.0, - // height: 24.0, - ), - Switch( - value: sleepTimerSettings.autoTurnOnTimer, - onChanged: (value) { - ref.read(appSettingsProvider.notifier).update( - appSettings.copyWith.playerSettings - .sleepTimerSettings( - autoTurnOnTimer: value, - ), - ); - }, - ), - ], - ), + value: sleepTimerSettings.autoTurnOnTimer, + onToggle: (value) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.playerSettings.sleepTimerSettings( + autoTurnOnTimer: value, + ), + ); + }, + ), + SettingsTile( + title: const Text('Notification Media Player'), + leading: const Icon(Icons.play_lesson), + description: const Text( + 'Customize the media player in notifications', ), + onPressed: (context) { + context.pushNamed(Routes.notificationSettings.name); + }, + ), + SettingsTile( + title: const Text('Player Settings'), + leading: const Icon(Icons.play_arrow), + description: const Text( + 'Customize the player settings', + ), + onPressed: (context) { + context.pushNamed(Routes.playerSettings.name); + }, + ), + NavigationWithSwitchTile( + title: const Text('Shake Detector'), + leading: const Icon(Icons.vibration), + description: const Text( + 'Customize the shake detector settings', + ), + value: appSettings.shakeDetectionSettings.isEnabled, + onPressed: (context) { + context.pushNamed(Routes.shakeDetectorSettings.name); + }, + onToggle: (value) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.shakeDetectionSettings( + isEnabled: value, + ), + ); + }, ), ], ), - // Backup and Restore section SettingsSection( margin: const EdgeInsetsDirectional.symmetric( diff --git a/lib/settings/view/notification_settings_page.dart b/lib/settings/view/notification_settings_page.dart index b673add..140d21c 100644 --- a/lib/settings/view/notification_settings_page.dart +++ b/lib/settings/view/notification_settings_page.dart @@ -6,6 +6,7 @@ import 'package:vaani/settings/app_settings_provider.dart'; import 'package:vaani/settings/models/app_settings.dart'; import 'package:vaani/settings/view/buttons.dart'; import 'package:vaani/settings/view/simple_settings_page.dart'; +import 'package:vaani/shared/extensions/enum.dart'; class NotificationSettingsPage extends HookConsumerWidget { const NotificationSettingsPage({ @@ -16,7 +17,7 @@ class NotificationSettingsPage extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final appSettings = ref.watch(appSettingsProvider); final notificationSettings = appSettings.notificationSettings; - + final primaryColor = Theme.of(context).colorScheme.primary; return SimpleSettingsPage( title: const Text('Notification Settings'), sections: [ @@ -37,7 +38,10 @@ class NotificationSettingsPage extends HookConsumerWidget { children: [ TextSpan( text: notificationSettings.primaryTitle, - style: const TextStyle(fontWeight: FontWeight.bold), + style: TextStyle( + fontWeight: FontWeight.bold, + color: primaryColor, + ), ), ], ), @@ -72,7 +76,10 @@ class NotificationSettingsPage extends HookConsumerWidget { children: [ TextSpan( text: notificationSettings.secondaryTitle, - style: const TextStyle(fontWeight: FontWeight.bold), + style: TextStyle( + fontWeight: FontWeight.bold, + color: primaryColor, + ), ), ], ), @@ -151,19 +158,17 @@ class NotificationSettingsPage extends HookConsumerWidget { title: const Text('Media Controls'), leading: const Icon(Icons.control_camera), // description: const Text('Select the media controls to display'), - description: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text('Select the media controls to display'), - Wrap( - spacing: 8.0, - children: notificationSettings.mediaControls - .map( - (control) => Icon(control.icon), - ) - .toList(), - ), - ], + description: const Text('Select the media controls to display'), + trailing: Wrap( + spacing: 8.0, + children: notificationSettings.mediaControls + .map( + (control) => Icon( + control.icon, + color: primaryColor, + ), + ) + .toList(), ), onPressed: (context) async { final selectedControls = @@ -225,7 +230,7 @@ class MediaControlsPicker extends HookConsumerWidget { OkButton( onPressed: () { Navigator.of(context).pop(selectedMediaControls.value); - } + }, ), ], // a list of chips to easily select the media controls to display @@ -235,14 +240,8 @@ class MediaControlsPicker extends HookConsumerWidget { children: NotificationMediaControl.values .map( (control) => ChoiceChip( - label: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(control.icon), - const SizedBox(width: 4.0), - Text(control.name), - ], - ), + avatar: Icon(control.icon), + label: Text(control.pascalCase), selected: selectedMediaControls.value.contains(control), onSelected: (selected) { if (selected) { @@ -332,7 +331,7 @@ class NotificationTitlePicker extends HookConsumerWidget { OkButton( onPressed: () { Navigator.of(context).pop(selectedTitle.value); - } + }, ), ], // a list of chips to easily insert available fields into the text field @@ -362,10 +361,10 @@ class NotificationTitlePicker extends HookConsumerWidget { children: NotificationTitleType.values .map( (type) => ActionChip( - label: Text(type.stringValue), + label: Text(type.pascalCase), onPressed: () { final text = controller.text; - final newText = '$text\$${type.stringValue}'; + final newText = '$text\$${type.name}'; controller.text = newText; selectedTitle.value = newText; }, @@ -378,16 +377,3 @@ class NotificationTitlePicker extends HookConsumerWidget { ); } } - -Future showNotificationTitlePicker( - BuildContext context, { - required String initialValue, - required String title, -}) async { - return showDialog( - context: context, - builder: (context) { - return NotificationTitlePicker(initialValue: initialValue, title: title); - }, - ); -} diff --git a/lib/settings/view/player_settings_page.dart b/lib/settings/view/player_settings_page.dart index c07f8cf..58b050f 100644 --- a/lib/settings/view/player_settings_page.dart +++ b/lib/settings/view/player_settings_page.dart @@ -17,6 +17,7 @@ class PlayerSettingsPage extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final appSettings = ref.watch(appSettingsProvider); final playerSettings = appSettings.playerSettings; + final primaryColor = Theme.of(context).colorScheme.primary; return SimpleSettingsPage( title: const Text('Player Settings'), @@ -47,7 +48,11 @@ class PlayerSettingsPage extends HookConsumerWidget { // preferred default speed SettingsTile( title: const Text('Default Speed'), - description: Text('${playerSettings.preferredDefaultSpeed}x'), + trailing: Text( + '${playerSettings.preferredDefaultSpeed}x', + style: + TextStyle(color: primaryColor, fontWeight: FontWeight.bold), + ), leading: const Icon(Icons.speed), onPressed: (context) async { final newSpeed = await showDialog( @@ -70,6 +75,8 @@ class PlayerSettingsPage extends HookConsumerWidget { title: const Text('Speed Options'), description: Text( playerSettings.speedOptions.map((e) => '${e}x').join(', '), + style: + TextStyle(fontWeight: FontWeight.bold, color: primaryColor), ), leading: const Icon(Icons.speed), onPressed: (context) async { @@ -104,7 +111,10 @@ class PlayerSettingsPage extends HookConsumerWidget { TextSpan( text: playerSettings .minimumPositionForReporting.smartBinaryFormat, - style: const TextStyle(fontWeight: FontWeight.bold), + style: TextStyle( + fontWeight: FontWeight.bold, + color: primaryColor, + ), ), const TextSpan(text: ' of the book'), ], @@ -141,7 +151,10 @@ class PlayerSettingsPage extends HookConsumerWidget { TextSpan( text: playerSettings .markCompleteWhenTimeLeft.smartBinaryFormat, - style: const TextStyle(fontWeight: FontWeight.bold), + style: TextStyle( + fontWeight: FontWeight.bold, + color: primaryColor, + ), ), const TextSpan(text: ' left in the book'), ], @@ -178,7 +191,10 @@ class PlayerSettingsPage extends HookConsumerWidget { TextSpan( text: playerSettings .playbackReportInterval.smartBinaryFormat, - style: const TextStyle(fontWeight: FontWeight.bold), + style: TextStyle( + fontWeight: FontWeight.bold, + color: primaryColor, + ), ), const TextSpan(text: ' to the server'), ], diff --git a/lib/settings/view/shake_detector_settings_page.dart b/lib/settings/view/shake_detector_settings_page.dart new file mode 100644 index 0000000..98c5b8d --- /dev/null +++ b/lib/settings/view/shake_detector_settings_page.dart @@ -0,0 +1,395 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:flutter_settings_ui/flutter_settings_ui.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:vaani/settings/app_settings_provider.dart'; +import 'package:vaani/settings/models/app_settings.dart'; +import 'package:vaani/settings/view/buttons.dart'; +import 'package:vaani/settings/view/simple_settings_page.dart'; +import 'package:vaani/shared/extensions/enum.dart'; + +class ShakeDetectorSettingsPage extends HookConsumerWidget { + const ShakeDetectorSettingsPage({ + super.key, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final appSettings = ref.watch(appSettingsProvider); + final shakeDetectionSettings = appSettings.shakeDetectionSettings; + final isShakeDetectionEnabled = shakeDetectionSettings.isEnabled; + final selectedValueColor = isShakeDetectionEnabled + ? Theme.of(context).colorScheme.primary + : Theme.of(context).disabledColor; + + return SimpleSettingsPage( + title: const Text('Shake Detector Settings'), + sections: [ + SettingsSection( + margin: const EdgeInsetsDirectional.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + tiles: [ + SettingsTile.switchTile( + leading: shakeDetectionSettings.isEnabled + ? const Icon(Icons.vibration) + : const Icon(Icons.not_interested), + title: const Text('Enable Shake Detection'), + description: const Text( + 'Enable shake detection to do various actions', + ), + initialValue: shakeDetectionSettings.isEnabled, + onToggle: (value) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.shakeDetectionSettings( + isEnabled: value, + ), + ); + }, + ), + ], + ), + + // Shake Detection Settings + SettingsSection( + tiles: [ + SettingsTile( + enabled: isShakeDetectionEnabled, + leading: const Icon(Icons.flag_circle), + title: const Text('Shake Activation Threshold'), + description: const Text( + 'The higher the threshold, the harder you need to shake', + ), + trailing: Text( + '${shakeDetectionSettings.threshold} m/s²', + style: TextStyle( + color: selectedValueColor, + fontWeight: FontWeight.bold, + ), + ), + onPressed: (context) async { + final newThreshold = await showDialog( + context: context, + builder: (context) => ShakeForceSelector( + initialValue: shakeDetectionSettings.threshold, + ), + ); + + if (newThreshold != null) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.shakeDetectionSettings( + threshold: newThreshold, + ), + ); + } + }, + ), + + // shake action + SettingsTile( + enabled: isShakeDetectionEnabled, + leading: const Icon(Icons.directions_run), + title: const Text('Shake Action'), + description: const Text( + 'The action to perform when a shake is detected', + ), + trailing: Icon( + shakeDetectionSettings.shakeAction.icon, + color: selectedValueColor, + ), + onPressed: (context) async { + final newShakeAction = await showDialog( + context: context, + builder: (context) => ShakeActionSelector( + initialValue: shakeDetectionSettings.shakeAction, + ), + ); + + if (newShakeAction != null) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.shakeDetectionSettings( + shakeAction: newShakeAction, + ), + ); + } + }, + ), + + // shake feedback + SettingsTile( + enabled: isShakeDetectionEnabled, + leading: const Icon(Icons.feedback), + title: const Text('Shake Feedback'), + description: const Text( + 'The feedback to give when a shake is detected', + ), + trailing: shakeDetectionSettings.feedback.isEmpty + ? Icon( + Icons.not_interested, + color: Theme.of(context).disabledColor, + ) + : Wrap( + spacing: 8.0, + children: shakeDetectionSettings.feedback.map( + (feedback) { + return Icon( + feedback.icon, + color: selectedValueColor, + ); + }, + ).toList(), + ), + onPressed: (context) async { + final newFeedback = + await showDialog>( + context: context, + builder: (context) => ShakeFeedbackSelector( + initialValue: shakeDetectionSettings.feedback, + ), + ); + + if (newFeedback != null) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.shakeDetectionSettings( + feedback: newFeedback, + ), + ); + } + }, + ), + ], + ), + ], + ); + } +} + +class ShakeFeedbackSelector extends HookConsumerWidget { + const ShakeFeedbackSelector({ + super.key, + this.initialValue = const {ShakeDetectedFeedback.vibrate}, + }); + + final Set initialValue; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final feedback = useState(initialValue); + return AlertDialog( + title: const Text('Select Shake Feedback'), + content: Wrap( + spacing: 8.0, + runSpacing: 8.0, + children: ShakeDetectedFeedback.values + .map( + (feedbackType) => ChoiceChip( + avatar: Icon(feedbackType.icon), + label: Text(feedbackType.pascalCase), + tooltip: feedbackType.description, + onSelected: (val) { + if (feedback.value.contains(feedbackType)) { + feedback.value = feedback.value + .where((element) => element != feedbackType) + .toSet(); + } else { + feedback.value = {...feedback.value, feedbackType}; + } + }, + selected: feedback.value.contains(feedbackType), + ), + ) + .toList(), + ), + actions: [ + const CancelButton(), + OkButton( + onPressed: () { + Navigator.of(context).pop(feedback.value); + }, + ), + ], + ); + } +} + +class ShakeActionSelector extends HookConsumerWidget { + const ShakeActionSelector({ + super.key, + this.initialValue = ShakeAction.resetSleepTimer, + }); + + final ShakeAction initialValue; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final shakeAction = useState(initialValue); + return AlertDialog( + title: const Text('Select Shake Action'), + content: Wrap( + spacing: 8.0, + runSpacing: 8.0, + children: ShakeAction.values + .map( + // chips with radio buttons as one of the options can be selected + (action) => ChoiceChip( + avatar: Icon(action.icon), + label: Text(action.pascalCase), + onSelected: (val) { + shakeAction.value = action; + }, + selected: shakeAction.value == action, + ), + ) + .toList(), + ), + actions: [ + const CancelButton(), + OkButton( + onPressed: () { + Navigator.of(context).pop(shakeAction.value); + }, + ), + ], + ); + } +} + +class ShakeForceSelector extends HookConsumerWidget { + const ShakeForceSelector({ + super.key, + this.initialValue = 6, + }); + + final double initialValue; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final shakeForce = useState(initialValue); + final controller = useTextEditingController(text: initialValue.toString()); + return AlertDialog( + title: const Text('Select Shake Activation Threshold'), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextField( + autofocus: true, + controller: controller, + onChanged: (value) { + final newThreshold = double.tryParse(value); + if (newThreshold != null) { + shakeForce.value = newThreshold; + } + }, + keyboardType: TextInputType.number, + decoration: InputDecoration( + // clear button + suffix: IconButton( + icon: const Icon(Icons.clear), + onPressed: () { + controller.clear(); + shakeForce.value = 0; + }, + ), + helper: const Text( + 'Enter a number to set the threshold in m/s²', + ), + ), + ), + Wrap( + spacing: 8.0, + runSpacing: 8.0, + children: ShakeForce.values + .map( + (force) => ChoiceChip( + label: Text(force.pascalCase), + onSelected: (val) { + controller.text = force.threshold.toString(); + shakeForce.value = force.threshold; + }, + selected: shakeForce.value == force.threshold, + ), + ) + .toList(), + ), + ], + ), + actions: [ + const CancelButton(), + OkButton( + onPressed: () { + Navigator.of(context).pop(shakeForce.value); + }, + ), + ], + ); + } +} + +enum ShakeForce { + whisper(0.5), + low(2.5), + medium(5), + high(7.5), + storm(10), + hurricane(15), + earthquake(20), + meteorShower(30), + supernova(40), + blackHole(50); + + const ShakeForce(this.threshold); + + final double threshold; +} + +extension ShakeActionIcon on ShakeAction { + IconData? get icon { + switch (this) { + case ShakeAction.none: + return Icons.not_interested; + case ShakeAction.resetSleepTimer: + return Icons.timer; + case ShakeAction.playPause: + return Icons.play_arrow; + // case ShakeAction.nextChapter: + // return Icons.skip_next; + // case ShakeAction.previousChapter: + // return Icons.skip_previous; + // case ShakeAction.volumeUp: + // return Icons.volume_up; + // case ShakeAction.volumeDown: + // return Icons.volume_down; + case ShakeAction.fastForward: + return Icons.fast_forward; + case ShakeAction.rewind: + return Icons.fast_rewind; + default: + return Icons.question_mark; + } + } +} + +extension on ShakeDetectedFeedback { + IconData? get icon { + switch (this) { + case ShakeDetectedFeedback.vibrate: + return Icons.vibration; + case ShakeDetectedFeedback.beep: + return Icons.volume_up; + default: + return Icons.question_mark; + } + } + + String get description { + switch (this) { + case ShakeDetectedFeedback.vibrate: + return 'Vibrate the device'; + case ShakeDetectedFeedback.beep: + return 'Play a beep sound'; + default: + return 'Unknown'; + } + } +} diff --git a/lib/settings/view/widgets/navigation_with_switch_tile.dart b/lib/settings/view/widgets/navigation_with_switch_tile.dart new file mode 100644 index 0000000..dbc8ecf --- /dev/null +++ b/lib/settings/view/widgets/navigation_with_switch_tile.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_settings_ui/flutter_settings_ui.dart'; + +class NavigationWithSwitchTile extends AbstractSettingsTile { + const NavigationWithSwitchTile({ + this.leading, + // this.trailing, + required this.value, + required this.title, + this.description, + this.descriptionInlineIos = false, + this.onPressed, + this.enabled = true, + this.backgroundColor, + super.key, + this.onToggle, + }); + + final Widget title; + final Widget? description; + final Color? backgroundColor; + final bool descriptionInlineIos; + final bool enabled; + final Widget? leading; + final Function(BuildContext)? onPressed; + final bool value; + final Function(bool)? onToggle; + + @override + Widget build(BuildContext context) { + return SettingsTile.navigation( + title: title, + description: description, + backgroundColor: backgroundColor, + descriptionInlineIos: descriptionInlineIos, + enabled: enabled, + leading: leading, + onPressed: onPressed, + trailing: IntrinsicHeight( + child: Row( + children: [ + VerticalDivider( + color: Theme.of(context).dividerColor.withOpacity(0.5), + indent: 8.0, + endIndent: 8.0, + ), + Switch.adaptive( + value: value, + onChanged: onToggle, + ), + ], + ), + ), + ); + } +} diff --git a/lib/shared/extensions/duration_format.dart b/lib/shared/extensions/duration_format.dart index d871424..09906cf 100644 --- a/lib/shared/extensions/duration_format.dart +++ b/lib/shared/extensions/duration_format.dart @@ -16,6 +16,16 @@ extension DurationFormat on Duration { return '${seconds}s'; } } + + String get smartSingleFormat { + if (inHours > 0) { + return '${inHours}h'; + } else if (inMinutes > 0) { + return '${inMinutes}m'; + } else { + return '${inSeconds}s'; + } + } } extension OnlyTime on DateTime { diff --git a/lib/shared/extensions/enum.dart b/lib/shared/extensions/enum.dart new file mode 100644 index 0000000..e0e6c09 --- /dev/null +++ b/lib/shared/extensions/enum.dart @@ -0,0 +1,25 @@ +extension TitleCase on Enum { + String get properName { + final name = toString().split('.').last; + return name[0].toUpperCase() + name.substring(1); + } + + String get titleCase { + return name + .replaceAllMapped(RegExp(r'([A-Z])'), (match) => ' ${match.group(0)}') + .trim(); + } + + String get pascalCase { + // capitalize the first letter of each word + return name + .replaceAllMapped( + RegExp(r'([A-Z])'), + (match) => ' ${match.group(0)}', + ) + .trim() + .split(' ') + .map((word) => word[0].toUpperCase() + word.substring(1)) + .join(' '); + } +} diff --git a/pubspec.lock b/pubspec.lock index f7059ef..969bcca 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1363,6 +1363,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + vibration: + dependency: "direct main" + description: + name: vibration + sha256: fe8f90e1827f86a4f722b819799ecac8a24789a39c6d562ea316bcaeb8b1ec61 + url: "https://pub.dev" + source: hosted + version: "2.0.0" + vibration_platform_interface: + dependency: transitive + description: + name: vibration_platform_interface + sha256: "735a5fef0f284de0ad9449a5ed7d36ba017c6f59b5b20ac64418af4a6bd35ee7" + url: "https://pub.dev" + source: hosted + version: "0.0.1" vm_service: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 11eddba..8bbeef6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -88,6 +88,7 @@ dependencies: path: ./shelfsdk shimmer: ^3.0.0 url_launcher: ^6.2.6 + vibration: ^2.0.0 dev_dependencies: build_runner: ^2.4.9 custom_lint: ^0.6.4 @@ -112,6 +113,7 @@ flutter: assets: - assets/ - assets/animations/ + - assets/sounds/ # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg # An image asset can refer to one or more resolution-specific "variants", see From b8059cad4dc18282356c93509b3b3bb68cd074d2 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Sat, 28 Sep 2024 04:34:40 -0400 Subject: [PATCH 19/92] chore: update GitHub Actions workflow for APK and AAB builds --- .github/workflows/flutter_release.yaml | 29 ++++++++++++++------------ 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/.github/workflows/flutter_release.yaml b/.github/workflows/flutter_release.yaml index ec1053b..e5544be 100644 --- a/.github/workflows/flutter_release.yaml +++ b/.github/workflows/flutter_release.yaml @@ -18,12 +18,6 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - - name: Decode android/upload.jks - run: echo "${{ secrets.UPLOAD_KEYSTORE_JKS }}" | base64 --decode > android/upload.jks - - - name: Decode android/key.properties - run: echo "${{ secrets.KEY_PROPERTIES }}" | base64 --decode > android/key.properties - - name: Checkout shelfsdk uses: actions/checkout@v3 with: @@ -47,14 +41,23 @@ jobs: # - name: Run tests # run: flutter test - - name: Build APK + - name: Decode android/upload.jks + run: echo "${{ secrets.UPLOAD_KEYSTORE_JKS }}" | base64 --decode > android/upload.jks + + - name: Decode android/key.properties + run: echo "${{ secrets.KEY_PROPERTIES }}" | base64 --decode > android/key.properties + + - name: Build APKs + run: flutter build apk --release --split-per-abi + + - name: Build Universal APK run: flutter build apk --release - - name: Upload APK - uses: actions/upload-artifact@v4 - with: - name: release-apk - path: build/app/outputs/flutter-apk/app-release.apk + - name: Rename Universal APK + run: mv build/app/outputs/flutter-apk/{app-release,app-release-universal}.apk + + - name: Build App Bundle + run: flutter build appbundle --release - name: version id: version @@ -75,7 +78,7 @@ jobs: - name: Create GitHub Release uses: ncipollo/release-action@v1 with: - artifacts: build/app/outputs/flutter-apk/app-release.apk + artifacts: "build/app/outputs/flutter-apk/*-release*.apk,build/app/outputs/bundle/release/*.aab" name: v${{ steps.version.outputs.version }} tag: ${{ github.ref }} body: ${{ steps.generate_release_notes.outputs.body }} From 6c0265fe5f900c30d137fd81bce890b632eeea9d Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Sat, 28 Sep 2024 04:37:27 -0400 Subject: [PATCH 20/92] chore: bump version to 0.0.8+1 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 8bbeef6..87df6a6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.0.7+1 +version: 0.0.8+1 environment: sdk: ">=3.3.4 <4.0.0" From 67d6c9240b24c464c1d4ee6f7fba677be7c53331 Mon Sep 17 00:00:00 2001 From: "Dr.Blank" Date: Mon, 30 Sep 2024 02:34:13 -0400 Subject: [PATCH 21/92] Fix Shake Detector not working when app in background (#40) * feat: update shake detection settings to reduce cooldown and feedback options * fix: shake detector not detecting in background * enhance shake action handling to avoid unnecessary feedback * disable shake detector when player not playing anything * refactor: remove outdated TODO regarding shake detection optimization * refactor: comment out notifyListeners call in restartTimer method for clarity --- .../shake_detection/core/shake_detector.dart | 6 + .../providers/shake_detector.dart | 110 ++++++++++++------ .../providers/shake_detector.g.dart | 2 +- .../sleep_timer/core/sleep_timer.dart | 3 + .../providers/sleep_timer_provider.dart | 2 +- .../providers/sleep_timer_provider.g.dart | 2 +- lib/main.dart | 2 +- lib/settings/models/app_settings.dart | 4 +- lib/settings/models/app_settings.freezed.dart | 5 +- lib/settings/models/app_settings.g.dart | 4 +- 10 files changed, 93 insertions(+), 47 deletions(-) diff --git a/lib/features/shake_detection/core/shake_detector.dart b/lib/features/shake_detection/core/shake_detector.dart index 4b7b719..023a8ab 100644 --- a/lib/features/shake_detection/core/shake_detector.dart +++ b/lib/features/shake_detection/core/shake_detector.dart @@ -28,6 +28,9 @@ class ShakeDetector { DateTime _lastShakeTime = DateTime.now(); + final StreamController + _detectedShakeStreamController = StreamController.broadcast(); + void start() { if (_accelerometerSubscription != null) { _logger.warning('ShakeDetector is already running'); @@ -36,6 +39,7 @@ class ShakeDetector { _accelerometerSubscription = userAccelerometerEventStream(samplingPeriod: _settings.samplingPeriod) .listen((event) { + _logger.finest('RMS: ${event.rms}'); if (event.rms > _settings.threshold) { _currentShakeCount++; @@ -44,6 +48,7 @@ class ShakeDetector { _logger.fine('Shake detected $_currentShakeCount times'); onShakeDetected?.call(); + _detectedShakeStreamController.add(event); _lastShakeTime = DateTime.now(); _currentShakeCount = 0; @@ -60,6 +65,7 @@ class ShakeDetector { _currentShakeCount = 0; _accelerometerSubscription?.cancel(); _accelerometerSubscription = null; + _detectedShakeStreamController.close(); _logger.fine('ShakeDetector stopped'); } diff --git a/lib/features/shake_detection/providers/shake_detector.dart b/lib/features/shake_detection/providers/shake_detector.dart index 956fc16..8892a92 100644 --- a/lib/features/shake_detection/providers/shake_detector.dart +++ b/lib/features/shake_detection/providers/shake_detector.dart @@ -19,73 +19,111 @@ Logger _logger = Logger('ShakeDetector'); @riverpod class ShakeDetector extends _$ShakeDetector { + bool wasPlayerLoaded = false; + @override core.ShakeDetector? build() { final appSettings = ref.watch(appSettingsProvider); final shakeDetectionSettings = appSettings.shakeDetectionSettings; if (!shakeDetectionSettings.isEnabled) { - _logger.fine('Shake detection is disabled'); - return null; - } - final player = ref.watch(audiobookPlayerProvider); - if (!player.playing && !shakeDetectionSettings.isActiveWhenPaused) { - _logger.fine( - 'Shake detection is disabled when paused and player is not playing', - ); - return null; - } - // if sleep timer is not enabled, shake detection should not be enabled - final sleepTimer = ref.watch(sleepTimerProvider); - if (!shakeDetectionSettings.isPlaybackManagementEnabled && - sleepTimer == null) { - _logger.fine('No playback management is enabled and sleep timer is off, ' - 'so shake detection is disabled'); + _logger.config('Shake detection is disabled'); return null; } - _logger.fine('Creating shake detector'); + // if no book is loaded, shake detection should not be enabled + final player = ref.watch(simpleAudiobookPlayerProvider); + player.playerStateStream.listen((event) { + if (event.processingState == ProcessingState.idle && wasPlayerLoaded) { + _logger.config('Player is now not loaded, invalidating'); + wasPlayerLoaded = false; + ref.invalidateSelf(); + } + if (event.processingState != ProcessingState.idle && !wasPlayerLoaded) { + _logger.config('Player is now loaded, invalidating'); + wasPlayerLoaded = true; + ref.invalidateSelf(); + } + }); + + if (player.book == null) { + _logger.config('No book is loaded, disabling shake detection'); + wasPlayerLoaded = false; + return null; + } else { + _logger.finer('Book is loaded, marking player as loaded'); + wasPlayerLoaded = true; + } + + // if sleep timer is not enabled, shake detection should not be enabled + final sleepTimer = ref.watch(sleepTimerProvider); + if (!shakeDetectionSettings.shakeAction.isPlaybackManagementEnabled && + sleepTimer == null) { + _logger + .config('No playback management is enabled and sleep timer is off, ' + 'so shake detection is disabled'); + return null; + } + + _logger.config('Creating shake detector'); final detector = core.ShakeDetector( shakeDetectionSettings, () { - doShakeAction( + final wasActionComplete = doShakeAction( shakeDetectionSettings.shakeAction, ref: ref, ); - shakeDetectionSettings.feedback.forEach(postShakeFeedback); + if (wasActionComplete) { + shakeDetectionSettings.feedback.forEach(postShakeFeedback); + } }, ); ref.onDispose(detector.dispose); return detector; } - void doShakeAction( + /// Perform the shake action and return whether the action was successful + bool doShakeAction( ShakeAction shakeAction, { required Ref ref, }) { - final player = ref.watch(simpleAudiobookPlayerProvider); + final player = ref.read(simpleAudiobookPlayerProvider); + if (player.book == null && shakeAction.isPlaybackManagementEnabled) { + _logger.warning('No book is loaded'); + return false; + } switch (shakeAction) { case ShakeAction.resetSleepTimer: _logger.fine('Resetting sleep timer'); - ref.read(sleepTimerProvider.notifier).restartTimer(); - break; + var sleepTimer = ref.read(sleepTimerProvider); + if (sleepTimer == null || !sleepTimer.isActive) { + _logger.warning('No sleep timer is running'); + return false; + } + sleepTimer.restartTimer(); + return true; case ShakeAction.fastForward: _logger.fine('Fast forwarding'); + if (!player.playing) { + _logger.warning('Player is not playing'); + return false; + } player.seek(player.position + const Duration(seconds: 30)); - break; + return true; case ShakeAction.rewind: _logger.fine('Rewinding'); - player.seek(player.position - const Duration(seconds: 30)); - break; - case ShakeAction.playPause: - if (player.book == null) { - _logger.warning('No book is loaded'); - break; + if (!player.playing) { + _logger.warning('Player is not playing'); + return false; } + player.seek(player.position - const Duration(seconds: 30)); + return true; + case ShakeAction.playPause: + _logger.fine('Toggling play/pause'); player.togglePlayPause(); - break; + return true; default: - break; + return false; } } @@ -121,18 +159,18 @@ class ShakeDetector extends _$ShakeDetector { } } -extension on ShakeDetectionSettings { +extension on ShakeAction { bool get isActiveWhenPaused { // If the shake action is play/pause, it should be required when not playing - return shakeAction == ShakeAction.playPause; + return this == ShakeAction.playPause; } bool get isPlaybackManagementEnabled { return {ShakeAction.playPause, ShakeAction.fastForward, ShakeAction.rewind} - .contains(shakeAction); + .contains(this); } bool get shouldActOnSleepTimer { - return {ShakeAction.resetSleepTimer}.contains(shakeAction); + return {ShakeAction.resetSleepTimer}.contains(this); } } diff --git a/lib/features/shake_detection/providers/shake_detector.g.dart b/lib/features/shake_detection/providers/shake_detector.g.dart index c3035b8..0f4285f 100644 --- a/lib/features/shake_detection/providers/shake_detector.g.dart +++ b/lib/features/shake_detection/providers/shake_detector.g.dart @@ -6,7 +6,7 @@ part of 'shake_detector.dart'; // RiverpodGenerator // ************************************************************************** -String _$shakeDetectorHash() => r'7bfbdd22f2f43ef3e3858d226d1eb78923e8114d'; +String _$shakeDetectorHash() => r'2a380bab1d4021d05d2ae40fec964a5f33d3730c'; /// See also [ShakeDetector]. @ProviderFor(ShakeDetector) diff --git a/lib/features/sleep_timer/core/sleep_timer.dart b/lib/features/sleep_timer/core/sleep_timer.dart index 728cec1..215c264 100644 --- a/lib/features/sleep_timer/core/sleep_timer.dart +++ b/lib/features/sleep_timer/core/sleep_timer.dart @@ -28,6 +28,9 @@ class SleepTimer { /// The timer that will pause the player Timer? timer; + /// is the sleep timer actively counting down + bool get isActive => timer != null && timer!.isActive; + /// for internal use only /// when the timer was started DateTime? startedAt; diff --git a/lib/features/sleep_timer/providers/sleep_timer_provider.dart b/lib/features/sleep_timer/providers/sleep_timer_provider.dart index 6f1b1b7..92e5eb8 100644 --- a/lib/features/sleep_timer/providers/sleep_timer_provider.dart +++ b/lib/features/sleep_timer/providers/sleep_timer_provider.dart @@ -54,7 +54,7 @@ class SleepTimer extends _$SleepTimer { void restartTimer() { state?.restartTimer(); - ref.notifyListeners(); + // ref.notifyListeners(); // see https://github.com/Dr-Blank/Vaani/pull/40 for more information on why this is commented out } void cancelTimer() { diff --git a/lib/features/sleep_timer/providers/sleep_timer_provider.g.dart b/lib/features/sleep_timer/providers/sleep_timer_provider.g.dart index fe74010..6d820e4 100644 --- a/lib/features/sleep_timer/providers/sleep_timer_provider.g.dart +++ b/lib/features/sleep_timer/providers/sleep_timer_provider.g.dart @@ -6,7 +6,7 @@ part of 'sleep_timer_provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$sleepTimerHash() => r'9d9f20267da91e5483151b58b7d4d7c0762c3ca7'; +String _$sleepTimerHash() => r'4f80bcc342e918c70c547b8b24790ccd88aba8c3'; /// See also [SleepTimer]. @ProviderFor(SleepTimer) diff --git a/lib/main.dart b/lib/main.dart index 3228a8a..8eef350 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -20,7 +20,7 @@ final appLogger = Logger('vaani'); void main() async { WidgetsFlutterBinding.ensureInitialized(); // Configure the root Logger - Logger.root.level = Level.ALL; // Capture all logs + Logger.root.level = Level.FINE; // Capture all logs Logger.root.onRecord.listen((record) { // Print log records to the console debugPrint( diff --git a/lib/settings/models/app_settings.dart b/lib/settings/models/app_settings.dart index 09a07e2..749b227 100644 --- a/lib/settings/models/app_settings.dart +++ b/lib/settings/models/app_settings.dart @@ -197,12 +197,12 @@ class ShakeDetectionSettings with _$ShakeDetectionSettings { @Default(ShakeDirection.horizontal) ShakeDirection direction, @Default(5) double threshold, @Default(ShakeAction.resetSleepTimer) ShakeAction shakeAction, - @Default({ShakeDetectedFeedback.vibrate, ShakeDetectedFeedback.beep}) + @Default({ShakeDetectedFeedback.vibrate}) Set feedback, @Default(0.5) double beepVolume, /// the duration to wait before the shake detection is enabled again - @Default(Duration(seconds: 5)) Duration shakeTriggerCoolDown, + @Default(Duration(seconds: 2)) Duration shakeTriggerCoolDown, /// the number of shakes required to trigger the action @Default(2) int shakeTriggerCount, diff --git a/lib/settings/models/app_settings.freezed.dart b/lib/settings/models/app_settings.freezed.dart index 3c1d9f4..57f0e96 100644 --- a/lib/settings/models/app_settings.freezed.dart +++ b/lib/settings/models/app_settings.freezed.dart @@ -2633,11 +2633,10 @@ class _$ShakeDetectionSettingsImpl implements _ShakeDetectionSettings { this.threshold = 5, this.shakeAction = ShakeAction.resetSleepTimer, final Set feedback = const { - ShakeDetectedFeedback.vibrate, - ShakeDetectedFeedback.beep + ShakeDetectedFeedback.vibrate }, this.beepVolume = 0.5, - this.shakeTriggerCoolDown = const Duration(seconds: 5), + this.shakeTriggerCoolDown = const Duration(seconds: 2), this.shakeTriggerCount = 2, this.samplingPeriod = const Duration(milliseconds: 100)}) : _feedback = feedback; diff --git a/lib/settings/models/app_settings.g.dart b/lib/settings/models/app_settings.g.dart index 3b0784f..7c553dd 100644 --- a/lib/settings/models/app_settings.g.dart +++ b/lib/settings/models/app_settings.g.dart @@ -294,10 +294,10 @@ _$ShakeDetectionSettingsImpl _$$ShakeDetectionSettingsImplFromJson( feedback: (json['feedback'] as List?) ?.map((e) => $enumDecode(_$ShakeDetectedFeedbackEnumMap, e)) .toSet() ?? - const {ShakeDetectedFeedback.vibrate, ShakeDetectedFeedback.beep}, + const {ShakeDetectedFeedback.vibrate}, beepVolume: (json['beepVolume'] as num?)?.toDouble() ?? 0.5, shakeTriggerCoolDown: json['shakeTriggerCoolDown'] == null - ? const Duration(seconds: 5) + ? const Duration(seconds: 2) : Duration( microseconds: (json['shakeTriggerCoolDown'] as num).toInt()), shakeTriggerCount: (json['shakeTriggerCount'] as num?)?.toInt() ?? 2, From a790a7e583d3fcb328edb605f6b09a3a38928f41 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Mon, 30 Sep 2024 02:47:13 -0400 Subject: [PATCH 22/92] ci: add upload step for APKs in test workflow --- .github/workflows/flutter_test.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/flutter_test.yaml b/.github/workflows/flutter_test.yaml index c2f502f..245a489 100644 --- a/.github/workflows/flutter_test.yaml +++ b/.github/workflows/flutter_test.yaml @@ -45,3 +45,9 @@ jobs: - name: Build APK run: flutter build apk --release + + - name: Upload APKs + uses: actions/upload-artifact@v4 + with: + name: app-release + path: build/app/outputs/flutter-apk/*.apk From 90913162cc59bbe518c06f737add82989e96a30c Mon Sep 17 00:00:00 2001 From: "Dr.Blank" Date: Mon, 30 Sep 2024 04:19:15 -0400 Subject: [PATCH 23/92] fix: speed selector wheel was not visible (#41) --- .../widgets/player_speed_adjust_button.dart | 3 - .../player/view/widgets/speed_selector.dart | 104 ++++++++++-------- 2 files changed, 59 insertions(+), 48 deletions(-) diff --git a/lib/features/player/view/widgets/player_speed_adjust_button.dart b/lib/features/player/view/widgets/player_speed_adjust_button.dart index e13d278..36b7cd7 100644 --- a/lib/features/player/view/widgets/player_speed_adjust_button.dart +++ b/lib/features/player/view/widgets/player_speed_adjust_button.dart @@ -29,9 +29,6 @@ class PlayerSpeedAdjustButton extends HookConsumerWidget { await showModalBottomSheet( context: context, barrierLabel: 'Select Speed', - constraints: const BoxConstraints( - maxHeight: 225, - ), builder: (context) { return SpeedSelector( onSpeedSelected: (speed) { diff --git a/lib/features/player/view/widgets/speed_selector.dart b/lib/features/player/view/widgets/speed_selector.dart index 289b736..987579a 100644 --- a/lib/features/player/view/widgets/speed_selector.dart +++ b/lib/features/player/view/widgets/speed_selector.dart @@ -57,23 +57,34 @@ class SpeedSelector extends HookConsumerWidget { initialItem: availableSpeedsList.indexOf(currentSpeed), ); const double itemExtent = 25; - return Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - children: [ - // the title - Padding( - padding: const EdgeInsets.all(8.0), - child: Center( - child: Text( - 'Playback Speed: ${speedState.value}x', - style: Theme.of(context).textTheme.titleLarge, - ), + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + // the title + Padding( + padding: const EdgeInsets.only(top: 16.0, bottom: 8.0), + child: Center( + child: Text( + 'Playback Speed: ${speedState.value}x', + style: Theme.of(context).textTheme.titleLarge, ), ), + ), - // the speed selector - Flexible( + // a inverted triangle to indicate the speed selector + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.arrow_drop_down, + color: Theme.of(context).colorScheme.onSurface, + ), + ), + + // the speed selector + Padding( + padding: const EdgeInsets.only(bottom: 8.0, right: 8.0, left: 8.0), + child: SizedBox( + height: 80, child: SpeedWheel( availableSpeedsList: availableSpeedsList, speedState: speedState, @@ -81,9 +92,12 @@ class SpeedSelector extends HookConsumerWidget { itemExtent: itemExtent, ), ), + ), - // the speed buttons - Wrap( + // the speed buttons + Padding( + padding: const EdgeInsets.all(8.0), + child: Wrap( spacing: 8.0, alignment: WrapAlignment.center, runAlignment: WrapAlignment.center, @@ -133,8 +147,8 @@ class SpeedSelector extends HookConsumerWidget { ) .toList(), ), - ], - ), + ), + ], ); } } @@ -178,7 +192,7 @@ class SpeedWheel extends StatelessWidget { }, ), // the speed selector wheel - Expanded( + Flexible( child: ListWheelScrollViewX( controller: scrollController, scrollDirection: Axis.horizontal, @@ -189,9 +203,7 @@ class SpeedWheel extends StatelessWidget { physics: const FixedExtentScrollPhysics(), children: availableSpeedsList .map( - (speed) => Expanded( - child: SpeedLine(itemExtent: itemExtent, speed: speed), - ), + (speed) => SpeedLine(itemExtent: itemExtent, speed: speed), ) .toList(), onSelectedItemChanged: (index) { @@ -236,34 +248,36 @@ class SpeedLine extends StatelessWidget { return Column( children: [ // a vertical line - Container( - height: itemExtent * 2, - // thick if multiple of 1, thin if multiple of 0.5 and transparent if multiple of 0.05 - width: speed % 0.5 == 0 - ? 3 - : speed % 0.25 == 0 - ? 2 - : 0.5, - color: Theme.of(context).colorScheme.onSurface, + Expanded( + child: Container( + // height: itemExtent, + // thick if multiple of 1, thin if multiple of 0.5 and transparent if multiple of 0.05 + width: speed % 0.5 == 0 + ? 3 + : speed % 0.25 == 0 + ? 2 + : 0.5, + color: Theme.of(context).colorScheme.onSurface, + ), ), // the speed text but only at .5 increments of speed - if (speed % 0.25 == 0) - Expanded( - child: Text.rich( - TextSpan( - text: speed.floor().toString(), - children: [ - TextSpan( - text: '.${speed.toStringAsFixed(2).split('.').last}', - style: TextStyle( - fontSize: - Theme.of(context).textTheme.labelSmall?.fontSize, - ), + // if (speed % 0.25 == 0) + Opacity( + opacity: speed % 0.25 == 0 ? 1 : 0, + child: Text.rich( + TextSpan( + text: speed.floor().toString(), + children: [ + TextSpan( + text: '.${speed.toStringAsFixed(2).split('.').last}', + style: TextStyle( + fontSize: Theme.of(context).textTheme.labelSmall?.fontSize, ), - ], - ), + ), + ], ), ), + ), ], ); } From 35d3bb362d08c795ed2afa57120852aca83f1c73 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Mon, 30 Sep 2024 05:44:52 -0400 Subject: [PATCH 24/92] chore: bump version to 0.0.9+1 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 87df6a6..eebb464 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.0.8+1 +version: 0.0.9+1 environment: sdk: ">=3.3.4 <4.0.0" From 3400b725f202dfaf811b98ae0cbd9e3c8601de04 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Mon, 30 Sep 2024 23:18:02 -0400 Subject: [PATCH 25/92] chore: update dependencies to latest versions --- pubspec.lock | 76 ++++++++++++++++++++++++++-------------------------- pubspec.yaml | 2 +- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 969bcca..621e454 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -122,10 +122,10 @@ packages: dependency: "direct main" description: name: background_downloader - sha256: "5323dfc5519d7a646f7e61adee31f44f2ede54861d5318dfd451a8e38a285538" + sha256: "6b73fa5d20c47e855f6ef3ed6fb3e0d164141d8ae7d43ca0a42c78f90eaa15e7" url: "https://pub.dev" source: hosted - version: "8.5.3" + version: "8.5.6" boolean_selector: dependency: transitive description: @@ -170,10 +170,10 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: dd09dd4e2b078992f42aac7f1a622f01882a8492fef08486b27ddde929c19f04 + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" url: "https://pub.dev" source: hosted - version: "2.4.12" + version: "2.4.13" build_runner_core: dependency: transitive description: @@ -322,18 +322,18 @@ packages: dependency: "direct dev" description: name: custom_lint - sha256: "4939d89e580c36215e48a7de8fd92f22c79dcc3eb11fda84f3402b3b45aec663" + sha256: "6e1ec47427ca968f22bce734d00028ae7084361999b41673291138945c5baca0" url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.7" custom_lint_builder: dependency: transitive description: name: custom_lint_builder - sha256: d9e5bb63ed52c1d006f5a1828992ba6de124c27a531e8fba0a31afffa81621b3 + sha256: ba2f90fff4eff71d202d097eb14b14f87087eaaef742e956208c0eb9d3a40a21 url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.7" custom_lint_core: dependency: transitive description: @@ -346,10 +346,10 @@ packages: dependency: transitive description: name: dart_style - sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" + sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab" url: "https://pub.dev" source: hosted - version: "2.3.6" + version: "2.3.7" device_info_plus: dependency: "direct main" description: @@ -463,10 +463,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" + sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "5.0.0" flutter_material_pickers: dependency: "direct main" description: @@ -503,10 +503,10 @@ packages: dependency: transitive description: name: flutter_shaders - sha256: "02750b545c01ff4d8e9bbe8f27a7731aa3778402506c67daa1de7f5fc3f4befe" + sha256: "34794acadd8275d971e02df03afee3dee0f98dbfb8c4837082ad0034f612a3e2" url: "https://pub.dev" source: hosted - version: "0.1.2" + version: "0.1.3" flutter_test: dependency: "direct dev" description: flutter @@ -561,10 +561,10 @@ packages: dependency: "direct main" description: name: go_router - sha256: "2ddb88e9ad56ae15ee144ed10e33886777eb5ca2509a914850a5faa7b52ff459" + sha256: "5cf5fdcf853b0629deb35891c7af643be900c3dcaed7489009f9e7dbcfe55ab6" url: "https://pub.dev" source: hosted - version: "14.2.7" + version: "14.2.8" graphs: dependency: transitive description: @@ -730,10 +730,10 @@ packages: dependency: transitive description: name: just_audio_web - sha256: b163878529d9b028c53a6972fcd58cae2405bcd11cbfcea620b6fb9f151429d6 + sha256: "9a98035b8b24b40749507687520ec5ab404e291d2b0937823ff45d92cb18d448" url: "https://pub.dev" source: hosted - version: "0.4.12" + version: "0.4.13" leak_tracker: dependency: transitive description: @@ -762,10 +762,10 @@ packages: dependency: transitive description: name: lints - sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" + sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "5.0.0" list_wheel_scroll_view_nls: dependency: "direct main" description: @@ -1127,18 +1127,18 @@ packages: dependency: transitive description: name: socket_io_client - sha256: "15c9deae04e2b21065adbe864a641e0a5fc2499ff4c89e98a3877aea22ce841c" + sha256: "543842390db2c1d1b02e1ad0e6167db2f8872c7a6669051cb89e2559b11a5aeb" url: "https://pub.dev" source: hosted - version: "3.0.0-beta.2" + version: "3.0.0-beta.4" socket_io_common: dependency: transitive description: name: socket_io_common - sha256: "5ad0f12e1b17f4300b0d6a27feaf1b7c1153ca21498ba307f0297b81449f7a44" + sha256: "392c3613c88ad3ee0e15911db2e7e9dbd675622c2589ce99383630603b097619" url: "https://pub.dev" source: hosted - version: "3.0.0-beta.0" + version: "3.0.0" source_gen: dependency: transitive description: @@ -1175,18 +1175,18 @@ packages: dependency: transitive description: name: sqflite - sha256: a43e5a27235518c03ca238e7b4732cf35eabe863a369ceba6cbefa537a66f16d + sha256: ff5a2436ef8ebdfda748fbfe957f9981524cb5ff11e7bafa8c42771840e8a788 url: "https://pub.dev" source: hosted - version: "2.3.3+1" + version: "2.3.3+2" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "7b41b6c3507854a159e24ae90a8e3e9cc01eb26a477c118d6dca065b5f55453e" + sha256: "2d8e607db72e9cb7748c9c6e739e2c9618320a5517de693d5a24609c4671b1a4" url: "https://pub.dev" source: hosted - version: "2.5.4+2" + version: "2.5.4+4" stack_trace: dependency: transitive description: @@ -1231,10 +1231,10 @@ packages: dependency: transitive description: name: synchronized - sha256: a824e842b8a054f91a728b783c177c1e4731f6b124f9192468457a8913371255 + sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225" url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.3.0+3" term_glyph: dependency: transitive description: @@ -1319,10 +1319,10 @@ packages: dependency: transitive description: name: url_launcher_macos - sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de" + sha256: "769549c999acdb42b8bcfa7c43d72bf79a382ca7441ab18a808e101149daf672" url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.2.1" url_launcher_platform_interface: dependency: transitive description: @@ -1351,10 +1351,10 @@ packages: dependency: transitive description: name: uuid - sha256: "83d37c7ad7aaf9aa8e275490669535c8080377cfa7a7004c24dfac53afffaa90" + sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff url: "https://pub.dev" source: hosted - version: "4.4.2" + version: "4.5.1" vector_math: dependency: transitive description: @@ -1399,10 +1399,10 @@ packages: dependency: transitive description: name: web - sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062 + sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.1.0" web_socket: dependency: transitive description: @@ -1431,10 +1431,10 @@ packages: dependency: transitive description: name: win32_registry - sha256: "723b7f851e5724c55409bb3d5a32b203b3afe8587eaf5dafb93a5fed8ecda0d6" + sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852" url: "https://pub.dev" source: hosted - version: "1.1.4" + version: "1.1.5" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index eebb464..43b1704 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -92,7 +92,7 @@ dependencies: dev_dependencies: build_runner: ^2.4.9 custom_lint: ^0.6.4 - flutter_lints: ^4.0.0 + flutter_lints: ^5.0.0 flutter_test: sdk: flutter freezed: ^2.5.2 From 29f4c93554607c4b48569ff5c20000f562d803f6 Mon Sep 17 00:00:00 2001 From: "Dr.Blank" Date: Tue, 1 Oct 2024 02:16:08 -0400 Subject: [PATCH 26/92] fix: notification logo not showing (#42) --- ..._stat_notification_logo.png => ic_stat_logo.png} | Bin ..._stat_notification_logo.png => ic_stat_logo.png} | Bin ..._stat_notification_logo.png => ic_stat_logo.png} | Bin ..._stat_notification_logo.png => ic_stat_logo.png} | Bin ..._stat_notification_logo.png => ic_stat_logo.png} | Bin android/app/src/main/res/raw/keep.xml | 3 +++ lib/features/player/core/init.dart | 6 +++--- 7 files changed, 6 insertions(+), 3 deletions(-) rename android/app/src/main/res/drawable-hdpi/{ic_stat_notification_logo.png => ic_stat_logo.png} (100%) rename android/app/src/main/res/drawable-mdpi/{ic_stat_notification_logo.png => ic_stat_logo.png} (100%) rename android/app/src/main/res/drawable-xhdpi/{ic_stat_notification_logo.png => ic_stat_logo.png} (100%) rename android/app/src/main/res/drawable-xxhdpi/{ic_stat_notification_logo.png => ic_stat_logo.png} (100%) rename android/app/src/main/res/drawable-xxxhdpi/{ic_stat_notification_logo.png => ic_stat_logo.png} (100%) create mode 100644 android/app/src/main/res/raw/keep.xml diff --git a/android/app/src/main/res/drawable-hdpi/ic_stat_notification_logo.png b/android/app/src/main/res/drawable-hdpi/ic_stat_logo.png similarity index 100% rename from android/app/src/main/res/drawable-hdpi/ic_stat_notification_logo.png rename to android/app/src/main/res/drawable-hdpi/ic_stat_logo.png diff --git a/android/app/src/main/res/drawable-mdpi/ic_stat_notification_logo.png b/android/app/src/main/res/drawable-mdpi/ic_stat_logo.png similarity index 100% rename from android/app/src/main/res/drawable-mdpi/ic_stat_notification_logo.png rename to android/app/src/main/res/drawable-mdpi/ic_stat_logo.png diff --git a/android/app/src/main/res/drawable-xhdpi/ic_stat_notification_logo.png b/android/app/src/main/res/drawable-xhdpi/ic_stat_logo.png similarity index 100% rename from android/app/src/main/res/drawable-xhdpi/ic_stat_notification_logo.png rename to android/app/src/main/res/drawable-xhdpi/ic_stat_logo.png diff --git a/android/app/src/main/res/drawable-xxhdpi/ic_stat_notification_logo.png b/android/app/src/main/res/drawable-xxhdpi/ic_stat_logo.png similarity index 100% rename from android/app/src/main/res/drawable-xxhdpi/ic_stat_notification_logo.png rename to android/app/src/main/res/drawable-xxhdpi/ic_stat_logo.png diff --git a/android/app/src/main/res/drawable-xxxhdpi/ic_stat_notification_logo.png b/android/app/src/main/res/drawable-xxxhdpi/ic_stat_logo.png similarity index 100% rename from android/app/src/main/res/drawable-xxxhdpi/ic_stat_notification_logo.png rename to android/app/src/main/res/drawable-xxxhdpi/ic_stat_logo.png diff --git a/android/app/src/main/res/raw/keep.xml b/android/app/src/main/res/raw/keep.xml new file mode 100644 index 0000000..af0bd8d --- /dev/null +++ b/android/app/src/main/res/raw/keep.xml @@ -0,0 +1,3 @@ + + \ No newline at end of file diff --git a/lib/features/player/core/init.dart b/lib/features/player/core/init.dart index c61637b..abcf013 100644 --- a/lib/features/player/core/init.dart +++ b/lib/features/player/core/init.dart @@ -21,10 +21,10 @@ Future configurePlayer() async { await JustAudioBackground.init( androidNotificationChannelId: 'com.vaani.bg_demo.channel.audio', androidNotificationChannelName: 'Audio playback', - androidNotificationOngoing: true, - androidStopForegroundOnPause: true, + androidNotificationOngoing: false, + androidStopForegroundOnPause: false, androidNotificationChannelDescription: 'Audio playback in the background', - androidNotificationIcon: 'drawable/ic_stat_notification_logo', + androidNotificationIcon: 'drawable/ic_stat_logo', rewindInterval: appSettings.notificationSettings.rewindInterval, fastForwardInterval: appSettings.notificationSettings.fastForwardInterval, androidShowNotificationBadge: false, From e9c4b9cd8645d1276cb30304dbcdc8fa98906057 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Tue, 1 Oct 2024 02:17:38 -0400 Subject: [PATCH 27/92] chore: remove rxdart dependency from pubspec.yaml --- pubspec.lock | 2 +- pubspec.yaml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 621e454..0436fc6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1048,7 +1048,7 @@ packages: source: hosted version: "2.3.13" rxdart: - dependency: "direct main" + dependency: transitive description: name: rxdart sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" diff --git a/pubspec.yaml b/pubspec.yaml index 43b1704..123f6f7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -81,7 +81,6 @@ dependencies: path: ^1.9.0 path_provider: ^2.1.0 riverpod_annotation: ^2.3.5 - rxdart: ^0.28.0 scroll_loop_auto_scroll: ^0.0.5 sensors_plus: ^6.0.1 shelfsdk: From e9b2fc074cd3accde849157b51c3790337753d04 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Tue, 1 Oct 2024 02:47:22 -0400 Subject: [PATCH 28/92] chore: add privacy policy document --- privacy-policy.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 privacy-policy.md diff --git a/privacy-policy.md b/privacy-policy.md new file mode 100644 index 0000000..0ec8a98 --- /dev/null +++ b/privacy-policy.md @@ -0,0 +1,25 @@ +**Privacy Policy** + +This privacy policy applies to the Vaani app (hereby referred to as "Application") for mobile devices that was created by Dr. Blank (hereby referred to as "Service Provider") as an Open Source service. This service is intended for use "AS IS". + +**Information Collection and Use** + +The Application does not collect any information by itself. It is a client for a self-hosted server, meaning that users are responsible for setting up their own servers to use the Application. Any information collected will be by the user's server and not by the Service Provider. + +**Changes** + +This Privacy Policy may be updated from time to time for any reason. The Service Provider will notify you of any changes to the Privacy Policy by updating this page with the new Privacy Policy. You are advised to consult this Privacy Policy regularly for any changes, as continued use is deemed approval of all changes. + +This privacy policy is effective as of 2024-10-01 + +**Your Consent** + +By using the Application, you are consenting to the processing of your information as set forth in this Privacy Policy now and as amended by us. + +**Contact Us** + +If you have any questions regarding privacy while using the Application, or have questions about the practices, please contact the Service Provider via email at drblankdev@gmail.com. + +* * * + +This privacy policy page was generated by [App Privacy Policy Generator](https://app-privacy-policy-generator.nisrulz.com/) From ce74ead2b3ff3781bf8ba9edb3ef72f3e1942de2 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Wed, 2 Oct 2024 02:20:16 -0400 Subject: [PATCH 29/92] docs: update README with features and download instructions --- README.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0d0310b..c50a48f 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,23 @@ Client for [Audiobookshelf](https://github.com/advplyr/audiobookshelf) server made with Flutter. +## Features + +* Functional Player: Speed Control, Sleep Timer, Shake to Control Player +* Save data with Offline listening and caching +* Material Design +* Extensive Settings to customize the every tiny detail + +## Download + +### Android + -[Get it on GitHub](https://github.com/Dr-Blank/Vaani/releases/latest) [Get it on Obtainium](http://apps.obtainium.imranr.dev/redirect.html?r=obtainium://add/https://github.com/Dr-Blank/Vaani) +[Get it on GitHub](https://github.com/Dr-Blank/Vaani/releases/latest/download/app-release-universal.apk) [Get it on Obtainium](http://apps.obtainium.imranr.dev/redirect.html?r=obtainium://add/https://github.com/Dr-Blank/Vaani) + +Playstore App is in closed testing. To join testing +1. [Join the Google Group](https://groups.google.com/g/vaani-app) +2. [Join on Android](https://play.google.com/store/apps/details?id=dr.blank.vaani) Or [Join on Web](https://play.google.com/apps/testing/dr.blank.vaani) ## Screencaps @@ -19,4 +34,4 @@ https://github.com/user-attachments/assets/2ac9ace2-4a3c-40fc-adde-55914e4cf62d Currently, the app is in development and is not ready for production use. -Plan is to have support for android, ios, and desktop. +Plan is to have support for android, and desktop. From 4c5dc5316913985101976796549cd21b6bc02b77 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Wed, 2 Oct 2024 02:39:33 -0400 Subject: [PATCH 30/92] refactor: update default speed options for player settings --- lib/settings/models/app_settings.dart | 2 +- lib/settings/models/app_settings.freezed.dart | 2 +- lib/settings/models/app_settings.g.dart | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/settings/models/app_settings.dart b/lib/settings/models/app_settings.dart index 749b227..7debe11 100644 --- a/lib/settings/models/app_settings.dart +++ b/lib/settings/models/app_settings.dart @@ -45,7 +45,7 @@ class PlayerSettings with _$PlayerSettings { ExpandedPlayerSettings expandedPlayerSettings, @Default(1) double preferredDefaultVolume, @Default(1) double preferredDefaultSpeed, - @Default([0.75, 1, 1.25, 1.5, 1.75, 2]) List speedOptions, + @Default([1, 1.25, 1.5, 1.75, 2]) List speedOptions, @Default(0.05) double speedIncrement, @Default(0.1) double minSpeed, @Default(4) double maxSpeed, diff --git a/lib/settings/models/app_settings.freezed.dart b/lib/settings/models/app_settings.freezed.dart index 57f0e96..4980b85 100644 --- a/lib/settings/models/app_settings.freezed.dart +++ b/lib/settings/models/app_settings.freezed.dart @@ -838,7 +838,7 @@ class _$PlayerSettingsImpl implements _PlayerSettings { this.expandedPlayerSettings = const ExpandedPlayerSettings(), this.preferredDefaultVolume = 1, this.preferredDefaultSpeed = 1, - final List speedOptions = const [0.75, 1, 1.25, 1.5, 1.75, 2], + final List speedOptions = const [1, 1.25, 1.5, 1.75, 2], this.speedIncrement = 0.05, this.minSpeed = 0.1, this.maxSpeed = 4, diff --git a/lib/settings/models/app_settings.g.dart b/lib/settings/models/app_settings.g.dart index 7c553dd..da9ca9c 100644 --- a/lib/settings/models/app_settings.g.dart +++ b/lib/settings/models/app_settings.g.dart @@ -73,7 +73,7 @@ _$PlayerSettingsImpl _$$PlayerSettingsImplFromJson(Map json) => speedOptions: (json['speedOptions'] as List?) ?.map((e) => (e as num).toDouble()) .toList() ?? - const [0.75, 1, 1.25, 1.5, 1.75, 2], + const [1, 1.25, 1.5, 1.75, 2], speedIncrement: (json['speedIncrement'] as num?)?.toDouble() ?? 0.05, minSpeed: (json['minSpeed'] as num?)?.toDouble() ?? 0.1, maxSpeed: (json['maxSpeed'] as num?)?.toDouble() ?? 4, From 933bfc57501f1aa8a0fb90f71ecc756e4d64d6d0 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Wed, 2 Oct 2024 09:07:21 -0400 Subject: [PATCH 31/92] chore: update release drafter configuration to include UI changes category --- .github/release-drafter.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index 8c7d11c..9ec7edd 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -1,13 +1,14 @@ name-template: "v$RESOLVED_VERSION" tag-template: "v$RESOLVED_VERSION" -# name-template: 'v$NEXT_PATCH_VERSION' -# tag-template: 'v$NEXT_PATCH_VERSION' categories: - title: "🚀 Features" labels: - "feature" - "enhancement" + - title: "📱 UI Changes" + labels: + - "ui" - title: "🐛 Bug Fixes" labels: - "fix" @@ -18,7 +19,7 @@ categories: - title: "💥 Breaking Changes" labels: - "breaking" -change-template: "- $TITLE by @$AUTHOR in #$NUMBER" +change-template: "- $TITLE (#$NUMBER)" change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. version-resolver: major: @@ -60,3 +61,9 @@ autolabeler: - label: "chore" title: - "/chore/i" + - label: "ui" + title: + - "/^ui\b/i" + - label: "refactor" + title: + - "/refactor/i" From 12100ffbcd10cc53e3893cb0373cd7d64c892a27 Mon Sep 17 00:00:00 2001 From: "Dr.Blank" Date: Wed, 2 Oct 2024 09:18:06 -0400 Subject: [PATCH 32/92] ui: better sleep timer ui in player and fix auto turn on settings (#43) * refactor: enhance sleep timer functionality and improve duration formatting * refactor: update sleep timer settings handling * refactor: update cancel icon for sleep timer button * refactor: implement isBetween method for TimeOfDay and simplify sleep timer logic * refactor: update alwaysAutoTurnOnTimer default value and improve icon usage in settings * refactor: remove unused IconButton and update sleep timer preset durations --- .../player/view/player_when_expanded.dart | 147 +------ .../player/view/widgets/speed_selector.dart | 18 +- .../sleep_timer/core/sleep_timer.dart | 12 +- .../providers/sleep_timer_provider.dart | 34 +- .../providers/sleep_timer_provider.g.dart | 2 +- .../sleep_timer/view/sleep_timer_button.dart | 366 ++++++++++++++++++ lib/settings/app_settings_provider.dart | 16 + lib/settings/app_settings_provider.g.dart | 17 + lib/settings/models/app_settings.dart | 27 +- lib/settings/models/app_settings.freezed.dart | 278 ++++++------- lib/settings/models/app_settings.g.dart | 54 ++- lib/settings/view/app_settings_page.dart | 9 +- .../view/auto_sleep_timer_settings_page.dart | 52 ++- lib/shared/extensions/duration_format.dart | 19 +- lib/shared/extensions/time_of_day.dart | 17 +- lib/shared/hooks.dart | 61 +++ pubspec.lock | 8 + pubspec.yaml | 1 + 18 files changed, 755 insertions(+), 383 deletions(-) create mode 100644 lib/features/sleep_timer/view/sleep_timer_button.dart diff --git a/lib/features/player/view/player_when_expanded.dart b/lib/features/player/view/player_when_expanded.dart index 933121c..5fe0ea7 100644 --- a/lib/features/player/view/player_when_expanded.dart +++ b/lib/features/player/view/player_when_expanded.dart @@ -1,17 +1,11 @@ -import 'package:duration_picker/duration_picker.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:miniplayer/miniplayer.dart'; import 'package:vaani/constants/sizes.dart'; import 'package:vaani/features/player/providers/currently_playing_provider.dart'; import 'package:vaani/features/player/providers/player_form.dart'; import 'package:vaani/features/player/view/audiobook_player.dart'; -import 'package:vaani/features/sleep_timer/core/sleep_timer.dart'; -import 'package:vaani/features/sleep_timer/providers/sleep_timer_provider.dart' - show sleepTimerProvider; -import 'package:vaani/settings/app_settings_provider.dart'; -import 'package:vaani/shared/extensions/duration_format.dart'; +import 'package:vaani/features/sleep_timer/view/sleep_timer_button.dart'; import 'package:vaani/shared/extensions/inverse_lerp.dart'; import 'package:vaani/shared/widgets/not_implemented.dart'; @@ -246,13 +240,13 @@ class PlayerWhenExpanded extends HookConsumerWidget { // chapter list const ChapterSelectionButton(), // settings - IconButton( - icon: const Icon(Icons.more_horiz), - onPressed: () { - // show toast - showNotImplementedToast(context); - }, - ), + // IconButton( + // icon: const Icon(Icons.more_horiz), + // onPressed: () { + // // show toast + // showNotImplementedToast(context); + // }, + // ), ], ), ), @@ -261,128 +255,3 @@ class PlayerWhenExpanded extends HookConsumerWidget { ); } } - -class SleepTimerButton extends HookConsumerWidget { - const SleepTimerButton({ - super.key, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final sleepTimer = ref.watch(sleepTimerProvider); - // if sleep timer is not active, show the button with the sleep timer icon - // if the sleep timer is active, show the remaining time in a pill shaped container - return Tooltip( - message: 'Sleep Timer', - child: InkWell( - onTap: () async { - pendingPlayerModals++; - // show the sleep timer dialog - final resultingDuration = await showDurationPicker( - context: context, - initialTime: ref - .watch(appSettingsProvider) - .playerSettings - .sleepTimerSettings - .defaultDuration, - ); - pendingPlayerModals--; - if (resultingDuration != null) { - // if 0 is selected, cancel the timer - if (resultingDuration.inSeconds == 0) { - ref.read(sleepTimerProvider.notifier).cancelTimer(); - } else { - ref.read(sleepTimerProvider.notifier).setTimer(resultingDuration); - } - } - }, - child: sleepTimer == null - ? Icon( - Icons.timer_rounded, - color: Theme.of(context).colorScheme.onSurface, - ) - : RemainingSleepTimeDisplay( - timer: sleepTimer, - ), - ), - ); - } -} - -class SleepTimerDialog extends HookConsumerWidget { - const SleepTimerDialog({ - super.key, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final sleepTimer = ref.watch(sleepTimerProvider); - final sleepTimerSettings = - ref.watch(appSettingsProvider).playerSettings.sleepTimerSettings; - final timerDurationController = useTextEditingController( - text: sleepTimerSettings.defaultDuration.inMinutes.toString(), - ); - - return AlertDialog( - title: const Text('Sleep Timer'), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const Text('Set the duration for the sleep timer'), - TextField( - controller: timerDurationController, - keyboardType: TextInputType.number, - decoration: const InputDecoration( - labelText: 'Duration in minutes', - ), - ), - ], - ), - actions: [ - TextButton( - onPressed: () { - // sleepTimer.setTimer( - // Duration( - // minutes: int.tryParse(timerDurationController.text) ?? 0, - // ), - // ); - Navigator.of(context).pop(); - }, - child: const Text('Set Timer'), - ), - ], - ); - } -} - -class RemainingSleepTimeDisplay extends HookConsumerWidget { - const RemainingSleepTimeDisplay({ - super.key, - required this.timer, - }); - - final SleepTimer timer; - - @override - Widget build(BuildContext context, WidgetRef ref) { - final remainingTime = useStream(timer.remainingTimeStream).data; - return Container( - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primary, - borderRadius: BorderRadius.circular(16), - ), - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 4, - ), - child: Text( - timer.timer == null - ? timer.duration.smartBinaryFormat - : remainingTime?.smartBinaryFormat ?? '', - style: Theme.of(context).textTheme.bodyMedium!.copyWith( - color: Theme.of(context).colorScheme.onPrimary, - ), - ), - ); - } -} diff --git a/lib/features/player/view/widgets/speed_selector.dart b/lib/features/player/view/widgets/speed_selector.dart index 987579a..65a3bfa 100644 --- a/lib/features/player/view/widgets/speed_selector.dart +++ b/lib/features/player/view/widgets/speed_selector.dart @@ -6,6 +6,9 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:list_wheel_scroll_view_nls/list_wheel_scroll_view_nls.dart'; import 'package:vaani/features/player/providers/audiobook_player.dart'; import 'package:vaani/settings/app_settings_provider.dart'; +import 'package:vaani/shared/hooks.dart'; + +const double itemExtent = 25; class SpeedSelector extends HookConsumerWidget { const SpeedSelector({ @@ -34,11 +37,11 @@ class SpeedSelector extends HookConsumerWidget { // the speed options final minSpeed = min( - speeds.reduce((minSpeedSoFar, element) => min(minSpeedSoFar, element)), + speeds.reduce(min), playerSettings.minSpeed, ); final maxSpeed = max( - speeds.reduce((maxSpeedSoFar, element) => max(maxSpeedSoFar, element)), + speeds.reduce(max), playerSettings.maxSpeed, ); final speedIncrement = playerSettings.speedIncrement; @@ -53,10 +56,9 @@ class SpeedSelector extends HookConsumerWidget { }, ); - final scrollController = FixedExtentScrollController( + final scrollController = useFixedExtentScrollController( initialItem: availableSpeedsList.indexOf(currentSpeed), ); - const double itemExtent = 25; return Column( mainAxisSize: MainAxisSize.min, children: [ @@ -89,7 +91,6 @@ class SpeedSelector extends HookConsumerWidget { availableSpeedsList: availableSpeedsList, speedState: speedState, scrollController: scrollController, - itemExtent: itemExtent, ), ), ), @@ -159,14 +160,12 @@ class SpeedWheel extends StatelessWidget { required this.availableSpeedsList, required this.speedState, required this.scrollController, - required this.itemExtent, this.showIncrementButtons = true, }); final List availableSpeedsList; final ValueNotifier speedState; final FixedExtentScrollController scrollController; - final double itemExtent; final bool showIncrementButtons; @override @@ -203,7 +202,7 @@ class SpeedWheel extends StatelessWidget { physics: const FixedExtentScrollPhysics(), children: availableSpeedsList .map( - (speed) => SpeedLine(itemExtent: itemExtent, speed: speed), + (speed) => SpeedLine(speed: speed), ) .toList(), onSelectedItemChanged: (index) { @@ -236,11 +235,9 @@ class SpeedWheel extends StatelessWidget { class SpeedLine extends StatelessWidget { const SpeedLine({ super.key, - required this.itemExtent, required this.speed, }); - final double itemExtent; final double speed; @override @@ -250,7 +247,6 @@ class SpeedLine extends StatelessWidget { // a vertical line Expanded( child: Container( - // height: itemExtent, // thick if multiple of 1, thin if multiple of 0.5 and transparent if multiple of 0.05 width: speed % 0.5 == 0 ? 3 diff --git a/lib/features/sleep_timer/core/sleep_timer.dart b/lib/features/sleep_timer/core/sleep_timer.dart index 215c264..9350436 100644 --- a/lib/features/sleep_timer/core/sleep_timer.dart +++ b/lib/features/sleep_timer/core/sleep_timer.dart @@ -19,7 +19,17 @@ class SleepTimer { set duration(Duration value) { _duration = value; - clearCountDownTimer(); + _logger.fine('duration set to $value'); + + /// if the timer is active, restart it with the new duration + /// if the timer is not active, do nothing + if (isActive && player.playing) { + _logger.fine('timer is active counting down with new duration'); + startCountDown(value); + } else { + _logger.fine('timer is not active'); + clearCountDownTimer(); + } } /// The player to be paused diff --git a/lib/features/sleep_timer/providers/sleep_timer_provider.dart b/lib/features/sleep_timer/providers/sleep_timer_provider.dart index 92e5eb8..5c9ac2d 100644 --- a/lib/features/sleep_timer/providers/sleep_timer_provider.dart +++ b/lib/features/sleep_timer/providers/sleep_timer_provider.dart @@ -11,20 +11,16 @@ part 'sleep_timer_provider.g.dart'; class SleepTimer extends _$SleepTimer { @override core.SleepTimer? build() { - final appSettings = ref.watch(appSettingsProvider); - final sleepTimerSettings = appSettings.playerSettings.sleepTimerSettings; - bool isEnabled = sleepTimerSettings.autoTurnOnTimer; - if (!isEnabled) { + final sleepTimerSettings = ref.watch(sleepTimerSettingsProvider); + if (!sleepTimerSettings.autoTurnOnTimer) { return null; } if ((!sleepTimerSettings.alwaysAutoTurnOnTimer) && - (sleepTimerSettings.autoTurnOnTime - .toTimeOfDay() - .isAfter(TimeOfDay.now()) && - sleepTimerSettings.autoTurnOffTime - .toTimeOfDay() - .isBefore(TimeOfDay.now()))) { + !shouldBuildRightNow( + sleepTimerSettings.autoTurnOnTime, + sleepTimerSettings.autoTurnOffTime, + )) { return null; } @@ -36,10 +32,16 @@ class SleepTimer extends _$SleepTimer { return sleepTimer; } - void setTimer(Duration resultingDuration) { + void setTimer(Duration? resultingDuration, {bool notifyListeners = true}) { + if (resultingDuration == null || resultingDuration.inSeconds == 0) { + cancelTimer(); + return; + } if (state != null) { state!.duration = resultingDuration; - ref.notifyListeners(); + if (notifyListeners) { + ref.notifyListeners(); + } } else { final timer = core.SleepTimer( duration: resultingDuration, @@ -62,3 +64,11 @@ class SleepTimer extends _$SleepTimer { state = null; } } + +bool shouldBuildRightNow(Duration autoTurnOnTime, Duration autoTurnOffTime) { + final now = TimeOfDay.now(); + return now.isBetween( + autoTurnOnTime.toTimeOfDay(), + autoTurnOffTime.toTimeOfDay(), + ); +} diff --git a/lib/features/sleep_timer/providers/sleep_timer_provider.g.dart b/lib/features/sleep_timer/providers/sleep_timer_provider.g.dart index 6d820e4..7daade0 100644 --- a/lib/features/sleep_timer/providers/sleep_timer_provider.g.dart +++ b/lib/features/sleep_timer/providers/sleep_timer_provider.g.dart @@ -6,7 +6,7 @@ part of 'sleep_timer_provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$sleepTimerHash() => r'4f80bcc342e918c70c547b8b24790ccd88aba8c3'; +String _$sleepTimerHash() => r'2679454a217d0630a833d730557ab4e4feac2e56'; /// See also [SleepTimer]. @ProviderFor(SleepTimer) diff --git a/lib/features/sleep_timer/view/sleep_timer_button.dart b/lib/features/sleep_timer/view/sleep_timer_button.dart new file mode 100644 index 0000000..075b0e4 --- /dev/null +++ b/lib/features/sleep_timer/view/sleep_timer_button.dart @@ -0,0 +1,366 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:list_wheel_scroll_view_nls/list_wheel_scroll_view_nls.dart'; +import 'package:material_symbols_icons/symbols.dart'; +import 'package:vaani/features/player/view/player_when_expanded.dart'; +import 'package:vaani/features/player/view/widgets/speed_selector.dart'; +import 'package:vaani/features/sleep_timer/core/sleep_timer.dart'; +import 'package:vaani/features/sleep_timer/providers/sleep_timer_provider.dart' + show sleepTimerProvider; +import 'package:vaani/main.dart'; +import 'package:vaani/settings/app_settings_provider.dart'; +import 'package:vaani/shared/extensions/duration_format.dart'; +import 'package:vaani/shared/hooks.dart'; + +class SleepTimerButton extends HookConsumerWidget { + const SleepTimerButton({ + super.key, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final sleepTimer = ref.watch(sleepTimerProvider); + final durationState = useState(sleepTimer?.duration); + + // if sleep timer is not active, show the button with the sleep timer icon + // if the sleep timer is active, show the remaining time in a pill shaped container + return Tooltip( + message: 'Sleep Timer', + child: InkWell( + onTap: () async { + appLogger.fine('Sleep Timer button pressed'); + pendingPlayerModals++; + // show the sleep timer dialog + await showModalBottomSheet( + context: context, + barrierLabel: 'Sleep Timer', + builder: (context) { + return SleepTimerBottomSheet( + onDurationSelected: (duration) { + durationState.value = duration; + // ref + // .read(sleepTimerProvider.notifier) + // .setTimer(duration, notifyListeners: false); + }, + ); + }, + ); + pendingPlayerModals--; + ref.read(sleepTimerProvider.notifier).setTimer(durationState.value); + appLogger + .fine('Sleep Timer dialog closed with ${durationState.value}'); + }, + child: AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + child: sleepTimer == null + ? Icon( + Symbols.bedtime, + color: Theme.of(context).colorScheme.onSurface, + ) + : RemainingSleepTimeDisplay( + timer: sleepTimer, + ), + ), + ), + ); + } +} + +class SleepTimerBottomSheet extends HookConsumerWidget { + const SleepTimerBottomSheet({ + super.key, + this.onDurationSelected, + }); + + final void Function(Duration?)? onDurationSelected; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final sleepTimer = ref.watch(sleepTimerProvider); + final sleepTimerSettings = ref.watch(sleepTimerSettingsProvider); + + final durationOptions = sleepTimerSettings.presetDurations; + final minDuration = Duration.zero; + final maxDuration = [ + ...durationOptions, + sleepTimerSettings.maxDuration, + ].reduce((a, b) => a > b ? a : b); + final incrementStep = Duration(minutes: 1); + final allPossibleDurations = [ + for (var i = minDuration; i <= maxDuration; i += incrementStep) i, + ]; + + final scrollController = useFixedExtentScrollController( + initialItem: + allPossibleDurations.indexOf(sleepTimer?.duration ?? minDuration), + ); + + final durationState = useState( + sleepTimer?.duration ?? minDuration, + ); + + // useEffect to rebuild the sleep timer when the duration changes + useEffect( + () { + onDurationSelected?.call(durationState.value); + return null; + }, + [durationState.value], + ); + + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + // the title + Padding( + padding: const EdgeInsets.only(top: 16.0, bottom: 8.0), + child: Center( + child: Text( + 'Sleep Timer', + style: Theme.of(context).textTheme.titleLarge, + ), + ), + ), + + // a inverted triangle to indicate the speed selector + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.arrow_drop_down, + color: Theme.of(context).colorScheme.onSurface, + ), + ), + + // the speed selector + Padding( + padding: const EdgeInsets.only(bottom: 8.0, right: 8.0, left: 8.0), + child: SizedBox( + height: 80, + child: SleepTimerWheel( + durationState: durationState, + availableDurations: allPossibleDurations, + scrollController: scrollController, + ), + ), + ), + + // a cancel button to cancel the sleep timer + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: TextButton.icon( + onPressed: () { + ref.read(sleepTimerProvider.notifier).cancelTimer(); + onDurationSelected?.call(null); + Navigator.of(context).pop(); + }, + icon: const Icon(Symbols.bedtime_off), + label: const Text('Cancel Sleep Timer'), + ), + ), + + // the speed buttons + Padding( + padding: const EdgeInsets.all(8.0), + child: Wrap( + spacing: 8.0, + alignment: WrapAlignment.center, + runAlignment: WrapAlignment.center, + crossAxisAlignment: WrapCrossAlignment.center, + children: durationOptions + .map( + (timerDuration) => TextButton( + style: timerDuration == durationState.value + ? TextButton.styleFrom( + backgroundColor: + Theme.of(context).colorScheme.primaryContainer, + foregroundColor: Theme.of(context) + .colorScheme + .onPrimaryContainer, + ) + // border if not selected + : TextButton.styleFrom( + side: BorderSide( + color: Theme.of(context) + .colorScheme + .primaryContainer, + ), + ), + onPressed: () async { + // animate the wheel to the selected speed + var index = allPossibleDurations.indexOf(timerDuration); + // if the speed is not in the list + if (index == -1) { + // find the nearest speed + final nearestDuration = allPossibleDurations.firstWhere( + (element) => element > timerDuration, + orElse: () => allPossibleDurations.last, + ); + index = allPossibleDurations.indexOf(nearestDuration); + } + await scrollController.animateToItem( + index, + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOut, + ); + }, + child: Text(timerDuration.smartBinaryFormat), + ), + ) + .toList(), + ), + ), + ], + ); + } +} + +class RemainingSleepTimeDisplay extends HookConsumerWidget { + const RemainingSleepTimeDisplay({ + super.key, + required this.timer, + }); + + final SleepTimer timer; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final remainingTime = useStream(timer.remainingTimeStream).data; + return Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.primary, + borderRadius: BorderRadius.circular(16), + ), + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + child: Text( + timer.timer == null + ? timer.duration.smartBinaryFormat + : remainingTime?.smartBinaryFormat ?? '', + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: Theme.of(context).colorScheme.onPrimary, + ), + ), + ); + } +} + +class SleepTimerWheel extends StatelessWidget { + const SleepTimerWheel({ + super.key, + required this.availableDurations, + required this.scrollController, + required this.durationState, + this.showIncrementButtons = true, + }); + + final List availableDurations; + final ValueNotifier durationState; + final FixedExtentScrollController scrollController; + final bool showIncrementButtons; + + @override + Widget build(BuildContext context) { + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // a minus button to decrease the speed + if (showIncrementButtons) + IconButton.filledTonal( + icon: const Icon(Icons.remove), + onPressed: () { + // animate to index - 1 + final index = availableDurations + .indexOf(durationState.value ?? Duration.zero); + if (index > 0) { + scrollController.animateToItem( + index - 1, + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOut, + ); + } + }, + ), + // the speed selector wheel + Flexible( + child: ListWheelScrollViewX( + controller: scrollController, + scrollDirection: Axis.horizontal, + itemExtent: itemExtent, + diameterRatio: 1.5, squeeze: 1.2, + // useMagnifier: true, + // magnification: 1.5, + physics: const FixedExtentScrollPhysics(), + children: availableDurations + .map( + (duration) => DurationLine(duration: duration), + ) + .toList(), + onSelectedItemChanged: (index) { + durationState.value = availableDurations[index]; + }, + ), + ), + + if (showIncrementButtons) + // a plus button to increase the speed + IconButton.filledTonal( + icon: const Icon(Icons.add), + onPressed: () { + // animate to index + 1 + final index = availableDurations + .indexOf(durationState.value ?? Duration.zero); + if (index < availableDurations.length - 1) { + scrollController.animateToItem( + index + 1, + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOut, + ); + } + }, + ), + ], + ); + } +} + +class DurationLine extends StatelessWidget { + const DurationLine({ + super.key, + required this.duration, + }); + + final Duration duration; + + @override + Widget build(BuildContext context) { + return Column( + children: [ + // a vertical line + Expanded( + child: Container( + // thick if multiple of 1, thin if multiple of 0.5 and transparent if multiple of 0.05 + width: duration.inMinutes % 5 == 0 + ? 3 + : duration.inMinutes % 2.5 == 0 + ? 2 + : 0.5, + color: Theme.of(context).colorScheme.onSurface, + ), + ), + Opacity( + opacity: duration.inMinutes % 2.5 == 0 ? 1 : 0, + child: Text( + '${duration.inMinutes}m', + style: TextStyle( + fontSize: Theme.of(context).textTheme.labelSmall?.fontSize, + ), + ), + ), + ], + ); + } +} diff --git a/lib/settings/app_settings_provider.dart b/lib/settings/app_settings_provider.dart index 662a043..6d61774 100644 --- a/lib/settings/app_settings_provider.dart +++ b/lib/settings/app_settings_provider.dart @@ -60,3 +60,19 @@ class AppSettings extends _$AppSettings { state = const model.AppSettings(); } } + +// SleepTimerSettings provider but only rebuilds when the sleep timer settings change +@Riverpod(keepAlive: true) +class SleepTimerSettings extends _$SleepTimerSettings { + @override + model.SleepTimerSettings build() { + final settings = ref.read(appSettingsProvider).sleepTimerSettings; + state = settings; + ref.listen(appSettingsProvider, (a, b) { + if (a?.sleepTimerSettings != b.sleepTimerSettings) { + state = b.sleepTimerSettings; + } + }); + return state; + } +} diff --git a/lib/settings/app_settings_provider.g.dart b/lib/settings/app_settings_provider.g.dart index 2f321ee..df95738 100644 --- a/lib/settings/app_settings_provider.g.dart +++ b/lib/settings/app_settings_provider.g.dart @@ -21,5 +21,22 @@ final appSettingsProvider = ); typedef _$AppSettings = Notifier; +String _$sleepTimerSettingsHash() => + r'85bb3d3fb292b9a3a5b771d86e5fc57718519c69'; + +/// See also [SleepTimerSettings]. +@ProviderFor(SleepTimerSettings) +final sleepTimerSettingsProvider = + NotifierProvider.internal( + SleepTimerSettings.new, + name: r'sleepTimerSettingsProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$sleepTimerSettingsHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$SleepTimerSettings = Notifier; // ignore_for_file: type=lint // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/settings/models/app_settings.dart b/lib/settings/models/app_settings.dart index 7debe11..80262ea 100644 --- a/lib/settings/models/app_settings.dart +++ b/lib/settings/models/app_settings.dart @@ -14,6 +14,7 @@ class AppSettings with _$AppSettings { const factory AppSettings({ @Default(ThemeSettings()) ThemeSettings themeSettings, @Default(PlayerSettings()) PlayerSettings playerSettings, + @Default(SleepTimerSettings()) SleepTimerSettings sleepTimerSettings, @Default(DownloadSettings()) DownloadSettings downloadSettings, @Default(NotificationSettings()) NotificationSettings notificationSettings, @Default(ShakeDetectionSettings()) @@ -49,7 +50,6 @@ class PlayerSettings with _$PlayerSettings { @Default(0.05) double speedIncrement, @Default(0.1) double minSpeed, @Default(4) double maxSpeed, - @Default(SleepTimerSettings()) SleepTimerSettings sleepTimerSettings, @Default(Duration(seconds: 10)) Duration minimumPositionForReporting, @Default(Duration(seconds: 10)) Duration playbackReportInterval, @Default(Duration(seconds: 15)) Duration markCompleteWhenTimeLeft, @@ -81,22 +81,23 @@ class MinimizedPlayerSettings with _$MinimizedPlayerSettings { _$MinimizedPlayerSettingsFromJson(json); } -enum SleepTimerShakeSenseMode { never, always, nearEnds } - @freezed class SleepTimerSettings with _$SleepTimerSettings { const factory SleepTimerSettings({ @Default(Duration(minutes: 15)) Duration defaultDuration, - @Default(SleepTimerShakeSenseMode.always) - SleepTimerShakeSenseMode shakeSenseMode, - - /// the duration in which the shake is detected before the end of the timer and after the timer ends - /// only used if [shakeSenseMode] is [SleepTimerShakeSenseMode.nearEnds] - @Default(Duration(seconds: 30)) Duration shakeSenseDuration, - @Default(true) bool vibrateWhenReset, - @Default(false) bool beepWhenReset, + @Default( + [ + Duration(minutes: 5), + Duration(minutes: 10), + Duration(minutes: 15), + Duration(minutes: 20), + Duration(minutes: 30), + ], + ) + List presetDurations, + @Default(Duration(minutes: 100)) Duration maxDuration, @Default(false) bool fadeOutAudio, - @Default(0.5) double shakeDetectThreshold, + @Default(Duration(seconds: 20)) Duration fadeOutDuration, /// if true, the player will automatically rewind the audio when the sleep timer is stopped @Default(false) bool autoRewindWhenStopped, @@ -115,7 +116,7 @@ class SleepTimerSettings with _$SleepTimerSettings { @Default(false) bool autoTurnOnTimer, /// always auto turn on timer settings or during specific times - @Default(true) bool alwaysAutoTurnOnTimer, + @Default(false) bool alwaysAutoTurnOnTimer, /// auto timer settings, only used if [alwaysAutoTurnOnTimer] is false /// diff --git a/lib/settings/models/app_settings.freezed.dart b/lib/settings/models/app_settings.freezed.dart index 4980b85..3f8fd48 100644 --- a/lib/settings/models/app_settings.freezed.dart +++ b/lib/settings/models/app_settings.freezed.dart @@ -22,6 +22,8 @@ AppSettings _$AppSettingsFromJson(Map json) { mixin _$AppSettings { ThemeSettings get themeSettings => throw _privateConstructorUsedError; PlayerSettings get playerSettings => throw _privateConstructorUsedError; + SleepTimerSettings get sleepTimerSettings => + throw _privateConstructorUsedError; DownloadSettings get downloadSettings => throw _privateConstructorUsedError; NotificationSettings get notificationSettings => throw _privateConstructorUsedError; @@ -47,12 +49,14 @@ abstract class $AppSettingsCopyWith<$Res> { $Res call( {ThemeSettings themeSettings, PlayerSettings playerSettings, + SleepTimerSettings sleepTimerSettings, DownloadSettings downloadSettings, NotificationSettings notificationSettings, ShakeDetectionSettings shakeDetectionSettings}); $ThemeSettingsCopyWith<$Res> get themeSettings; $PlayerSettingsCopyWith<$Res> get playerSettings; + $SleepTimerSettingsCopyWith<$Res> get sleepTimerSettings; $DownloadSettingsCopyWith<$Res> get downloadSettings; $NotificationSettingsCopyWith<$Res> get notificationSettings; $ShakeDetectionSettingsCopyWith<$Res> get shakeDetectionSettings; @@ -75,6 +79,7 @@ class _$AppSettingsCopyWithImpl<$Res, $Val extends AppSettings> $Res call({ Object? themeSettings = null, Object? playerSettings = null, + Object? sleepTimerSettings = null, Object? downloadSettings = null, Object? notificationSettings = null, Object? shakeDetectionSettings = null, @@ -88,6 +93,10 @@ class _$AppSettingsCopyWithImpl<$Res, $Val extends AppSettings> ? _value.playerSettings : playerSettings // ignore: cast_nullable_to_non_nullable as PlayerSettings, + sleepTimerSettings: null == sleepTimerSettings + ? _value.sleepTimerSettings + : sleepTimerSettings // ignore: cast_nullable_to_non_nullable + as SleepTimerSettings, downloadSettings: null == downloadSettings ? _value.downloadSettings : downloadSettings // ignore: cast_nullable_to_non_nullable @@ -123,6 +132,17 @@ class _$AppSettingsCopyWithImpl<$Res, $Val extends AppSettings> }); } + /// Create a copy of AppSettings + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $SleepTimerSettingsCopyWith<$Res> get sleepTimerSettings { + return $SleepTimerSettingsCopyWith<$Res>(_value.sleepTimerSettings, + (value) { + return _then(_value.copyWith(sleepTimerSettings: value) as $Val); + }); + } + /// Create a copy of AppSettings /// with the given fields replaced by the non-null parameter values. @override @@ -167,6 +187,7 @@ abstract class _$$AppSettingsImplCopyWith<$Res> $Res call( {ThemeSettings themeSettings, PlayerSettings playerSettings, + SleepTimerSettings sleepTimerSettings, DownloadSettings downloadSettings, NotificationSettings notificationSettings, ShakeDetectionSettings shakeDetectionSettings}); @@ -176,6 +197,8 @@ abstract class _$$AppSettingsImplCopyWith<$Res> @override $PlayerSettingsCopyWith<$Res> get playerSettings; @override + $SleepTimerSettingsCopyWith<$Res> get sleepTimerSettings; + @override $DownloadSettingsCopyWith<$Res> get downloadSettings; @override $NotificationSettingsCopyWith<$Res> get notificationSettings; @@ -198,6 +221,7 @@ class __$$AppSettingsImplCopyWithImpl<$Res> $Res call({ Object? themeSettings = null, Object? playerSettings = null, + Object? sleepTimerSettings = null, Object? downloadSettings = null, Object? notificationSettings = null, Object? shakeDetectionSettings = null, @@ -211,6 +235,10 @@ class __$$AppSettingsImplCopyWithImpl<$Res> ? _value.playerSettings : playerSettings // ignore: cast_nullable_to_non_nullable as PlayerSettings, + sleepTimerSettings: null == sleepTimerSettings + ? _value.sleepTimerSettings + : sleepTimerSettings // ignore: cast_nullable_to_non_nullable + as SleepTimerSettings, downloadSettings: null == downloadSettings ? _value.downloadSettings : downloadSettings // ignore: cast_nullable_to_non_nullable @@ -233,6 +261,7 @@ class _$AppSettingsImpl implements _AppSettings { const _$AppSettingsImpl( {this.themeSettings = const ThemeSettings(), this.playerSettings = const PlayerSettings(), + this.sleepTimerSettings = const SleepTimerSettings(), this.downloadSettings = const DownloadSettings(), this.notificationSettings = const NotificationSettings(), this.shakeDetectionSettings = const ShakeDetectionSettings()}); @@ -248,6 +277,9 @@ class _$AppSettingsImpl implements _AppSettings { final PlayerSettings playerSettings; @override @JsonKey() + final SleepTimerSettings sleepTimerSettings; + @override + @JsonKey() final DownloadSettings downloadSettings; @override @JsonKey() @@ -258,7 +290,7 @@ class _$AppSettingsImpl implements _AppSettings { @override String toString() { - return 'AppSettings(themeSettings: $themeSettings, playerSettings: $playerSettings, downloadSettings: $downloadSettings, notificationSettings: $notificationSettings, shakeDetectionSettings: $shakeDetectionSettings)'; + return 'AppSettings(themeSettings: $themeSettings, playerSettings: $playerSettings, sleepTimerSettings: $sleepTimerSettings, downloadSettings: $downloadSettings, notificationSettings: $notificationSettings, shakeDetectionSettings: $shakeDetectionSettings)'; } @override @@ -270,6 +302,8 @@ class _$AppSettingsImpl implements _AppSettings { other.themeSettings == themeSettings) && (identical(other.playerSettings, playerSettings) || other.playerSettings == playerSettings) && + (identical(other.sleepTimerSettings, sleepTimerSettings) || + other.sleepTimerSettings == sleepTimerSettings) && (identical(other.downloadSettings, downloadSettings) || other.downloadSettings == downloadSettings) && (identical(other.notificationSettings, notificationSettings) || @@ -280,8 +314,14 @@ class _$AppSettingsImpl implements _AppSettings { @JsonKey(includeFromJson: false, includeToJson: false) @override - int get hashCode => Object.hash(runtimeType, themeSettings, playerSettings, - downloadSettings, notificationSettings, shakeDetectionSettings); + int get hashCode => Object.hash( + runtimeType, + themeSettings, + playerSettings, + sleepTimerSettings, + downloadSettings, + notificationSettings, + shakeDetectionSettings); /// Create a copy of AppSettings /// with the given fields replaced by the non-null parameter values. @@ -303,6 +343,7 @@ abstract class _AppSettings implements AppSettings { const factory _AppSettings( {final ThemeSettings themeSettings, final PlayerSettings playerSettings, + final SleepTimerSettings sleepTimerSettings, final DownloadSettings downloadSettings, final NotificationSettings notificationSettings, final ShakeDetectionSettings shakeDetectionSettings}) = _$AppSettingsImpl; @@ -315,6 +356,8 @@ abstract class _AppSettings implements AppSettings { @override PlayerSettings get playerSettings; @override + SleepTimerSettings get sleepTimerSettings; + @override DownloadSettings get downloadSettings; @override NotificationSettings get notificationSettings; @@ -552,8 +595,6 @@ mixin _$PlayerSettings { double get speedIncrement => throw _privateConstructorUsedError; double get minSpeed => throw _privateConstructorUsedError; double get maxSpeed => throw _privateConstructorUsedError; - SleepTimerSettings get sleepTimerSettings => - throw _privateConstructorUsedError; Duration get minimumPositionForReporting => throw _privateConstructorUsedError; Duration get playbackReportInterval => throw _privateConstructorUsedError; @@ -585,7 +626,6 @@ abstract class $PlayerSettingsCopyWith<$Res> { double speedIncrement, double minSpeed, double maxSpeed, - SleepTimerSettings sleepTimerSettings, Duration minimumPositionForReporting, Duration playbackReportInterval, Duration markCompleteWhenTimeLeft, @@ -593,7 +633,6 @@ abstract class $PlayerSettingsCopyWith<$Res> { $MinimizedPlayerSettingsCopyWith<$Res> get miniPlayerSettings; $ExpandedPlayerSettingsCopyWith<$Res> get expandedPlayerSettings; - $SleepTimerSettingsCopyWith<$Res> get sleepTimerSettings; } /// @nodoc @@ -619,7 +658,6 @@ class _$PlayerSettingsCopyWithImpl<$Res, $Val extends PlayerSettings> Object? speedIncrement = null, Object? minSpeed = null, Object? maxSpeed = null, - Object? sleepTimerSettings = null, Object? minimumPositionForReporting = null, Object? playbackReportInterval = null, Object? markCompleteWhenTimeLeft = null, @@ -658,10 +696,6 @@ class _$PlayerSettingsCopyWithImpl<$Res, $Val extends PlayerSettings> ? _value.maxSpeed : maxSpeed // ignore: cast_nullable_to_non_nullable as double, - sleepTimerSettings: null == sleepTimerSettings - ? _value.sleepTimerSettings - : sleepTimerSettings // ignore: cast_nullable_to_non_nullable - as SleepTimerSettings, minimumPositionForReporting: null == minimumPositionForReporting ? _value.minimumPositionForReporting : minimumPositionForReporting // ignore: cast_nullable_to_non_nullable @@ -702,17 +736,6 @@ class _$PlayerSettingsCopyWithImpl<$Res, $Val extends PlayerSettings> return _then(_value.copyWith(expandedPlayerSettings: value) as $Val); }); } - - /// Create a copy of PlayerSettings - /// with the given fields replaced by the non-null parameter values. - @override - @pragma('vm:prefer-inline') - $SleepTimerSettingsCopyWith<$Res> get sleepTimerSettings { - return $SleepTimerSettingsCopyWith<$Res>(_value.sleepTimerSettings, - (value) { - return _then(_value.copyWith(sleepTimerSettings: value) as $Val); - }); - } } /// @nodoc @@ -732,7 +755,6 @@ abstract class _$$PlayerSettingsImplCopyWith<$Res> double speedIncrement, double minSpeed, double maxSpeed, - SleepTimerSettings sleepTimerSettings, Duration minimumPositionForReporting, Duration playbackReportInterval, Duration markCompleteWhenTimeLeft, @@ -742,8 +764,6 @@ abstract class _$$PlayerSettingsImplCopyWith<$Res> $MinimizedPlayerSettingsCopyWith<$Res> get miniPlayerSettings; @override $ExpandedPlayerSettingsCopyWith<$Res> get expandedPlayerSettings; - @override - $SleepTimerSettingsCopyWith<$Res> get sleepTimerSettings; } /// @nodoc @@ -767,7 +787,6 @@ class __$$PlayerSettingsImplCopyWithImpl<$Res> Object? speedIncrement = null, Object? minSpeed = null, Object? maxSpeed = null, - Object? sleepTimerSettings = null, Object? minimumPositionForReporting = null, Object? playbackReportInterval = null, Object? markCompleteWhenTimeLeft = null, @@ -806,10 +825,6 @@ class __$$PlayerSettingsImplCopyWithImpl<$Res> ? _value.maxSpeed : maxSpeed // ignore: cast_nullable_to_non_nullable as double, - sleepTimerSettings: null == sleepTimerSettings - ? _value.sleepTimerSettings - : sleepTimerSettings // ignore: cast_nullable_to_non_nullable - as SleepTimerSettings, minimumPositionForReporting: null == minimumPositionForReporting ? _value.minimumPositionForReporting : minimumPositionForReporting // ignore: cast_nullable_to_non_nullable @@ -842,7 +857,6 @@ class _$PlayerSettingsImpl implements _PlayerSettings { this.speedIncrement = 0.05, this.minSpeed = 0.1, this.maxSpeed = 4, - this.sleepTimerSettings = const SleepTimerSettings(), this.minimumPositionForReporting = const Duration(seconds: 10), this.playbackReportInterval = const Duration(seconds: 10), this.markCompleteWhenTimeLeft = const Duration(seconds: 15), @@ -884,9 +898,6 @@ class _$PlayerSettingsImpl implements _PlayerSettings { final double maxSpeed; @override @JsonKey() - final SleepTimerSettings sleepTimerSettings; - @override - @JsonKey() final Duration minimumPositionForReporting; @override @JsonKey() @@ -900,7 +911,7 @@ class _$PlayerSettingsImpl implements _PlayerSettings { @override String toString() { - return 'PlayerSettings(miniPlayerSettings: $miniPlayerSettings, expandedPlayerSettings: $expandedPlayerSettings, preferredDefaultVolume: $preferredDefaultVolume, preferredDefaultSpeed: $preferredDefaultSpeed, speedOptions: $speedOptions, speedIncrement: $speedIncrement, minSpeed: $minSpeed, maxSpeed: $maxSpeed, sleepTimerSettings: $sleepTimerSettings, minimumPositionForReporting: $minimumPositionForReporting, playbackReportInterval: $playbackReportInterval, markCompleteWhenTimeLeft: $markCompleteWhenTimeLeft, configurePlayerForEveryBook: $configurePlayerForEveryBook)'; + return 'PlayerSettings(miniPlayerSettings: $miniPlayerSettings, expandedPlayerSettings: $expandedPlayerSettings, preferredDefaultVolume: $preferredDefaultVolume, preferredDefaultSpeed: $preferredDefaultSpeed, speedOptions: $speedOptions, speedIncrement: $speedIncrement, minSpeed: $minSpeed, maxSpeed: $maxSpeed, minimumPositionForReporting: $minimumPositionForReporting, playbackReportInterval: $playbackReportInterval, markCompleteWhenTimeLeft: $markCompleteWhenTimeLeft, configurePlayerForEveryBook: $configurePlayerForEveryBook)'; } @override @@ -924,8 +935,6 @@ class _$PlayerSettingsImpl implements _PlayerSettings { other.minSpeed == minSpeed) && (identical(other.maxSpeed, maxSpeed) || other.maxSpeed == maxSpeed) && - (identical(other.sleepTimerSettings, sleepTimerSettings) || - other.sleepTimerSettings == sleepTimerSettings) && (identical(other.minimumPositionForReporting, minimumPositionForReporting) || other.minimumPositionForReporting == @@ -953,7 +962,6 @@ class _$PlayerSettingsImpl implements _PlayerSettings { speedIncrement, minSpeed, maxSpeed, - sleepTimerSettings, minimumPositionForReporting, playbackReportInterval, markCompleteWhenTimeLeft, @@ -986,7 +994,6 @@ abstract class _PlayerSettings implements PlayerSettings { final double speedIncrement, final double minSpeed, final double maxSpeed, - final SleepTimerSettings sleepTimerSettings, final Duration minimumPositionForReporting, final Duration playbackReportInterval, final Duration markCompleteWhenTimeLeft, @@ -1012,8 +1019,6 @@ abstract class _PlayerSettings implements PlayerSettings { @override double get maxSpeed; @override - SleepTimerSettings get sleepTimerSettings; - @override Duration get minimumPositionForReporting; @override Duration get playbackReportInterval; @@ -1374,16 +1379,10 @@ SleepTimerSettings _$SleepTimerSettingsFromJson(Map json) { /// @nodoc mixin _$SleepTimerSettings { Duration get defaultDuration => throw _privateConstructorUsedError; - SleepTimerShakeSenseMode get shakeSenseMode => - throw _privateConstructorUsedError; - - /// the duration in which the shake is detected before the end of the timer and after the timer ends - /// only used if [shakeSenseMode] is [SleepTimerShakeSenseMode.nearEnds] - Duration get shakeSenseDuration => throw _privateConstructorUsedError; - bool get vibrateWhenReset => throw _privateConstructorUsedError; - bool get beepWhenReset => throw _privateConstructorUsedError; + List get presetDurations => throw _privateConstructorUsedError; + Duration get maxDuration => throw _privateConstructorUsedError; bool get fadeOutAudio => throw _privateConstructorUsedError; - double get shakeDetectThreshold => throw _privateConstructorUsedError; + Duration get fadeOutDuration => throw _privateConstructorUsedError; /// if true, the player will automatically rewind the audio when the sleep timer is stopped bool get autoRewindWhenStopped => throw _privateConstructorUsedError; @@ -1422,12 +1421,10 @@ abstract class $SleepTimerSettingsCopyWith<$Res> { @useResult $Res call( {Duration defaultDuration, - SleepTimerShakeSenseMode shakeSenseMode, - Duration shakeSenseDuration, - bool vibrateWhenReset, - bool beepWhenReset, + List presetDurations, + Duration maxDuration, bool fadeOutAudio, - double shakeDetectThreshold, + Duration fadeOutDuration, bool autoRewindWhenStopped, Map autoRewindDurations, bool autoTurnOnTimer, @@ -1452,12 +1449,10 @@ class _$SleepTimerSettingsCopyWithImpl<$Res, $Val extends SleepTimerSettings> @override $Res call({ Object? defaultDuration = null, - Object? shakeSenseMode = null, - Object? shakeSenseDuration = null, - Object? vibrateWhenReset = null, - Object? beepWhenReset = null, + Object? presetDurations = null, + Object? maxDuration = null, Object? fadeOutAudio = null, - Object? shakeDetectThreshold = null, + Object? fadeOutDuration = null, Object? autoRewindWhenStopped = null, Object? autoRewindDurations = null, Object? autoTurnOnTimer = null, @@ -1470,30 +1465,22 @@ class _$SleepTimerSettingsCopyWithImpl<$Res, $Val extends SleepTimerSettings> ? _value.defaultDuration : defaultDuration // ignore: cast_nullable_to_non_nullable as Duration, - shakeSenseMode: null == shakeSenseMode - ? _value.shakeSenseMode - : shakeSenseMode // ignore: cast_nullable_to_non_nullable - as SleepTimerShakeSenseMode, - shakeSenseDuration: null == shakeSenseDuration - ? _value.shakeSenseDuration - : shakeSenseDuration // ignore: cast_nullable_to_non_nullable + presetDurations: null == presetDurations + ? _value.presetDurations + : presetDurations // ignore: cast_nullable_to_non_nullable + as List, + maxDuration: null == maxDuration + ? _value.maxDuration + : maxDuration // ignore: cast_nullable_to_non_nullable as Duration, - vibrateWhenReset: null == vibrateWhenReset - ? _value.vibrateWhenReset - : vibrateWhenReset // ignore: cast_nullable_to_non_nullable - as bool, - beepWhenReset: null == beepWhenReset - ? _value.beepWhenReset - : beepWhenReset // ignore: cast_nullable_to_non_nullable - as bool, fadeOutAudio: null == fadeOutAudio ? _value.fadeOutAudio : fadeOutAudio // ignore: cast_nullable_to_non_nullable as bool, - shakeDetectThreshold: null == shakeDetectThreshold - ? _value.shakeDetectThreshold - : shakeDetectThreshold // ignore: cast_nullable_to_non_nullable - as double, + fadeOutDuration: null == fadeOutDuration + ? _value.fadeOutDuration + : fadeOutDuration // ignore: cast_nullable_to_non_nullable + as Duration, autoRewindWhenStopped: null == autoRewindWhenStopped ? _value.autoRewindWhenStopped : autoRewindWhenStopped // ignore: cast_nullable_to_non_nullable @@ -1532,12 +1519,10 @@ abstract class _$$SleepTimerSettingsImplCopyWith<$Res> @useResult $Res call( {Duration defaultDuration, - SleepTimerShakeSenseMode shakeSenseMode, - Duration shakeSenseDuration, - bool vibrateWhenReset, - bool beepWhenReset, + List presetDurations, + Duration maxDuration, bool fadeOutAudio, - double shakeDetectThreshold, + Duration fadeOutDuration, bool autoRewindWhenStopped, Map autoRewindDurations, bool autoTurnOnTimer, @@ -1560,12 +1545,10 @@ class __$$SleepTimerSettingsImplCopyWithImpl<$Res> @override $Res call({ Object? defaultDuration = null, - Object? shakeSenseMode = null, - Object? shakeSenseDuration = null, - Object? vibrateWhenReset = null, - Object? beepWhenReset = null, + Object? presetDurations = null, + Object? maxDuration = null, Object? fadeOutAudio = null, - Object? shakeDetectThreshold = null, + Object? fadeOutDuration = null, Object? autoRewindWhenStopped = null, Object? autoRewindDurations = null, Object? autoTurnOnTimer = null, @@ -1578,30 +1561,22 @@ class __$$SleepTimerSettingsImplCopyWithImpl<$Res> ? _value.defaultDuration : defaultDuration // ignore: cast_nullable_to_non_nullable as Duration, - shakeSenseMode: null == shakeSenseMode - ? _value.shakeSenseMode - : shakeSenseMode // ignore: cast_nullable_to_non_nullable - as SleepTimerShakeSenseMode, - shakeSenseDuration: null == shakeSenseDuration - ? _value.shakeSenseDuration - : shakeSenseDuration // ignore: cast_nullable_to_non_nullable + presetDurations: null == presetDurations + ? _value._presetDurations + : presetDurations // ignore: cast_nullable_to_non_nullable + as List, + maxDuration: null == maxDuration + ? _value.maxDuration + : maxDuration // ignore: cast_nullable_to_non_nullable as Duration, - vibrateWhenReset: null == vibrateWhenReset - ? _value.vibrateWhenReset - : vibrateWhenReset // ignore: cast_nullable_to_non_nullable - as bool, - beepWhenReset: null == beepWhenReset - ? _value.beepWhenReset - : beepWhenReset // ignore: cast_nullable_to_non_nullable - as bool, fadeOutAudio: null == fadeOutAudio ? _value.fadeOutAudio : fadeOutAudio // ignore: cast_nullable_to_non_nullable as bool, - shakeDetectThreshold: null == shakeDetectThreshold - ? _value.shakeDetectThreshold - : shakeDetectThreshold // ignore: cast_nullable_to_non_nullable - as double, + fadeOutDuration: null == fadeOutDuration + ? _value.fadeOutDuration + : fadeOutDuration // ignore: cast_nullable_to_non_nullable + as Duration, autoRewindWhenStopped: null == autoRewindWhenStopped ? _value.autoRewindWhenStopped : autoRewindWhenStopped // ignore: cast_nullable_to_non_nullable @@ -1635,12 +1610,16 @@ class __$$SleepTimerSettingsImplCopyWithImpl<$Res> class _$SleepTimerSettingsImpl implements _SleepTimerSettings { const _$SleepTimerSettingsImpl( {this.defaultDuration = const Duration(minutes: 15), - this.shakeSenseMode = SleepTimerShakeSenseMode.always, - this.shakeSenseDuration = const Duration(seconds: 30), - this.vibrateWhenReset = true, - this.beepWhenReset = false, + final List presetDurations = const [ + Duration(minutes: 5), + Duration(minutes: 10), + Duration(minutes: 15), + Duration(minutes: 20), + Duration(minutes: 30) + ], + this.maxDuration = const Duration(minutes: 100), this.fadeOutAudio = false, - this.shakeDetectThreshold = 0.5, + this.fadeOutDuration = const Duration(seconds: 20), this.autoRewindWhenStopped = false, final Map autoRewindDurations = const { 5: Duration(seconds: 10), @@ -1650,10 +1629,11 @@ class _$SleepTimerSettingsImpl implements _SleepTimerSettings { 120: Duration(minutes: 2) }, this.autoTurnOnTimer = false, - this.alwaysAutoTurnOnTimer = true, + this.alwaysAutoTurnOnTimer = false, this.autoTurnOnTime = const Duration(hours: 22, minutes: 0), this.autoTurnOffTime = const Duration(hours: 6, minutes: 0)}) - : _autoRewindDurations = autoRewindDurations; + : _presetDurations = presetDurations, + _autoRewindDurations = autoRewindDurations; factory _$SleepTimerSettingsImpl.fromJson(Map json) => _$$SleepTimerSettingsImplFromJson(json); @@ -1661,27 +1641,24 @@ class _$SleepTimerSettingsImpl implements _SleepTimerSettings { @override @JsonKey() final Duration defaultDuration; + final List _presetDurations; @override @JsonKey() - final SleepTimerShakeSenseMode shakeSenseMode; + List get presetDurations { + if (_presetDurations is EqualUnmodifiableListView) return _presetDurations; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_presetDurations); + } - /// the duration in which the shake is detected before the end of the timer and after the timer ends - /// only used if [shakeSenseMode] is [SleepTimerShakeSenseMode.nearEnds] @override @JsonKey() - final Duration shakeSenseDuration; - @override - @JsonKey() - final bool vibrateWhenReset; - @override - @JsonKey() - final bool beepWhenReset; + final Duration maxDuration; @override @JsonKey() final bool fadeOutAudio; @override @JsonKey() - final double shakeDetectThreshold; + final Duration fadeOutDuration; /// if true, the player will automatically rewind the audio when the sleep timer is stopped @override @@ -1723,7 +1700,7 @@ class _$SleepTimerSettingsImpl implements _SleepTimerSettings { @override String toString() { - return 'SleepTimerSettings(defaultDuration: $defaultDuration, shakeSenseMode: $shakeSenseMode, shakeSenseDuration: $shakeSenseDuration, vibrateWhenReset: $vibrateWhenReset, beepWhenReset: $beepWhenReset, fadeOutAudio: $fadeOutAudio, shakeDetectThreshold: $shakeDetectThreshold, autoRewindWhenStopped: $autoRewindWhenStopped, autoRewindDurations: $autoRewindDurations, autoTurnOnTimer: $autoTurnOnTimer, alwaysAutoTurnOnTimer: $alwaysAutoTurnOnTimer, autoTurnOnTime: $autoTurnOnTime, autoTurnOffTime: $autoTurnOffTime)'; + return 'SleepTimerSettings(defaultDuration: $defaultDuration, presetDurations: $presetDurations, maxDuration: $maxDuration, fadeOutAudio: $fadeOutAudio, fadeOutDuration: $fadeOutDuration, autoRewindWhenStopped: $autoRewindWhenStopped, autoRewindDurations: $autoRewindDurations, autoTurnOnTimer: $autoTurnOnTimer, alwaysAutoTurnOnTimer: $alwaysAutoTurnOnTimer, autoTurnOnTime: $autoTurnOnTime, autoTurnOffTime: $autoTurnOffTime)'; } @override @@ -1733,18 +1710,14 @@ class _$SleepTimerSettingsImpl implements _SleepTimerSettings { other is _$SleepTimerSettingsImpl && (identical(other.defaultDuration, defaultDuration) || other.defaultDuration == defaultDuration) && - (identical(other.shakeSenseMode, shakeSenseMode) || - other.shakeSenseMode == shakeSenseMode) && - (identical(other.shakeSenseDuration, shakeSenseDuration) || - other.shakeSenseDuration == shakeSenseDuration) && - (identical(other.vibrateWhenReset, vibrateWhenReset) || - other.vibrateWhenReset == vibrateWhenReset) && - (identical(other.beepWhenReset, beepWhenReset) || - other.beepWhenReset == beepWhenReset) && + const DeepCollectionEquality() + .equals(other._presetDurations, _presetDurations) && + (identical(other.maxDuration, maxDuration) || + other.maxDuration == maxDuration) && (identical(other.fadeOutAudio, fadeOutAudio) || other.fadeOutAudio == fadeOutAudio) && - (identical(other.shakeDetectThreshold, shakeDetectThreshold) || - other.shakeDetectThreshold == shakeDetectThreshold) && + (identical(other.fadeOutDuration, fadeOutDuration) || + other.fadeOutDuration == fadeOutDuration) && (identical(other.autoRewindWhenStopped, autoRewindWhenStopped) || other.autoRewindWhenStopped == autoRewindWhenStopped) && const DeepCollectionEquality() @@ -1764,12 +1737,10 @@ class _$SleepTimerSettingsImpl implements _SleepTimerSettings { int get hashCode => Object.hash( runtimeType, defaultDuration, - shakeSenseMode, - shakeSenseDuration, - vibrateWhenReset, - beepWhenReset, + const DeepCollectionEquality().hash(_presetDurations), + maxDuration, fadeOutAudio, - shakeDetectThreshold, + fadeOutDuration, autoRewindWhenStopped, const DeepCollectionEquality().hash(_autoRewindDurations), autoTurnOnTimer, @@ -1797,12 +1768,10 @@ class _$SleepTimerSettingsImpl implements _SleepTimerSettings { abstract class _SleepTimerSettings implements SleepTimerSettings { const factory _SleepTimerSettings( {final Duration defaultDuration, - final SleepTimerShakeSenseMode shakeSenseMode, - final Duration shakeSenseDuration, - final bool vibrateWhenReset, - final bool beepWhenReset, + final List presetDurations, + final Duration maxDuration, final bool fadeOutAudio, - final double shakeDetectThreshold, + final Duration fadeOutDuration, final bool autoRewindWhenStopped, final Map autoRewindDurations, final bool autoTurnOnTimer, @@ -1816,20 +1785,13 @@ abstract class _SleepTimerSettings implements SleepTimerSettings { @override Duration get defaultDuration; @override - SleepTimerShakeSenseMode get shakeSenseMode; - - /// the duration in which the shake is detected before the end of the timer and after the timer ends - /// only used if [shakeSenseMode] is [SleepTimerShakeSenseMode.nearEnds] + List get presetDurations; @override - Duration get shakeSenseDuration; - @override - bool get vibrateWhenReset; - @override - bool get beepWhenReset; + Duration get maxDuration; @override bool get fadeOutAudio; @override - double get shakeDetectThreshold; + Duration get fadeOutDuration; /// if true, the player will automatically rewind the audio when the sleep timer is stopped @override diff --git a/lib/settings/models/app_settings.g.dart b/lib/settings/models/app_settings.g.dart index da9ca9c..90b317e 100644 --- a/lib/settings/models/app_settings.g.dart +++ b/lib/settings/models/app_settings.g.dart @@ -16,6 +16,10 @@ _$AppSettingsImpl _$$AppSettingsImplFromJson(Map json) => ? const PlayerSettings() : PlayerSettings.fromJson( json['playerSettings'] as Map), + sleepTimerSettings: json['sleepTimerSettings'] == null + ? const SleepTimerSettings() + : SleepTimerSettings.fromJson( + json['sleepTimerSettings'] as Map), downloadSettings: json['downloadSettings'] == null ? const DownloadSettings() : DownloadSettings.fromJson( @@ -34,6 +38,7 @@ Map _$$AppSettingsImplToJson(_$AppSettingsImpl instance) => { 'themeSettings': instance.themeSettings, 'playerSettings': instance.playerSettings, + 'sleepTimerSettings': instance.sleepTimerSettings, 'downloadSettings': instance.downloadSettings, 'notificationSettings': instance.notificationSettings, 'shakeDetectionSettings': instance.shakeDetectionSettings, @@ -77,10 +82,6 @@ _$PlayerSettingsImpl _$$PlayerSettingsImplFromJson(Map json) => speedIncrement: (json['speedIncrement'] as num?)?.toDouble() ?? 0.05, minSpeed: (json['minSpeed'] as num?)?.toDouble() ?? 0.1, maxSpeed: (json['maxSpeed'] as num?)?.toDouble() ?? 4, - sleepTimerSettings: json['sleepTimerSettings'] == null - ? const SleepTimerSettings() - : SleepTimerSettings.fromJson( - json['sleepTimerSettings'] as Map), minimumPositionForReporting: json['minimumPositionForReporting'] == null ? const Duration(seconds: 10) : Duration( @@ -109,7 +110,6 @@ Map _$$PlayerSettingsImplToJson( 'speedIncrement': instance.speedIncrement, 'minSpeed': instance.minSpeed, 'maxSpeed': instance.maxSpeed, - 'sleepTimerSettings': instance.sleepTimerSettings, 'minimumPositionForReporting': instance.minimumPositionForReporting.inMicroseconds, 'playbackReportInterval': instance.playbackReportInterval.inMicroseconds, @@ -150,17 +150,23 @@ _$SleepTimerSettingsImpl _$$SleepTimerSettingsImplFromJson( defaultDuration: json['defaultDuration'] == null ? const Duration(minutes: 15) : Duration(microseconds: (json['defaultDuration'] as num).toInt()), - shakeSenseMode: $enumDecodeNullable( - _$SleepTimerShakeSenseModeEnumMap, json['shakeSenseMode']) ?? - SleepTimerShakeSenseMode.always, - shakeSenseDuration: json['shakeSenseDuration'] == null - ? const Duration(seconds: 30) - : Duration(microseconds: (json['shakeSenseDuration'] as num).toInt()), - vibrateWhenReset: json['vibrateWhenReset'] as bool? ?? true, - beepWhenReset: json['beepWhenReset'] as bool? ?? false, + presetDurations: (json['presetDurations'] as List?) + ?.map((e) => Duration(microseconds: (e as num).toInt())) + .toList() ?? + const [ + Duration(minutes: 5), + Duration(minutes: 10), + Duration(minutes: 15), + Duration(minutes: 20), + Duration(minutes: 30) + ], + maxDuration: json['maxDuration'] == null + ? const Duration(minutes: 100) + : Duration(microseconds: (json['maxDuration'] as num).toInt()), fadeOutAudio: json['fadeOutAudio'] as bool? ?? false, - shakeDetectThreshold: - (json['shakeDetectThreshold'] as num?)?.toDouble() ?? 0.5, + fadeOutDuration: json['fadeOutDuration'] == null + ? const Duration(seconds: 20) + : Duration(microseconds: (json['fadeOutDuration'] as num).toInt()), autoRewindWhenStopped: json['autoRewindWhenStopped'] as bool? ?? false, autoRewindDurations: (json['autoRewindDurations'] as Map?)?.map( @@ -175,7 +181,7 @@ _$SleepTimerSettingsImpl _$$SleepTimerSettingsImplFromJson( 120: Duration(minutes: 2) }, autoTurnOnTimer: json['autoTurnOnTimer'] as bool? ?? false, - alwaysAutoTurnOnTimer: json['alwaysAutoTurnOnTimer'] as bool? ?? true, + alwaysAutoTurnOnTimer: json['alwaysAutoTurnOnTimer'] as bool? ?? false, autoTurnOnTime: json['autoTurnOnTime'] == null ? const Duration(hours: 22, minutes: 0) : Duration(microseconds: (json['autoTurnOnTime'] as num).toInt()), @@ -188,13 +194,11 @@ Map _$$SleepTimerSettingsImplToJson( _$SleepTimerSettingsImpl instance) => { 'defaultDuration': instance.defaultDuration.inMicroseconds, - 'shakeSenseMode': - _$SleepTimerShakeSenseModeEnumMap[instance.shakeSenseMode]!, - 'shakeSenseDuration': instance.shakeSenseDuration.inMicroseconds, - 'vibrateWhenReset': instance.vibrateWhenReset, - 'beepWhenReset': instance.beepWhenReset, + 'presetDurations': + instance.presetDurations.map((e) => e.inMicroseconds).toList(), + 'maxDuration': instance.maxDuration.inMicroseconds, 'fadeOutAudio': instance.fadeOutAudio, - 'shakeDetectThreshold': instance.shakeDetectThreshold, + 'fadeOutDuration': instance.fadeOutDuration.inMicroseconds, 'autoRewindWhenStopped': instance.autoRewindWhenStopped, 'autoRewindDurations': instance.autoRewindDurations .map((k, e) => MapEntry(k.toString(), e.inMicroseconds)), @@ -204,12 +208,6 @@ Map _$$SleepTimerSettingsImplToJson( 'autoTurnOffTime': instance.autoTurnOffTime.inMicroseconds, }; -const _$SleepTimerShakeSenseModeEnumMap = { - SleepTimerShakeSenseMode.never: 'never', - SleepTimerShakeSenseMode.always: 'always', - SleepTimerShakeSenseMode.nearEnds: 'nearEnds', -}; - _$DownloadSettingsImpl _$$DownloadSettingsImplFromJson( Map json) => _$DownloadSettingsImpl( diff --git a/lib/settings/view/app_settings_page.dart b/lib/settings/view/app_settings_page.dart index 58754c6..77afaae 100644 --- a/lib/settings/view/app_settings_page.dart +++ b/lib/settings/view/app_settings_page.dart @@ -6,6 +6,7 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_settings_ui/flutter_settings_ui.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:material_symbols_icons/symbols.dart'; import 'package:vaani/api/authenticated_user_provider.dart'; import 'package:vaani/api/server_provider.dart'; import 'package:vaani/router/router.dart'; @@ -26,7 +27,7 @@ class AppSettingsPage extends HookConsumerWidget { final registeredServersAsList = registeredServers.toList(); final availableUsers = ref.watch(authenticatedUserProvider); final serverURIController = useTextEditingController(); - final sleepTimerSettings = appSettings.playerSettings.sleepTimerSettings; + final sleepTimerSettings = appSettings.sleepTimerSettings; return SimpleSettingsPage( title: const Text('App Settings'), @@ -91,15 +92,15 @@ class AppSettingsPage extends HookConsumerWidget { 'Automatically turn on the sleep timer based on the time of day', ), leading: sleepTimerSettings.autoTurnOnTimer - ? const Icon(Icons.timer) - : const Icon(Icons.timer_off), + ? const Icon(Symbols.time_auto, fill: 1) + : const Icon(Symbols.timer_off, fill: 1), onPressed: (context) { context.pushNamed(Routes.autoSleepTimerSettings.name); }, value: sleepTimerSettings.autoTurnOnTimer, onToggle: (value) { ref.read(appSettingsProvider.notifier).update( - appSettings.copyWith.playerSettings.sleepTimerSettings( + appSettings.copyWith.sleepTimerSettings( autoTurnOnTimer: value, ), ); diff --git a/lib/settings/view/auto_sleep_timer_settings_page.dart b/lib/settings/view/auto_sleep_timer_settings_page.dart index 29524a9..fe7d4b3 100644 --- a/lib/settings/view/auto_sleep_timer_settings_page.dart +++ b/lib/settings/view/auto_sleep_timer_settings_page.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_settings_ui/flutter_settings_ui.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:material_symbols_icons/symbols.dart'; import 'package:vaani/settings/app_settings_provider.dart'; import 'package:vaani/settings/view/simple_settings_page.dart'; import 'package:vaani/shared/extensions/time_of_day.dart'; @@ -13,8 +14,13 @@ class AutoSleepTimerSettingsPage extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final appSettings = ref.watch(appSettingsProvider); - final sleepTimerSettings = appSettings.playerSettings.sleepTimerSettings; + final sleepTimerSettings = appSettings.sleepTimerSettings; + var enabled = sleepTimerSettings.autoTurnOnTimer && + !sleepTimerSettings.alwaysAutoTurnOnTimer; + final selectedValueColor = enabled + ? Theme.of(context).colorScheme.primary + : Theme.of(context).disabledColor; return SimpleSettingsPage( title: const Text('Auto Sleep Timer Settings'), sections: [ @@ -31,11 +37,11 @@ class AutoSleepTimerSettingsPage extends HookConsumerWidget { 'Automatically turn on the sleep timer based on the time of day', ), leading: sleepTimerSettings.autoTurnOnTimer - ? const Icon(Icons.timer) - : const Icon(Icons.timer_off), + ? const Icon(Symbols.time_auto) + : const Icon(Symbols.timer_off), onToggle: (value) { ref.read(appSettingsProvider.notifier).update( - appSettings.copyWith.playerSettings.sleepTimerSettings( + appSettings.copyWith.sleepTimerSettings( autoTurnOnTimer: value, ), ); @@ -44,8 +50,9 @@ class AutoSleepTimerSettingsPage extends HookConsumerWidget { ), // auto turn on time settings, enabled only when autoTurnOnTimer is enabled SettingsTile.navigation( - enabled: sleepTimerSettings.autoTurnOnTimer, - title: const Text('Auto Turn On Time'), + enabled: enabled, + leading: const Icon(Symbols.timer_play), + title: const Text('From'), description: const Text( 'Turn on the sleep timer at the specified time', ), @@ -57,22 +64,24 @@ class AutoSleepTimerSettingsPage extends HookConsumerWidget { ); if (selected != null) { ref.read(appSettingsProvider.notifier).update( - appSettings.copyWith.playerSettings.sleepTimerSettings( + appSettings.copyWith.sleepTimerSettings( autoTurnOnTime: selected.toDuration(), ), ); } }, - value: Text( + trailing: Text( sleepTimerSettings.autoTurnOnTime.toTimeOfDay().format(context), + style: TextStyle(color: selectedValueColor), ), ), SettingsTile.navigation( - title: const Text('Auto Turn Off Time'), + enabled: enabled, + leading: const Icon(Symbols.timer_pause), + title: const Text('Until'), description: const Text( 'Turn off the sleep timer at the specified time', ), - enabled: sleepTimerSettings.autoTurnOnTimer, onPressed: (context) async { // navigate to the time picker final selected = await showTimePicker( @@ -81,18 +90,37 @@ class AutoSleepTimerSettingsPage extends HookConsumerWidget { ); if (selected != null) { ref.read(appSettingsProvider.notifier).update( - appSettings.copyWith.playerSettings.sleepTimerSettings( + appSettings.copyWith.sleepTimerSettings( autoTurnOffTime: selected.toDuration(), ), ); } }, - value: Text( + trailing: Text( sleepTimerSettings.autoTurnOffTime .toTimeOfDay() .format(context), + style: TextStyle(color: selectedValueColor), ), ), + + // switch tile for always auto turn on timer no matter what + SettingsTile.switchTile( + leading: const Icon(Symbols.all_inclusive), + title: const Text('Always Auto Turn On Timer'), + description: const Text( + 'Always turn on the sleep timer, no matter what', + ), + onToggle: (value) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.sleepTimerSettings( + alwaysAutoTurnOnTimer: value, + ), + ); + }, + enabled: sleepTimerSettings.autoTurnOnTimer, + initialValue: sleepTimerSettings.alwaysAutoTurnOnTimer, + ), ], ), ], diff --git a/lib/shared/extensions/duration_format.dart b/lib/shared/extensions/duration_format.dart index 09906cf..b492a37 100644 --- a/lib/shared/extensions/duration_format.dart +++ b/lib/shared/extensions/duration_format.dart @@ -9,14 +9,27 @@ extension DurationFormat on Duration { final minutes = inMinutes.remainder(60); final seconds = inSeconds.remainder(60); if (hours > 0) { - return '${hours}h ${minutes}m'; + // skip minutes if it's 0 + if (minutes == 0) { + return smartSingleFormat; + } + return '${Duration(hours: hours).smartBinaryFormat} ${Duration(minutes: minutes).smartSingleFormat}'; } else if (minutes > 0) { - return '${minutes}m ${seconds}s'; + if (seconds == 0) { + return smartSingleFormat; + } + return '${Duration(minutes: minutes).smartSingleFormat} ${Duration(seconds: seconds).smartSingleFormat}'; } else { - return '${seconds}s'; + return smartSingleFormat; } } + /// formats the duration using only 1 unit + /// if the duration is more than 1 hour, it will return `10h` + /// if the duration is less than 1 hour, it will return `30m` + /// if the duration is less than 1 minute, it will return `20s` + /// + /// rest of the duration will be ignored String get smartSingleFormat { if (inHours > 0) { return '${inHours}h'; diff --git a/lib/shared/extensions/time_of_day.dart b/lib/shared/extensions/time_of_day.dart index 702c5b6..9088b46 100644 --- a/lib/shared/extensions/time_of_day.dart +++ b/lib/shared/extensions/time_of_day.dart @@ -2,7 +2,10 @@ import 'package:flutter/material.dart'; extension ToTimeOfDay on Duration { TimeOfDay toTimeOfDay() { - return TimeOfDay(hour: inHours, minute: inMinutes % 60); + return TimeOfDay( + hour: inHours % 24, + minute: inMinutes % 60, + ); } } @@ -28,4 +31,16 @@ extension TimeOfDayExtension on TimeOfDay { bool isBefore(TimeOfDay other) => this < other; bool isAfter(TimeOfDay other) => this > other; + + bool isBetween(TimeOfDay start, TimeOfDay end) { + // needs more logic to handle the case where start is after end + //but on the other day + if (start == end) { + return this == start; + } + if (start < end) { + return this >= start && this <= end; + } + return this >= start || this <= end; + } } diff --git a/lib/shared/hooks.dart b/lib/shared/hooks.dart index 8e27b3a..62c6116 100644 --- a/lib/shared/hooks.dart +++ b/lib/shared/hooks.dart @@ -28,3 +28,64 @@ void useTimer(VoidCallback callback, Duration delay) { [delay], ); } + +/// Creates [FixedExtentScrollController] that will be disposed automatically. +/// +/// See also: +/// - [FixedExtentScrollController] +FixedExtentScrollController useFixedExtentScrollController({ + String? debugLabel, + List? keys, + int initialItem = 0, + void Function(ScrollPosition)? onAttach, + void Function(ScrollPosition)? onDetach, +}) { + return use( + _FixedExtentScrollControllerHook( + debugLabel: debugLabel, + keys: keys, + initialItem: initialItem, + onAttach: onAttach, + onDetach: onDetach, + ), + ); +} + +class _FixedExtentScrollControllerHook + extends Hook { + const _FixedExtentScrollControllerHook({ + this.debugLabel, + super.keys, + required this.initialItem, + this.onAttach, + this.onDetach, + }); + + final int initialItem; + final void Function(ScrollPosition)? onAttach; + final void Function(ScrollPosition)? onDetach; + + final String? debugLabel; + + @override + HookState> + createState() => _FixedExtentScrollControllerHookState(); +} + +class _FixedExtentScrollControllerHookState extends HookState< + FixedExtentScrollController, _FixedExtentScrollControllerHook> { + late final controller = FixedExtentScrollController( + initialItem: hook.initialItem, + onAttach: hook.onAttach, + onDetach: hook.onDetach, + ); + + @override + FixedExtentScrollController build(BuildContext context) => controller; + + @override + void dispose() => controller.dispose(); + + @override + String get debugLabel => 'useFixedExtentScrollController'; +} diff --git a/pubspec.lock b/pubspec.lock index 0436fc6..e675e19 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -814,6 +814,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.11.1" + material_symbols_icons: + dependency: "direct main" + description: + name: material_symbols_icons + sha256: "66416c4e30bd363508e12669634fc4f3250b83b69e862de67f4f9c480cf42414" + url: "https://pub.dev" + source: hosted + version: "4.2785.1" media_kit: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 123f6f7..aaab763 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -70,6 +70,7 @@ dependencies: list_wheel_scroll_view_nls: ^0.0.3 logging: ^1.2.0 lottie: ^3.1.0 + material_symbols_icons: ^4.2785.1 media_kit_libs_linux: any media_kit_libs_windows_audio: any miniplayer: From be5eb3fd13e896f08696f24c35e1738459871e26 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Wed, 2 Oct 2024 09:32:05 -0400 Subject: [PATCH 33/92] test: add TimeOfDay extension tests and enable test execution in CI --- .github/workflows/flutter_test.yaml | 4 +- test/shared/extensions/time_of_day_test.dart | 136 +++++++++++++++++++ 2 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 test/shared/extensions/time_of_day_test.dart diff --git a/.github/workflows/flutter_test.yaml b/.github/workflows/flutter_test.yaml index 245a489..56b3947 100644 --- a/.github/workflows/flutter_test.yaml +++ b/.github/workflows/flutter_test.yaml @@ -40,8 +40,8 @@ jobs: - name: Install dependencies run: flutter pub get - # - name: Run tests - # run: flutter test + - name: Run tests + run: flutter test - name: Build APK run: flutter build apk --release diff --git a/test/shared/extensions/time_of_day_test.dart b/test/shared/extensions/time_of_day_test.dart new file mode 100644 index 0000000..131ba6d --- /dev/null +++ b/test/shared/extensions/time_of_day_test.dart @@ -0,0 +1,136 @@ +// ignore_for_file: constant_identifier_names + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:vaani/shared/extensions/time_of_day.dart'; + +const TIME_08_30_AM = TimeOfDay(hour: 8, minute: 30); +const TIME_09_00_AM = TimeOfDay(hour: 9, minute: 0); +const TIME_10_30_AM = TimeOfDay(hour: 10, minute: 30); +const TIME_11_00_AM = TimeOfDay(hour: 11, minute: 0); +const TIME_12_00_PM = TimeOfDay(hour: 12, minute: 0); +const TIME_10_00_PM = TimeOfDay(hour: 22, minute: 0); +void main() { + group('ToTimeOfDay extension', () { + test('Duration to TimeOfDay conversion', () { + final duration = Duration(hours: 10, minutes: 30); + expect(duration.toTimeOfDay(), TIME_10_30_AM); + }); + + test('Duration to TimeOfDay conversion with more than 24 hours', () { + final duration = Duration(hours: 32, minutes: 30); + expect(duration.toTimeOfDay(), TIME_08_30_AM); + }); + }); + + group('ToDuration extension', () { + test('TimeOfDay to Duration conversion', () { + final duration = TIME_10_30_AM.toDuration(); + expect(duration.inHours, 10); + expect(duration.inMinutes % 60, 30); + }); + }); + + group('Compare TimeOfDay', () { + test('compareTo method', () { + expect(TIME_10_30_AM.compareTo(TIME_12_00_PM), -1); + expect(TIME_12_00_PM.compareTo(TIME_10_30_AM), 1); + expect(TIME_10_30_AM.compareTo(TIME_10_30_AM), 0); + }); + + test('operator <', () { + expect(TIME_10_30_AM < TIME_12_00_PM, true); + expect(TIME_12_00_PM < TIME_10_30_AM, false); + }); + + test('operator >', () { + expect(TIME_10_30_AM > TIME_10_00_PM, false); + expect(TIME_10_00_PM > TIME_10_30_AM, true); + }); + + test('operator <=', () { + expect(TIME_10_30_AM <= TIME_12_00_PM, true); + expect(TIME_12_00_PM <= TIME_10_30_AM, false); + expect(TIME_10_30_AM <= TIME_10_30_AM, true); + }); + + test('operator >=', () { + expect(TIME_10_30_AM >= TIME_10_00_PM, false); + expect(TIME_10_00_PM >= TIME_10_30_AM, true); + expect(TIME_10_30_AM >= TIME_10_30_AM, true); + }); + }); + + group('isBetween method', () { + void testIsBetween( + TimeOfDay time, + TimeOfDay start, + TimeOfDay end, + bool expectedResult, + ) { + test('TimeOfDay $time is between $start and $end', () { + expect(time.isBetween(start, end), expectedResult); + }); + } + + final testCases = [ + ( + time: TIME_10_30_AM, + start: TIME_09_00_AM, + end: TIME_11_00_AM, + expectedResult: true + ), + ( + time: TIME_08_30_AM, + start: TIME_09_00_AM, + end: TIME_11_00_AM, + expectedResult: false + ), + ( + time: TIME_10_30_AM, + start: TIME_11_00_AM, + end: TIME_09_00_AM, + expectedResult: false + ), + ( + time: TIME_08_30_AM, + start: TIME_10_00_PM, + end: TIME_09_00_AM, + expectedResult: true + ), + ( + time: TIME_12_00_PM, + start: TIME_11_00_AM, + end: TIME_09_00_AM, + expectedResult: true + ), + ( + time: TIME_10_00_PM, + start: TIME_11_00_AM, + end: TIME_09_00_AM, + expectedResult: true + ), + ( + time: TIME_09_00_AM, + start: TIME_09_00_AM, + end: TIME_09_00_AM, + expectedResult: true + ), + ( + time: TIME_10_00_PM, + start: TIME_09_00_AM, + end: TIME_09_00_AM, + expectedResult: false + ), + ]; + + for (var testCase in testCases) { + testIsBetween( + testCase.time, + testCase.start, + testCase.end, + testCase.expectedResult, + ); + } + }); +} From 02b6194d8f15cf2e419d3c0d54db9489bb06fbad Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Wed, 2 Oct 2024 09:33:12 -0400 Subject: [PATCH 34/92] ci: reorder Java setup in CI workflow for improved efficiency in case of test failure --- .github/workflows/flutter_test.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/flutter_test.yaml b/.github/workflows/flutter_test.yaml index 56b3947..9c74813 100644 --- a/.github/workflows/flutter_test.yaml +++ b/.github/workflows/flutter_test.yaml @@ -26,12 +26,6 @@ jobs: repository: Dr-Blank/shelfsdk path: ./shelfsdk - - name: Set Up Java - uses: actions/setup-java@v3.12.0 - with: - distribution: "oracle" - java-version: "17" - - name: Set up Flutter uses: subosito/flutter-action@v2 with: @@ -43,6 +37,12 @@ jobs: - name: Run tests run: flutter test + - name: Set Up Java + uses: actions/setup-java@v3.12.0 + with: + distribution: "oracle" + java-version: "17" + - name: Build APK run: flutter build apk --release From 7b0c2c4b889cde93a2dca856b4f35784eb75de19 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Wed, 2 Oct 2024 09:35:46 -0400 Subject: [PATCH 35/92] chore: bump version to 0.0.10+1 in pubspec.yaml --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index aaab763..fc1bfdb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.0.9+1 +version: 0.0.10+1 environment: sdk: ">=3.3.4 <4.0.0" From 35a2d7cfce0e9b604f411ef3694026a433cd9453 Mon Sep 17 00:00:00 2001 From: "Dr.Blank" Date: Thu, 3 Oct 2024 05:54:29 -0400 Subject: [PATCH 36/92] feat: error reporting with logs (#45) * feat: add ability to get logs file from ui * test: add unit test for log line parsing in logs_provider * refactor: update all logs to obfuscate sensitive information * feat: generate dynamic zip file name for logs export * feat: enhance logging in audiobook player and provider for better debugging * refactor: extract user display logic into UserBar widget for offline access of settings and logs * feat: add About section with app metadata and source code link in YouPage --- assets/images/vaani_logo_foreground.png | Bin 0 -> 3869 bytes lib/api/api_provider.dart | 4 +- lib/api/api_provider.g.dart | 2 +- lib/api/authenticated_user_provider.dart | 10 +- lib/api/authenticated_user_provider.g.dart | 2 +- lib/api/server_provider.dart | 18 +- lib/api/server_provider.g.dart | 2 +- lib/db/init.dart | 12 +- .../downloads/core/download_manager.dart | 5 +- .../downloads/providers/download_manager.dart | 4 + .../providers/download_manager.g.dart | 4 +- .../view/library_item_actions.dart | 10 +- .../view/library_item_hero_section.dart | 2 +- lib/features/logging/core/logger.dart | 36 +++ .../logging/providers/logs_provider.dart | 76 +++++ .../logging/providers/logs_provider.g.dart | 25 ++ lib/features/logging/view/logs_page.dart | 266 ++++++++++++++++++ .../view/user_login_with_open_id.dart | 5 +- .../core/playback_reporter.dart | 6 +- .../player/core/audiobook_player.dart | 45 +-- .../player/providers/audiobook_player.dart | 27 +- .../player/providers/audiobook_player.g.dart | 4 +- .../providers/currently_playing_provider.dart | 4 + .../currently_playing_provider.g.dart | 2 +- .../widgets/chapter_selection_button.dart | 3 +- .../sleep_timer/core/sleep_timer.dart | 8 +- lib/features/you/view/server_manager.dart | 6 +- lib/features/you/view/you_page.dart | 178 +++++++----- lib/main.dart | 11 +- lib/models/error_response.dart | 3 +- lib/pages/home_page.dart | 3 +- lib/pages/library_page.dart | 3 +- lib/router/constants.dart | 6 + lib/router/router.dart | 12 +- lib/router/scaffold_with_nav_bar.dart | 18 +- lib/settings/api_settings_provider.dart | 6 +- lib/settings/api_settings_provider.g.dart | 2 +- lib/settings/constants.dart | 5 + lib/shared/extensions/obfuscation.dart | 125 ++++++++ pubspec.lock | 44 ++- pubspec.yaml | 5 + .../logging/providers/logs_provider_test.dart | 24 ++ .../flutter/generated_plugin_registrant.cc | 3 + windows/flutter/generated_plugins.cmake | 1 + 44 files changed, 861 insertions(+), 176 deletions(-) create mode 100644 assets/images/vaani_logo_foreground.png create mode 100644 lib/features/logging/core/logger.dart create mode 100644 lib/features/logging/providers/logs_provider.dart create mode 100644 lib/features/logging/providers/logs_provider.g.dart create mode 100644 lib/features/logging/view/logs_page.dart create mode 100644 lib/shared/extensions/obfuscation.dart create mode 100644 test/features/logging/providers/logs_provider_test.dart diff --git a/assets/images/vaani_logo_foreground.png b/assets/images/vaani_logo_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..cb8014fdd92400fcd32a8791e6d07d7bbdd4d448 GIT binary patch literal 3869 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 literal 0 HcmV?d00001 diff --git a/lib/api/api_provider.dart b/lib/api/api_provider.dart index daffff8..1d3745f 100644 --- a/lib/api/api_provider.dart +++ b/lib/api/api_provider.dart @@ -8,6 +8,7 @@ import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:shelfsdk/audiobookshelf_api.dart'; import 'package:vaani/db/cache_manager.dart'; import 'package:vaani/settings/api_settings_provider.dart'; +import 'package:vaani/shared/extensions/obfuscation.dart'; part 'api_provider.g.dart'; @@ -80,7 +81,7 @@ FutureOr serverStatus( Uri baseUrl, [ ResponseErrorHandler? responseErrorHandler, ]) async { - _logger.fine('fetching server status: $baseUrl'); + _logger.fine('fetching server status: ${baseUrl.obfuscate()}'); final api = ref.watch(audiobookshelfApiProvider(baseUrl)); final res = await api.server.status(responseErrorHandler: responseErrorHandler); @@ -145,7 +146,6 @@ class PersonalizedView extends _$PersonalizedView { _logger.warning('failed to fetch personalized view'); yield []; } - } // method to force refresh the view and ignore the cache diff --git a/lib/api/api_provider.g.dart b/lib/api/api_provider.g.dart index 67e86e2..7758c7b 100644 --- a/lib/api/api_provider.g.dart +++ b/lib/api/api_provider.g.dart @@ -327,7 +327,7 @@ class _IsServerAliveProviderElement String get address => (origin as IsServerAliveProvider).address; } -String _$serverStatusHash() => r'2739906a1862d09b098588ebd16749a09032ee99'; +String _$serverStatusHash() => r'd7079e19e68f5f61b0afa0f73a2af8807c4b3cf6'; /// fetch status of server /// diff --git a/lib/api/authenticated_user_provider.dart b/lib/api/authenticated_user_provider.dart index c10f799..c4f065c 100644 --- a/lib/api/authenticated_user_provider.dart +++ b/lib/api/authenticated_user_provider.dart @@ -5,8 +5,8 @@ import 'package:vaani/api/server_provider.dart' import 'package:vaani/db/storage.dart'; import 'package:vaani/settings/api_settings_provider.dart'; import 'package:vaani/settings/models/audiobookshelf_server.dart'; -import 'package:vaani/settings/models/authenticated_user.dart' - as model; +import 'package:vaani/settings/models/authenticated_user.dart' as model; +import 'package:vaani/shared/extensions/obfuscation.dart'; part 'authenticated_user_provider.g.dart'; @@ -35,7 +35,9 @@ class AuthenticatedUser extends _$AuthenticatedUser { Set readFromBoxOrCreate() { if (_box.isNotEmpty) { final foundData = _box.getRange(0, _box.length); - _logger.fine('found users in box: $foundData'); + _logger.fine( + 'found users in box: ${foundData.obfuscate()}', + ); return foundData.toSet(); } else { _logger.fine('no settings found in box'); @@ -49,7 +51,7 @@ class AuthenticatedUser extends _$AuthenticatedUser { return; } _box.addAll(state); - _logger.fine('writing state to box: $state'); + _logger.fine('writing state to box: ${state.obfuscate()}'); } void addUser(model.AuthenticatedUser user, {bool setActive = false}) { diff --git a/lib/api/authenticated_user_provider.g.dart b/lib/api/authenticated_user_provider.g.dart index 7fca094..65f7c32 100644 --- a/lib/api/authenticated_user_provider.g.dart +++ b/lib/api/authenticated_user_provider.g.dart @@ -6,7 +6,7 @@ part of 'authenticated_user_provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$authenticatedUserHash() => r'308f19b33ae04af6340fb83167fa64aa23400a09'; +String _$authenticatedUserHash() => r'1983527595207c63a12bc84cf0bf1a3c1d729506'; /// provides with a set of authenticated users /// diff --git a/lib/api/server_provider.dart b/lib/api/server_provider.dart index 4ad4b1e..f4d8a21 100644 --- a/lib/api/server_provider.dart +++ b/lib/api/server_provider.dart @@ -1,16 +1,18 @@ import 'package:collection/collection.dart'; -import 'package:flutter/material.dart'; +import 'package:logging/logging.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:vaani/api/authenticated_user_provider.dart'; import 'package:vaani/db/storage.dart'; import 'package:vaani/settings/api_settings_provider.dart'; -import 'package:vaani/settings/models/audiobookshelf_server.dart' - as model; +import 'package:vaani/settings/models/audiobookshelf_server.dart' as model; +import 'package:vaani/shared/extensions/obfuscation.dart'; part 'server_provider.g.dart'; final _box = AvailableHiveBoxes.serverBox; +final _logger = Logger('AudiobookShelfServerProvider'); + class ServerAlreadyExistsException implements Exception { final model.AudiobookShelfServer server; @@ -47,10 +49,10 @@ class AudiobookShelfServer extends _$AudiobookShelfServer { Set readFromBoxOrCreate() { if (_box.isNotEmpty) { final foundServers = _box.getRange(0, _box.length); - debugPrint('found servers in box: $foundServers'); + _logger.info('found servers in box: ${foundServers.obfuscate()}'); return foundServers.whereNotNull().toSet(); } else { - debugPrint('no settings found in box'); + _logger.info('no settings found in box'); return {}; } } @@ -61,7 +63,7 @@ class AudiobookShelfServer extends _$AudiobookShelfServer { return; } _box.addAll(state); - debugPrint('writing state to box: $state'); + _logger.info('writing state to box: ${state.obfuscate()}'); } void addServer(model.AudiobookShelfServer server) { @@ -71,8 +73,8 @@ class AudiobookShelfServer extends _$AudiobookShelfServer { state = {...state, server}; } - void removeServer(model.AudiobookShelfServer server, - { + void removeServer( + model.AudiobookShelfServer server, { bool removeUsers = false, }) { state = state.where((s) => s != server).toSet(); diff --git a/lib/api/server_provider.g.dart b/lib/api/server_provider.g.dart index 69478cc..7ff40c2 100644 --- a/lib/api/server_provider.g.dart +++ b/lib/api/server_provider.g.dart @@ -7,7 +7,7 @@ part of 'server_provider.dart'; // ************************************************************************** String _$audiobookShelfServerHash() => - r'f0d645bb42233c59886bc43fdc473897484ceca1'; + r'0084fb72c4c54323207928b95716cfd9ca496c11'; /// provides with a set of servers added by the user /// diff --git a/lib/db/init.dart b/lib/db/init.dart index ad875db..8b5e7d0 100644 --- a/lib/db/init.dart +++ b/lib/db/init.dart @@ -1,28 +1,28 @@ -// does the initial setup of the storage - import 'dart:io'; -import 'package:flutter/material.dart'; import 'package:hive/hive.dart'; import 'package:path/path.dart' as p; import 'package:path_provider/path_provider.dart'; +import 'package:vaani/main.dart'; import 'package:vaani/settings/constants.dart'; import 'register_models.dart'; +// does the initial setup of the storage Future initStorage() async { final dir = await getApplicationDocumentsDirectory(); // use vaani as the directory for hive - final storageDir = Directory(p.join( - dir.path, + final storageDir = Directory( + p.join( + dir.path, AppMetadata.appNameLowerCase, ), ); await storageDir.create(recursive: true); Hive.defaultDirectory = storageDir.path; - debugPrint('Hive storage directory init: ${Hive.defaultDirectory}'); + appLogger.config('Hive storage directory init: ${Hive.defaultDirectory}'); await registerModels(); } diff --git a/lib/features/downloads/core/download_manager.dart b/lib/features/downloads/core/download_manager.dart index 5b6229d..0e808b1 100644 --- a/lib/features/downloads/core/download_manager.dart +++ b/lib/features/downloads/core/download_manager.dart @@ -8,6 +8,7 @@ import 'package:logging/logging.dart'; import 'package:path_provider/path_provider.dart'; import 'package:shelfsdk/audiobookshelf_api.dart'; import 'package:vaani/shared/extensions/model_conversions.dart'; +import 'package:vaani/shared/extensions/obfuscation.dart'; final _logger = Logger('AudiobookDownloadManager'); final tq = MemoryTaskQueue(); @@ -35,7 +36,9 @@ class AudiobookDownloadManager { FileDownloader().addTaskQueue(tq); - _logger.fine('initialized with baseUrl: $baseUrl, token: $token'); + _logger.fine( + 'initialized with baseUrl: ${Uri.parse(baseUrl).obfuscate()} and token: ${token.obfuscate()}', + ); _logger.fine( 'requiresWiFi: $requiresWiFi, retries: $retries, allowPause: $allowPause', ); diff --git a/lib/features/downloads/providers/download_manager.dart b/lib/features/downloads/providers/download_manager.dart index 87a2191..9f56129 100644 --- a/lib/features/downloads/providers/download_manager.dart +++ b/lib/features/downloads/providers/download_manager.dart @@ -31,9 +31,11 @@ class SimpleDownloadManager extends _$SimpleDownloadManager { core.tq.maxConcurrentByGroup = downloadSettings.maxConcurrentByGroup; ref.onDispose(() { + _logger.info('disposing download manager'); manager.dispose(); }); + _logger.config('initialized download manager'); return manager; } } @@ -52,12 +54,14 @@ class DownloadManager extends _$DownloadManager { Future queueAudioBookDownload( LibraryItemExpanded item, ) async { + _logger.fine('queueing download for ${item.id}'); await state.queueAudioBookDownload( item, ); } Future deleteDownloadedItem(LibraryItemExpanded item) async { + _logger.fine('deleting downloaded item ${item.id}'); await state.deleteDownloadedItem(item); ref.notifyListeners(); } diff --git a/lib/features/downloads/providers/download_manager.g.dart b/lib/features/downloads/providers/download_manager.g.dart index 43fc01c..47cbf4d 100644 --- a/lib/features/downloads/providers/download_manager.g.dart +++ b/lib/features/downloads/providers/download_manager.g.dart @@ -158,7 +158,7 @@ class _DownloadHistoryProviderElement } String _$simpleDownloadManagerHash() => - r'cec95717c86e422f88f78aa014d29e800e5a2089'; + r'8ab13f06ec5f2f73b73064bd285813dc890b7f36'; /// See also [SimpleDownloadManager]. @ProviderFor(SimpleDownloadManager) @@ -174,7 +174,7 @@ final simpleDownloadManagerProvider = NotifierProvider; -String _$downloadManagerHash() => r'7296a39439230f77abbe7d3231dae748f09c7ecf'; +String _$downloadManagerHash() => r'852012e32e613f86445afc7f7e4e85bec808e982'; /// See also [DownloadManager]. @ProviderFor(DownloadManager) diff --git a/lib/features/item_viewer/view/library_item_actions.dart b/lib/features/item_viewer/view/library_item_actions.dart index f1eec3d..1b1b5a8 100644 --- a/lib/features/item_viewer/view/library_item_actions.dart +++ b/lib/features/item_viewer/view/library_item_actions.dart @@ -518,7 +518,7 @@ Future libraryItemPlayButtonOnPressed({ required shelfsdk.BookExpanded book, shelfsdk.MediaProgress? userMediaProgress, }) async { - debugPrint('Pressed play/resume button'); + appLogger.info('Pressed play/resume button'); final player = ref.watch(audiobookPlayerProvider); final isCurrentBookSetInPlayer = player.book == book; @@ -527,8 +527,8 @@ Future libraryItemPlayButtonOnPressed({ Future? setSourceFuture; // set the book to the player if not already set if (!isCurrentBookSetInPlayer) { - debugPrint('Setting the book ${book.libraryItemId}'); - debugPrint('Initial position: ${userMediaProgress?.currentTime}'); + appLogger.info('Setting the book ${book.libraryItemId}'); + appLogger.info('Initial position: ${userMediaProgress?.currentTime}'); final downloadManager = ref.watch(simpleDownloadManagerProvider); final libItem = await ref.read(libraryItemProvider(book.libraryItemId).future); @@ -539,9 +539,9 @@ Future libraryItemPlayButtonOnPressed({ downloadedUris: downloadedUris, ); } else { - debugPrint('Book was already set'); + appLogger.info('Book was already set'); if (isPlayingThisBook) { - debugPrint('Pausing the book'); + appLogger.info('Pausing the book'); await player.pause(); return; } diff --git a/lib/features/item_viewer/view/library_item_hero_section.dart b/lib/features/item_viewer/view/library_item_hero_section.dart index ea21da6..83b5555 100644 --- a/lib/features/item_viewer/view/library_item_hero_section.dart +++ b/lib/features/item_viewer/view/library_item_hero_section.dart @@ -383,7 +383,7 @@ class _BookCover extends HookConsumerWidget { : themeData, ); } catch (e) { - appLogger.shout('Error changing theme: $e'); + appLogger.severe('Error changing theme: $e'); } }); } diff --git a/lib/features/logging/core/logger.dart b/lib/features/logging/core/logger.dart new file mode 100644 index 0000000..52eb099 --- /dev/null +++ b/lib/features/logging/core/logger.dart @@ -0,0 +1,36 @@ +import 'dart:io'; + +import 'package:flutter/foundation.dart'; +import 'package:logging/logging.dart'; +import 'package:logging_appenders/logging_appenders.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:vaani/shared/extensions/duration_format.dart'; + +Future getLoggingFilePath() async { + final Directory directory = await getApplicationDocumentsDirectory(); + return '${directory.path}/vaani.log'; +} + +Future initLogging() async { + final formatter = const DefaultLogRecordFormatter(); + if (kReleaseMode) { + Logger.root.level = Level.INFO; // is also the default + // Write to a file + RotatingFileAppender( + baseFilePath: await getLoggingFilePath(), + formatter: formatter, + ).attachToLogger(Logger.root); + } else { + Logger.root.level = Level.FINE; // Capture all logs + RotatingFileAppender( + baseFilePath: await getLoggingFilePath(), + formatter: formatter, + ).attachToLogger(Logger.root); + Logger.root.onRecord.listen((record) { + // Print log records to the console + debugPrint( + '${record.loggerName}: ${record.level.name}: ${record.time.time}: ${record.message}', + ); + }); + } +} diff --git a/lib/features/logging/providers/logs_provider.dart b/lib/features/logging/providers/logs_provider.dart new file mode 100644 index 0000000..ecdc0b6 --- /dev/null +++ b/lib/features/logging/providers/logs_provider.dart @@ -0,0 +1,76 @@ +import 'dart:io'; + +import 'package:archive/archive_io.dart'; +import 'package:logging/logging.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:vaani/features/logging/core/logger.dart'; + +part 'logs_provider.g.dart'; + +@riverpod +class Logs extends _$Logs { + @override + Future> build() async { + final path = await getLoggingFilePath(); + final file = File(path); + if (!file.existsSync()) { + return []; + } + final lines = await file.readAsLines(); + return lines.map(parseLogLine).toList(); + } + + Future clear() async { + final path = await getLoggingFilePath(); + final file = File(path); + await file.writeAsString(''); + state = AsyncData([]); + } + + Future getZipFilePath() async { + var encoder = ZipFileEncoder(); + encoder.create(await generateZipFilePath()); + encoder.addFile(File(await getLoggingFilePath())); + encoder.close(); + return encoder.zipPath; + } +} + +Future generateZipFilePath() async { + Directory appDocDirectory = await getTemporaryDirectory(); + return '${appDocDirectory.path}/${generateZipFileName()}'; +} + +String generateZipFileName() { + return 'vaani-${DateTime.now().toIso8601String()}.zip'; +} + +Level parseLevel(String level) { + return Level.LEVELS + .firstWhere((l) => l.name == level, orElse: () => Level.ALL); +} + +LogRecord parseLogLine(String line) { + // 2024-10-03 00:48:58.012400 INFO GoRouter - getting location for name: "logs" + + final RegExp logLineRegExp = RegExp( + r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{6}) (\w+) (\w+) - (.+)', + ); + + final match = logLineRegExp.firstMatch(line); + if (match == null) { + // return as is + return LogRecord(Level.ALL, line, 'Unknown'); + } + + final timeString = match.group(1)!; + final levelString = match.group(2)!; + final loggerName = match.group(3)!; + final message = match.group(4)!; + + final time = DateTime.parse(timeString); + final level = parseLevel(levelString); + + return LogRecord(level, message, loggerName, time); +} diff --git a/lib/features/logging/providers/logs_provider.g.dart b/lib/features/logging/providers/logs_provider.g.dart new file mode 100644 index 0000000..094893e --- /dev/null +++ b/lib/features/logging/providers/logs_provider.g.dart @@ -0,0 +1,25 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'logs_provider.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$logsHash() => r'901376741d17ddbb889d1b7b96bc2882289720a0'; + +/// See also [Logs]. +@ProviderFor(Logs) +final logsProvider = + AutoDisposeAsyncNotifierProvider>.internal( + Logs.new, + name: r'logsProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') ? null : _$logsHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$Logs = AutoDisposeAsyncNotifier>; +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/features/logging/view/logs_page.dart b/lib/features/logging/view/logs_page.dart new file mode 100644 index 0000000..f5ee104 --- /dev/null +++ b/lib/features/logging/view/logs_page.dart @@ -0,0 +1,266 @@ +import 'dart:io'; + +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:logging/logging.dart'; +import 'package:share_plus/share_plus.dart'; +import 'package:vaani/features/logging/providers/logs_provider.dart'; +import 'package:vaani/main.dart'; + +class LogsPage extends HookConsumerWidget { + const LogsPage({super.key}); + @override + Widget build(BuildContext context, WidgetRef ref) { + final logs = ref.watch(logsProvider); + final theme = Theme.of(context); + final scrollController = useScrollController(); + return Scaffold( + appBar: AppBar( + title: const Text('Logs'), + actions: [ + IconButton( + tooltip: 'Clear logs', + icon: const Icon(Icons.delete_forever), + onPressed: () async { + // ask for confirmation + final shouldClear = await showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: const Text('Clear logs?'), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(false); + }, + child: const Text('Cancel'), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(true); + }, + child: const Text('Clear'), + ), + ], + ); + }, + ); + if (shouldClear == true) { + ref.read(logsProvider.notifier).clear(); + } + }, + ), + IconButton( + tooltip: 'Share logs', + icon: const Icon(Icons.share), + onPressed: () async { + appLogger.info('Preparing logs for sharing'); + final zipLogFilePath = + await ref.read(logsProvider.notifier).getZipFilePath(); + + // submit logs + final result = await Share.shareXFiles([XFile(zipLogFilePath)]); + + switch (result.status) { + case ShareResultStatus.success: + appLogger.info('Share success'); + break; + case ShareResultStatus.dismissed: + appLogger.info('Share dismissed'); + break; + case ShareResultStatus.unavailable: + appLogger.severe('Share unavailable'); + break; + } + }, + ), + IconButton( + tooltip: 'Download logs', + icon: const Icon(Icons.download), + onPressed: () async { + appLogger.info('Preparing logs for download'); + final zipLogFilePath = + await ref.read(logsProvider.notifier).getZipFilePath(); + + // save to folder + String? outputFile = await FilePicker.platform.saveFile( + dialogTitle: 'Please select an output file:', + fileName: zipLogFilePath.split('/').last, + ); + if (outputFile != null) { + try { + final file = File(outputFile); + final zipFile = File(zipLogFilePath); + await zipFile.copy(file.path); + } catch (e) { + appLogger.severe('Error saving file: $e'); + } + } else { + appLogger.info('Download cancelled'); + } + }, + ), + IconButton( + tooltip: 'Refresh logs', + icon: const Icon(Icons.refresh), + onPressed: () { + ref.invalidate(logsProvider); + }, + ), + IconButton( + tooltip: 'Scroll to top', + icon: const Icon(Icons.arrow_upward), + onPressed: () { + scrollController.animateTo( + 0, + duration: const Duration(milliseconds: 500), + curve: Curves.easeInOut, + ); + }, + ), + ], + ), + // a column with listview.builder and a scrollable list of logs + body: Column( + children: [ + // a filter for log levels, loggers, and search + // TODO: implement filters and search + + Expanded( + child: logs.when( + data: (logRecords) { + return Scrollbar( + controller: scrollController, + child: ListView.builder( + controller: scrollController, + itemCount: logRecords.length, + itemBuilder: (context, index) { + final logRecord = logRecords[index]; + return LogRecordTile(logRecord: logRecord, theme: theme); + }, + ), + ); + }, + loading: () => const Center(child: CircularProgressIndicator()), + error: (error, stackTrace) => Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text('Error loading logs'), + ElevatedButton( + onPressed: () { + ref.invalidate(logsProvider); + }, + child: const Text('Retry'), + ), + ], + ), + ), + ), + ), + ], + ), + ); + } +} + +class LogRecordTile extends StatelessWidget { + final LogRecord logRecord; + final ThemeData theme; + const LogRecordTile({ + required this.logRecord, + required this.theme, + super.key, + }); + @override + Widget build(BuildContext context) { + return ListTile( + leading: CircleAvatar( + backgroundColor: getLogLevelColor(logRecord.level, theme), + child: Icon( + getLogLevelIcon(logRecord.level), + color: getLogLevelTextColor(logRecord.level, theme), + ), + ), + title: Text(logRecord.loggerName), + subtitle: Text(logRecord.message), + onTap: () { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + icon: Icon(getLogLevelIcon(logRecord.level)), + title: Text(logRecord.loggerName), + content: Text.rich( + TextSpan( + children: [ + TextSpan( + text: logRecord.time.toIso8601String(), + style: const TextStyle(fontStyle: FontStyle.italic), + ), + const TextSpan(text: '\n\n'), + TextSpan( + text: logRecord.message, + ), + ], + ), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text('Close'), + ), + ], + ); + }, + ); + }, + ); + } +} + +IconData getLogLevelIcon(Level level) { + switch (level) { + case Level.INFO: + return (Icons.info); + case Level.WARNING: + return (Icons.warning); + case Level.SEVERE: + case Level.SHOUT: + return (Icons.error); + default: + return (Icons.bug_report); + } +} + +Color? getLogLevelColor(Level level, ThemeData theme) { + switch (level) { + case Level.INFO: + return theme.colorScheme.surfaceContainerLow; + case Level.WARNING: + return theme.colorScheme.surfaceBright; + case Level.SEVERE: + case Level.SHOUT: + return theme.colorScheme.errorContainer; + default: + return theme.colorScheme.primaryContainer; + } +} + +Color? getLogLevelTextColor(Level level, ThemeData theme) { + switch (level) { + case Level.INFO: + return theme.colorScheme.onSurface; + case Level.WARNING: + return theme.colorScheme.onSurface; + case Level.SEVERE: + case Level.SHOUT: + return theme.colorScheme.onErrorContainer; + default: + return theme.colorScheme.onPrimaryContainer; + } +} diff --git a/lib/features/onboarding/view/user_login_with_open_id.dart b/lib/features/onboarding/view/user_login_with_open_id.dart index e403c81..71baa42 100644 --- a/lib/features/onboarding/view/user_login_with_open_id.dart +++ b/lib/features/onboarding/view/user_login_with_open_id.dart @@ -11,6 +11,7 @@ import 'package:vaani/models/error_response.dart'; import 'package:vaani/router/router.dart'; import 'package:vaani/settings/constants.dart'; import 'package:vaani/settings/models/models.dart' as model; +import 'package:vaani/shared/extensions/obfuscation.dart'; import 'package:vaani/shared/utils.dart'; class UserLoginWithOpenID extends HookConsumerWidget { @@ -89,7 +90,9 @@ class UserLoginWithOpenID extends HookConsumerWidget { return; } - appLogger.fine('Got OpenID login endpoint: $openIDLoginEndpoint'); + appLogger.fine( + 'Got OpenID login endpoint: ${openIDLoginEndpoint.obfuscate()}', + ); // add the flow to the provider ref.read(oauthFlowsProvider.notifier).addFlow( diff --git a/lib/features/playback_reporting/core/playback_reporter.dart b/lib/features/playback_reporting/core/playback_reporter.dart index faffb4d..b2be336 100644 --- a/lib/features/playback_reporting/core/playback_reporter.dart +++ b/lib/features/playback_reporting/core/playback_reporter.dart @@ -1,8 +1,10 @@ import 'dart:async'; +import 'package:http/http.dart' as http; import 'package:logging/logging.dart'; import 'package:shelfsdk/audiobookshelf_api.dart'; import 'package:vaani/features/player/core/audiobook_player.dart'; +import 'package:vaani/shared/extensions/obfuscation.dart'; final _logger = Logger('PlaybackReporter'); @@ -255,9 +257,9 @@ class PlaybackReporter { _logger.fine('cancelled timer'); } - void _responseErrorHandler(response, [error]) { + void _responseErrorHandler(http.Response response, [error]) { if (response.statusCode != 200) { - _logger.shout('Error with api: $response, $error'); + _logger.severe('Error with api: ${response.obfuscate()}, $error'); throw PlaybackSyncError( 'Error syncing position: ${response.body}, $error', ); diff --git a/lib/features/player/core/audiobook_player.dart b/lib/features/player/core/audiobook_player.dart index 726e91d..87247fe 100644 --- a/lib/features/player/core/audiobook_player.dart +++ b/lib/features/player/core/audiobook_player.dart @@ -11,38 +11,38 @@ import 'package:shelfsdk/audiobookshelf_api.dart'; import 'package:vaani/settings/app_settings_provider.dart'; import 'package:vaani/settings/models/app_settings.dart'; import 'package:vaani/shared/extensions/model_conversions.dart'; +import 'package:vaani/shared/extensions/obfuscation.dart'; final _logger = Logger('AudiobookPlayer'); /// returns the sum of the duration of all the previous tracks before the [index] Duration sumOfTracks(BookExpanded book, int? index) { + _logger.fine('Calculating sum of tracks for index: $index'); // return 0 if index is less than 0 if (index == null || index < 0) { + _logger.warning('Index is null or less than 0, returning 0'); return Duration.zero; } - return book.tracks.sublist(0, index).fold(Duration.zero, - (previousValue, element) { - return previousValue + element.duration; - }); + final total = book.tracks.sublist(0, index).fold( + Duration.zero, + (previousValue, element) => previousValue + element.duration, + ); + _logger.fine('Sum of tracks for index: $index is $total'); + return total; } /// returns the [AudioTrack] to play based on the [position] in the [book] AudioTrack getTrackToPlay(BookExpanded book, Duration position) { - // var totalDuration = Duration.zero; - // for (var track in book.tracks) { - // totalDuration += track.duration; - // if (totalDuration >= position) { - // return track; - // } - // } - // return book.tracks.last; - return book.tracks.firstWhere( + _logger.fine('Getting track to play for position: $position'); + final track = book.tracks.firstWhere( (element) { return element.startOffset <= position && (element.startOffset + element.duration) >= position; }, orElse: () => book.tracks.last, ); + _logger.fine('Track to play for position: $position is $track'); + return track; } /// will manage the audio player instance @@ -50,6 +50,7 @@ class AudiobookPlayer extends AudioPlayer { // constructor which takes in the BookExpanded object AudiobookPlayer(this.token, this.baseUrl) : super() { // set the source of the player to the first track in the book + _logger.config('Setting up audiobook player'); } /// the [BookExpanded] being played @@ -84,20 +85,23 @@ class AudiobookPlayer extends AudioPlayer { List? downloadedUris, Uri? artworkUri, }) async { + _logger.finer( + 'Initial position: $initialPosition, Downloaded URIs: $downloadedUris', + ); final appSettings = loadOrCreateAppSettings(); - // if the book is null, stop the player if (book == null) { _book = null; _logger.info('Book is null, stopping player'); return stop(); } - // see if the book is the same as the current book if (_book == book) { _logger.info('Book is the same, doing nothing'); return; } - // first stop the player and clear the source + _logger.info('Setting source for book: $book'); + + _logger.fine('Stopping player'); await stop(); _book = book; @@ -114,6 +118,7 @@ class AudiobookPlayer extends AudioPlayer { ? initialPosition - trackToPlay.startOffset : null; + _logger.finer('Setting audioSource'); await setAudioSource( preload: preload, initialIndex: initialIndex, @@ -124,7 +129,7 @@ class AudiobookPlayer extends AudioPlayer { final retrievedUri = _getUri(track, downloadedUris, baseUrl: baseUrl, token: token); _logger.fine( - 'Setting source for track: ${track.title}, URI: $retrievedUri', + 'Setting source for track: ${track.title}, URI: ${retrievedUri.obfuscate()}', ); return AudioSource.uri( retrievedUri, @@ -145,7 +150,7 @@ class AudiobookPlayer extends AudioPlayer { }).toList(), ), ).catchError((error) { - _logger.shout('Error: $error'); + _logger.shout('Error in setting audio source: $error'); }); } @@ -153,7 +158,7 @@ class AudiobookPlayer extends AudioPlayer { Future togglePlayPause() { // check if book is set if (_book == null) { - throw StateError('No book is set'); + _logger.warning('No book is set, not toggling play/pause'); } // TODO refactor this to cover all the states @@ -169,9 +174,11 @@ class AudiobookPlayer extends AudioPlayer { @override Future seek(Duration? positionInBook, {int? index}) async { if (_book == null) { + _logger.warning('No book is set, not seeking'); return; } if (positionInBook == null) { + _logger.warning('Position given is null, not seeking'); return; } final tracks = _book!.tracks; diff --git a/lib/features/player/providers/audiobook_player.dart b/lib/features/player/providers/audiobook_player.dart index 947ca57..91b6483 100644 --- a/lib/features/player/providers/audiobook_player.dart +++ b/lib/features/player/providers/audiobook_player.dart @@ -1,21 +1,11 @@ +import 'package:logging/logging.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:vaani/api/api_provider.dart'; -import 'package:vaani/features/player/core/audiobook_player.dart' - as core; +import 'package:vaani/features/player/core/audiobook_player.dart' as core; part 'audiobook_player.g.dart'; -// @Riverpod(keepAlive: true) -// core.AudiobookPlayer audiobookPlayer( -// AudiobookPlayerRef ref, -// ) { -// final api = ref.watch(authenticatedApiProvider); -// final player = core.AudiobookPlayer(api.token!, api.baseUrl); - -// ref.onDispose(player.dispose); - -// return player; -// } +final _logger = Logger('AudiobookPlayerProvider'); const playerId = 'audiobook_player'; @@ -32,6 +22,7 @@ class SimpleAudiobookPlayer extends _$SimpleAudiobookPlayer { ); ref.onDispose(player.dispose); + _logger.finer('created simple player'); return player; } @@ -47,18 +38,16 @@ class AudiobookPlayer extends _$AudiobookPlayer { // bind notify listeners to the player player.playerStateStream.listen((_) { - notifyListeners(); + ref.notifyListeners(); }); + _logger.finer('created player'); + return player; } - void notifyListeners() { - ref.notifyListeners(); - } - Future setSpeed(double speed) async { await state.setSpeed(speed); - notifyListeners(); + ref.notifyListeners(); } } diff --git a/lib/features/player/providers/audiobook_player.g.dart b/lib/features/player/providers/audiobook_player.g.dart index 849cde6..a1068eb 100644 --- a/lib/features/player/providers/audiobook_player.g.dart +++ b/lib/features/player/providers/audiobook_player.g.dart @@ -7,7 +7,7 @@ part of 'audiobook_player.dart'; // ************************************************************************** String _$simpleAudiobookPlayerHash() => - r'9e11ed2791d35e308f8cbe61a79a45cf51466ebb'; + r'5e94bbff4314adceb5affa704fc4d079d4016afa'; /// Simple because it doesn't rebuild when the player state changes /// it only rebuilds when the token changes @@ -26,7 +26,7 @@ final simpleAudiobookPlayerProvider = ); typedef _$SimpleAudiobookPlayer = Notifier; -String _$audiobookPlayerHash() => r'44394b1dbbf85eb19ef1f693717e8cbc15b768e5'; +String _$audiobookPlayerHash() => r'0f180308067486896fec6a65a6afb0e6686ac4a0'; /// See also [AudiobookPlayer]. @ProviderFor(AudiobookPlayer) diff --git a/lib/features/player/providers/currently_playing_provider.dart b/lib/features/player/providers/currently_playing_provider.dart index 67e0a35..3ceff3e 100644 --- a/lib/features/player/providers/currently_playing_provider.dart +++ b/lib/features/player/providers/currently_playing_provider.dart @@ -1,3 +1,4 @@ +import 'package:logging/logging.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:shelfsdk/audiobookshelf_api.dart'; import 'package:vaani/features/player/providers/audiobook_player.dart'; @@ -5,12 +6,15 @@ import 'package:vaani/shared/extensions/model_conversions.dart'; part 'currently_playing_provider.g.dart'; +final _logger = Logger('CurrentlyPlayingProvider'); + @riverpod BookExpanded? currentlyPlayingBook(CurrentlyPlayingBookRef ref) { try { final player = ref.watch(audiobookPlayerProvider); return player.book; } catch (e) { + _logger.warning('Error getting currently playing book: $e'); return null; } } diff --git a/lib/features/player/providers/currently_playing_provider.g.dart b/lib/features/player/providers/currently_playing_provider.g.dart index fb22028..6dc1c2a 100644 --- a/lib/features/player/providers/currently_playing_provider.g.dart +++ b/lib/features/player/providers/currently_playing_provider.g.dart @@ -7,7 +7,7 @@ part of 'currently_playing_provider.dart'; // ************************************************************************** String _$currentlyPlayingBookHash() => - r'52334c7b4d68fd498a2a00208d8d7f1ba0085237'; + r'7440b0d54cb364f66e704783652e8f1490ae90e0'; /// See also [currentlyPlayingBook]. @ProviderFor(currentlyPlayingBook) diff --git a/lib/features/player/view/widgets/chapter_selection_button.dart b/lib/features/player/view/widgets/chapter_selection_button.dart index d4da604..889392a 100644 --- a/lib/features/player/view/widgets/chapter_selection_button.dart +++ b/lib/features/player/view/widgets/chapter_selection_button.dart @@ -4,6 +4,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:vaani/features/player/providers/audiobook_player.dart'; import 'package:vaani/features/player/providers/currently_playing_provider.dart'; import 'package:vaani/features/player/view/player_when_expanded.dart'; +import 'package:vaani/main.dart'; import 'package:vaani/shared/extensions/chapter.dart'; import 'package:vaani/shared/extensions/duration_format.dart'; import 'package:vaani/shared/hooks.dart'; @@ -55,7 +56,7 @@ class ChapterSelectionModal extends HookConsumerWidget { final currentChapterIndex = currentChapter?.id; final chapterKey = GlobalKey(); scrollToCurrentChapter() async { - debugPrint('scrolling to chapter'); + appLogger.fine('scrolling to chapter'); await Scrollable.ensureVisible( chapterKey.currentContext!, duration: 200.ms, diff --git a/lib/features/sleep_timer/core/sleep_timer.dart b/lib/features/sleep_timer/core/sleep_timer.dart index 9350436..2d9ea31 100644 --- a/lib/features/sleep_timer/core/sleep_timer.dart +++ b/lib/features/sleep_timer/core/sleep_timer.dart @@ -69,7 +69,7 @@ class SleepTimer { }), ); - _logger.fine('created with duration: $duration'); + _logger.info('created with duration: $duration'); } /// resets the timer and stops it @@ -90,7 +90,7 @@ class SleepTimer { if (player.playing) { startCountDown(); } - _logger.fine('restarted timer'); + _logger.info('restarted timer'); } /// starts the timer with the given duration or the default duration @@ -105,7 +105,7 @@ class SleepTimer { _logger.fine('paused player after $duration'); }); startedAt = DateTime.now(); - _logger.fine('started for $duration at $startedAt'); + _logger.info('started for $duration at $startedAt'); } Duration get remainingTime { @@ -130,6 +130,6 @@ class SleepTimer { for (var sub in _subscriptions) { sub.cancel(); } - _logger.fine('disposed'); + _logger.info('disposed'); } } diff --git a/lib/features/you/view/server_manager.dart b/lib/features/you/view/server_manager.dart index 2ab70ea..8a385f2 100644 --- a/lib/features/you/view/server_manager.dart +++ b/lib/features/you/view/server_manager.dart @@ -5,10 +5,12 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:vaani/api/api_provider.dart'; import 'package:vaani/api/authenticated_user_provider.dart'; import 'package:vaani/api/server_provider.dart'; +import 'package:vaani/main.dart'; import 'package:vaani/models/error_response.dart'; import 'package:vaani/router/router.dart'; import 'package:vaani/settings/api_settings_provider.dart'; import 'package:vaani/settings/models/models.dart' as model; +import 'package:vaani/shared/extensions/obfuscation.dart'; import 'package:vaani/shared/widgets/add_new_server.dart'; class ServerManagerPage extends HookConsumerWidget { @@ -25,8 +27,8 @@ class ServerManagerPage extends HookConsumerWidget { final serverURIController = useTextEditingController(); final formKey = GlobalKey(); - debugPrint('registered servers: $registeredServers'); - debugPrint('available users: $availableUsers'); + appLogger.fine('registered servers: ${registeredServers.obfuscate()}'); + appLogger.fine('available users: ${availableUsers.obfuscate()}'); return Scaffold( appBar: AppBar( title: const Text('Manage Accounts'), diff --git a/lib/features/you/view/you_page.dart b/lib/features/you/view/you_page.dart index a171a70..2a7bee2 100644 --- a/lib/features/you/view/you_page.dart +++ b/lib/features/you/view/you_page.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:shelfsdk/audiobookshelf_api.dart'; import 'package:vaani/api/api_provider.dart'; import 'package:vaani/router/router.dart'; +import 'package:vaani/settings/constants.dart'; import 'package:vaani/shared/utils.dart'; import 'package:vaani/shared/widgets/not_implemented.dart'; @@ -12,27 +12,6 @@ class YouPage extends HookConsumerWidget { super.key, }); - @override - Widget build(BuildContext context, WidgetRef ref) { - final me = ref.watch(meProvider); - return me.when( - data: (data) { - return _YouPage(userData: data); - }, - loading: () => const CircularProgressIndicator(), - error: (error, stack) => Text('Error: $error'), - ); - } -} - -class _YouPage extends HookConsumerWidget { - const _YouPage({ - super.key, - required this.userData, - }); - - final User userData; - @override Widget build(BuildContext context, WidgetRef ref) { final api = ref.watch(authenticatedApiProvider); @@ -41,14 +20,21 @@ class _YouPage extends HookConsumerWidget { // title: const Text('You'), backgroundColor: Colors.transparent, actions: [ + IconButton( + tooltip: 'Logs', + icon: const Icon(Icons.bug_report), + onPressed: () { + context.pushNamed(Routes.logs.name); + }, + ), // IconButton( // icon: const Icon(Icons.edit), // onPressed: () { // // Handle edit profile // }, // ), - // settings button IconButton( + tooltip: 'Settings', icon: const Icon(Icons.settings), onPressed: () { context.pushNamed(Routes.settings.name); @@ -64,30 +50,7 @@ class _YouPage extends HookConsumerWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - children: [ - CircleAvatar( - radius: 40, - // backgroundImage: NetworkImage(userData.avatarUrl), - // first letter of the username - child: Text( - userData.username[0].toUpperCase(), - style: const TextStyle( - fontSize: 32, - fontWeight: FontWeight.bold, - ), - ), - ), - const SizedBox(width: 16), - Text( - userData.username, - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - ), - ), - ], - ), + UserBar(), const SizedBox(height: 16), Wrap( spacing: 8, @@ -121,21 +84,6 @@ class _YouPage extends HookConsumerWidget { title: const Text('My Playlists'), onTap: () { // Handle navigation to playlists - }, - ), - ListTile( - leading: const Icon(Icons.help), - title: const Text('Help'), - onTap: () { - // Handle navigation to help website - showNotImplementedToast(context); - }, - ), - ListTile( - leading: const Icon(Icons.info), - title: const Text('About'), - onTap: () { - // Handle navigation to about showNotImplementedToast(context); }, ), @@ -149,10 +97,40 @@ class _YouPage extends HookConsumerWidget { ); }, ), - // const SizedBox(height: 16), - // const Text('App Version: 1.0.0'), - // const Text('Server Version: 1.0.0'), - // const Text('Author: Your Name'), + ListTile( + leading: const Icon(Icons.help), + title: const Text('Help'), + onTap: () { + // Handle navigation to help website + showNotImplementedToast(context); + }, + ), + + AboutListTile( + icon: const Icon(Icons.info), + applicationName: AppMetadata.appName, + applicationVersion: AppMetadata.version, + applicationLegalese: + 'Made with ❤️ by ${AppMetadata.author}', + aboutBoxChildren: [ + // link to github repo + ListTile( + leading: Icon(Icons.code), + title: Text('Source Code'), + onTap: () { + handleLaunchUrl(AppMetadata.githubRepo); + }, + ), + ], + // apply blend mode to the icon to match the primary color + applicationIcon: ColorFiltered( + colorFilter: ColorFilter.mode( + Theme.of(context).colorScheme.primary, + BlendMode.srcIn, + ), + child: const VaaniLogo(), + ), + ), ], ), ), @@ -162,3 +140,71 @@ class _YouPage extends HookConsumerWidget { ); } } + +class UserBar extends HookConsumerWidget { + const UserBar({ + super.key, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final me = ref.watch(meProvider); + + return me.when( + data: (userData) { + return Row( + children: [ + CircleAvatar( + radius: 40, + // backgroundImage: NetworkImage(userData.avatarUrl), + // first letter of the username + child: Text( + userData.username[0].toUpperCase(), + style: const TextStyle( + fontSize: 32, + fontWeight: FontWeight.bold, + ), + ), + ), + const SizedBox(width: 16), + Text( + userData.username, + style: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + ), + ), + ], + ); + }, + loading: () => const CircularProgressIndicator(), + error: (error, stack) => Text('Error: $error'), + ); + } +} + +class VaaniLogo extends StatelessWidget { + const VaaniLogo({ + super.key, + this.size, + this.duration = const Duration(milliseconds: 750), + this.curve = Curves.fastOutSlowIn, + }); + + final double? size; + final Duration duration; + final Curve curve; + + @override + Widget build(BuildContext context) { + final IconThemeData iconTheme = IconTheme.of(context); + final double? iconSize = size ?? iconTheme.size; + return AnimatedContainer( + width: iconSize, + height: iconSize, + duration: duration, + curve: curve, + child: Image.asset('assets/images/vaani_logo_foreground.png'), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart index 8eef350..7f54ec1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,6 +4,7 @@ import 'package:logging/logging.dart'; import 'package:vaani/api/server_provider.dart'; import 'package:vaani/db/storage.dart'; import 'package:vaani/features/downloads/providers/download_manager.dart'; +import 'package:vaani/features/logging/core/logger.dart'; import 'package:vaani/features/playback_reporting/providers/playback_reporter_provider.dart'; import 'package:vaani/features/player/core/init.dart'; import 'package:vaani/features/player/providers/audiobook_player.dart'; @@ -12,7 +13,6 @@ import 'package:vaani/features/sleep_timer/providers/sleep_timer_provider.dart'; import 'package:vaani/router/router.dart'; import 'package:vaani/settings/api_settings_provider.dart'; import 'package:vaani/settings/app_settings_provider.dart'; -import 'package:vaani/shared/extensions/duration_format.dart'; import 'package:vaani/theme/theme.dart'; final appLogger = Logger('vaani'); @@ -20,13 +20,7 @@ final appLogger = Logger('vaani'); void main() async { WidgetsFlutterBinding.ensureInitialized(); // Configure the root Logger - Logger.root.level = Level.FINE; // Capture all logs - Logger.root.onRecord.listen((record) { - // Print log records to the console - debugPrint( - '${record.loggerName}: ${record.level.name}: ${record.time.time}: ${record.message}', - ); - }); + await initLogging(); // initialize the storage await initStorage(); @@ -34,7 +28,6 @@ void main() async { // initialize audio player await configurePlayer(); - // run the app runApp( const ProviderScope( diff --git a/lib/models/error_response.dart b/lib/models/error_response.dart index 2e4c926..954f3f3 100644 --- a/lib/models/error_response.dart +++ b/lib/models/error_response.dart @@ -1,5 +1,6 @@ import 'package:http/http.dart' as http; import 'package:logging/logging.dart'; +import 'package:vaani/shared/extensions/obfuscation.dart'; final _logger = Logger('ErrorResponse'); @@ -13,7 +14,7 @@ class ErrorResponseHandler { }) : _response = response ?? http.Response('', 418); void storeError(http.Response response, [Object? error]) { - _logger.fine('for $name got response: $response'); + _logger.fine('for $name got response: ${response.obfuscate()}'); _response = response; } diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart index 5b3ab41..4d402b3 100644 --- a/lib/pages/home_page.dart +++ b/lib/pages/home_page.dart @@ -3,6 +3,7 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:vaani/api/api_provider.dart'; +import 'package:vaani/main.dart'; import 'package:vaani/router/router.dart'; import 'package:vaani/settings/api_settings_provider.dart'; @@ -59,7 +60,7 @@ class HomePage extends HookConsumerWidget { final shelvesToDisplay = data // .where((element) => !element.id.contains('discover')) .map((shelf) { - debugPrint('building shelf ${shelf.label}'); + appLogger.fine('building shelf ${shelf.label}'); return HomeShelf( title: shelf.label, shelf: shelf, diff --git a/lib/pages/library_page.dart b/lib/pages/library_page.dart index fb97221..18eedee 100644 --- a/lib/pages/library_page.dart +++ b/lib/pages/library_page.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:vaani/api/api_provider.dart'; +import 'package:vaani/main.dart'; import 'package:vaani/settings/api_settings_provider.dart'; import '../shared/widgets/drawer.dart'; @@ -47,7 +48,7 @@ class LibraryPage extends HookConsumerWidget { final shelvesToDisplay = data // .where((element) => !element.id.contains('discover')) .map((shelf) { - debugPrint('building shelf ${shelf.label}'); + appLogger.fine('building shelf ${shelf.label}'); return HomeShelf( title: shelf.label, shelf: shelf, diff --git a/lib/router/constants.dart b/lib/router/constants.dart index 4d8e7c1..9d01c29 100644 --- a/lib/router/constants.dart +++ b/lib/router/constants.dart @@ -90,6 +90,12 @@ class Routes { name: 'openIDCallback', parentRoute: onboarding, ); + + // logs page + static const logs = _SimpleRoute( + pathName: 'logs', + name: 'logs', + ); } // a class to store path diff --git a/lib/router/router.dart b/lib/router/router.dart index 8910fc3..c5b1a67 100644 --- a/lib/router/router.dart +++ b/lib/router/router.dart @@ -5,10 +5,12 @@ import 'package:vaani/features/explore/view/explore_page.dart'; import 'package:vaani/features/explore/view/search_result_page.dart'; import 'package:vaani/features/item_viewer/view/library_item_page.dart'; import 'package:vaani/features/library_browser/view/library_browser_page.dart'; +import 'package:vaani/features/logging/view/logs_page.dart'; import 'package:vaani/features/onboarding/view/callback_page.dart'; import 'package:vaani/features/onboarding/view/onboarding_single_page.dart'; import 'package:vaani/features/you/view/server_manager.dart'; import 'package:vaani/features/you/view/you_page.dart'; +import 'package:vaani/main.dart'; import 'package:vaani/pages/home_page.dart'; import 'package:vaani/settings/view/app_settings_page.dart'; import 'package:vaani/settings/view/auto_sleep_timer_settings_page.dart'; @@ -215,6 +217,14 @@ class MyAppRouter { ), ], ), + + // loggers page + GoRoute( + path: Routes.logs.localPath, + name: Routes.logs.name, + // builder: (context, state) => const LogsPage(), + pageBuilder: defaultPageBuilder(const LogsPage()), + ), ], ); @@ -225,7 +235,7 @@ class MyAppRouter { // extract the code and state from the uri final code = state.uri.queryParameters['code']; final stateParam = state.uri.queryParameters['state']; - debugPrint('deep linking callback: code: $code, state: $stateParam'); + appLogger.fine('deep linking callback: code: $code, state: $stateParam'); var callbackPage = CallbackPage(code: code, state: stateParam, key: ValueKey(stateParam)); diff --git a/lib/router/scaffold_with_nav_bar.dart b/lib/router/scaffold_with_nav_bar.dart index 467ec71..0a89162 100644 --- a/lib/router/scaffold_with_nav_bar.dart +++ b/lib/router/scaffold_with_nav_bar.dart @@ -6,6 +6,7 @@ import 'package:vaani/features/explore/providers/search_controller.dart'; import 'package:vaani/features/player/providers/player_form.dart'; import 'package:vaani/features/player/view/audiobook_player.dart'; import 'package:vaani/features/player/view/player_when_expanded.dart'; +import 'package:vaani/main.dart'; import 'package:vaani/router/router.dart'; // stack to track changes in navigationShell.currentIndex @@ -42,13 +43,13 @@ class ScaffoldWithNavBar extends HookConsumerWidget { onBackButtonPressed() async { final isPlayerExpanded = playerProgress != playerMinHeight; - debugPrint( + appLogger.fine( 'BackButtonListener: Back button pressed, isPlayerExpanded: $isPlayerExpanded, stack: $navigationShellStack, pendingPlayerModals: $pendingPlayerModals', ); // close miniplayer if it is open if (isPlayerExpanded && pendingPlayerModals == 0) { - debugPrint( + appLogger.fine( 'BackButtonListener: closing the player', ); audioBookMiniplayerController.animateToHeight(state: PanelState.MIN); @@ -59,7 +60,7 @@ class ScaffoldWithNavBar extends HookConsumerWidget { final canPop = GoRouter.of(context).canPop(); if (canPop) { - debugPrint( + appLogger.fine( 'BackButtonListener: passing it to the router as canPop is true', ); return false; @@ -69,7 +70,7 @@ class ScaffoldWithNavBar extends HookConsumerWidget { // pop the last index from the stack and navigate to it final index = navigationShellStack.last; navigationShellStack.remove(index); - debugPrint('BackButtonListener: popping the stack, index: $index'); + appLogger.fine('BackButtonListener: popping the stack, index: $index'); // if the stack is empty, navigate to home else navigate to the last index if (navigationShellStack.isNotEmpty) { @@ -79,12 +80,12 @@ class ScaffoldWithNavBar extends HookConsumerWidget { } if (navigationShell.currentIndex != 0) { // if the stack is empty and the current branch is not home, navigate to home - debugPrint('BackButtonListener: navigating to home'); + appLogger.fine('BackButtonListener: navigating to home'); navigationShell.goBranch(0); return true; } - debugPrint('BackButtonListener: passing it to the router'); + appLogger.fine('BackButtonListener: passing it to the router'); return false; } @@ -149,12 +150,11 @@ class ScaffoldWithNavBar extends HookConsumerWidget { navigationShellStack.remove(index); } navigationShellStack.add(index); - debugPrint('Tapped index: $index, stack: $navigationShellStack'); + appLogger.fine('Tapped index: $index, stack: $navigationShellStack'); // Check if the current branch is the same as the branch that was tapped. - // If it is, debugPrint a message to the console. if (index == navigationShell.currentIndex) { - debugPrint('Tapped the current branch'); + appLogger.fine('Tapped the current branch'); // if current branch is explore, open the search view if (index == 2) { diff --git a/lib/settings/api_settings_provider.dart b/lib/settings/api_settings_provider.dart index ecd297e..91334f0 100644 --- a/lib/settings/api_settings_provider.dart +++ b/lib/settings/api_settings_provider.dart @@ -4,6 +4,7 @@ import 'package:logging/logging.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:vaani/db/available_boxes.dart'; import 'package:vaani/settings/models/api_settings.dart' as model; +import 'package:vaani/shared/extensions/obfuscation.dart'; part 'api_settings_provider.g.dart'; @@ -19,6 +20,7 @@ class ApiSettings extends _$ApiSettings { ref.listenSelf((_, __) { writeToBox(); }); + return state; } @@ -33,7 +35,7 @@ class ApiSettings extends _$ApiSettings { activeServer: foundSettings.activeUser?.server, ); } - _logger.fine('found api settings in box: $foundSettings'); + _logger.fine('found api settings in box: ${foundSettings.obfuscate()}'); return foundSettings; } else { // create a new settings object @@ -47,7 +49,7 @@ class ApiSettings extends _$ApiSettings { void writeToBox() { _box.clear(); _box.add(state); - _logger.fine('wrote api settings to box: $state'); + _logger.fine('wrote api settings to box: ${state.obfuscate()}'); } void updateState(model.ApiSettings newSettings, {bool force = false}) { diff --git a/lib/settings/api_settings_provider.g.dart b/lib/settings/api_settings_provider.g.dart index 0bfacbf..d9a222c 100644 --- a/lib/settings/api_settings_provider.g.dart +++ b/lib/settings/api_settings_provider.g.dart @@ -6,7 +6,7 @@ part of 'api_settings_provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$apiSettingsHash() => r'26e7e09e7369bac9fbf0589da9fd97d1f15b7926'; +String _$apiSettingsHash() => r'5bc1e16e9d72b77fb10637aabadf08e8947da580'; /// See also [ApiSettings]. @ProviderFor(ApiSettings) diff --git a/lib/settings/constants.dart b/lib/settings/constants.dart index 2429545..9ab7b55 100644 --- a/lib/settings/constants.dart +++ b/lib/settings/constants.dart @@ -10,5 +10,10 @@ class AppMetadata { // for deeplinking static const String appScheme = 'vaani'; + static const version = '1.0.0'; + static const author = 'Dr.Blank'; + + static Uri githubRepo = Uri.parse('https://github.com/Dr-Blank/Vaani'); + static get appNameLowerCase => appName.toLowerCase().replaceAll(' ', '_'); } diff --git a/lib/shared/extensions/obfuscation.dart b/lib/shared/extensions/obfuscation.dart new file mode 100644 index 0000000..c70715a --- /dev/null +++ b/lib/shared/extensions/obfuscation.dart @@ -0,0 +1,125 @@ +import 'package:flutter/foundation.dart'; +import 'package:http/http.dart' as http; +import 'package:vaani/settings/models/api_settings.dart'; +import 'package:vaani/settings/models/audiobookshelf_server.dart'; +import 'package:vaani/settings/models/authenticated_user.dart'; + +// bool kReleaseMode = true; + +extension ObfuscateString on String { + String obfuscate() { + if (!kReleaseMode) { + return this; + } + return 'obfuscated'; + } +} + +extension ObfuscateURI on Uri { + /// keeps everything except the base url for security reasons + Uri obfuscate() { + if (!kReleaseMode) { + return this; + } + + // do not obfuscate the local host + if ([null, 'localhost'].contains(host)) { + return this; + } + + // do not obfuscate file urls + if (scheme == 'file') { + return this; + } + + return replace( + userInfo: userInfo == '' ? '' : 'userInfoObfuscated', + host: 'hostObfuscated', + ); + } +} + +extension ObfuscateList on List { + List obfuscate() { + return map((e) { + if (e is AuthenticatedUser) { + return e.obfuscate() as T; + } else if (e is AudiobookShelfServer) { + return e.obfuscate() as T; + } else if (e is Uri) { + return e.obfuscate() as T; + } else { + return e; + } + }).toList(); + } +} + +extension ObfuscateSet on Set { + Set obfuscate() { + return toList().obfuscate().toSet(); + } +} + +extension ObfuscateAuthenticatedUser on AuthenticatedUser { + AuthenticatedUser obfuscate() { + if (!kReleaseMode) { + return this; + } + return copyWith( + password: password == null ? null : 'passwordObfuscated', + username: username == null ? null : 'usernameObfuscated', + authToken: 'authTokenObfuscated', + server: server.obfuscate(), + ); + } +} + +extension ObfuscateServer on AudiobookShelfServer { + AudiobookShelfServer obfuscate() { + if (!kReleaseMode) { + return this; + } + return copyWith( + serverUrl: serverUrl.obfuscate(), + ); + } +} + +extension ObfuscateApiSettings on ApiSettings { + ApiSettings obfuscate() { + if (!kReleaseMode) { + return this; + } + return copyWith( + activeServer: activeServer?.obfuscate(), + activeUser: activeUser?.obfuscate(), + ); + } +} + +extension ObfuscateRequest on http.BaseRequest { + http.BaseRequest obfuscate() { + if (!kReleaseMode) { + return this; + } + return http.Request( + method, + url.obfuscate(), + ); + } +} + +extension ObfuscateResponse on http.Response { + http.Response obfuscate() { + if (!kReleaseMode) { + return this; + } + return http.Response( + body, + statusCode, + headers: headers, + request: request?.obfuscate(), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index e675e19..b6de7a9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -47,7 +47,7 @@ packages: source: hosted version: "2.0.10" archive: - dependency: transitive + dependency: "direct main" description: name: archive sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d @@ -366,6 +366,22 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.1" + dio: + dependency: transitive + description: + name: dio + sha256: "5598aa796bbf4699afd5c67c0f5f6e2ed542afc956884b9cd58c306966efc260" + url: "https://pub.dev" + source: hosted + version: "5.7.0" + dio_web_adapter: + dependency: transitive + description: + name: dio_web_adapter + sha256: "33259a9276d6cea88774a0000cfae0d861003497755969c92faa223108620dc8" + url: "https://pub.dev" + source: hosted + version: "2.0.0" duration_picker: dependency: "direct main" description: @@ -407,7 +423,7 @@ packages: source: hosted version: "7.0.0" file_picker: - dependency: transitive + dependency: "direct main" description: name: file_picker sha256: "167bb619cdddaa10ef2907609feb8a79c16dfa479d3afaf960f8e223f754bf12" @@ -782,6 +798,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + logging_appenders: + dependency: "direct main" + description: + name: logging_appenders + sha256: e329e7472f99416d0edaaf6451fe6c02dec91d34535bd252e284a0b94ab23d79 + url: "https://pub.dev" + source: hosted + version: "1.3.1" lottie: dependency: "direct main" description: @@ -1095,6 +1119,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + share_plus: + dependency: "direct main" + description: + name: share_plus + sha256: "468c43f285207c84bcabf5737f33b914ceb8eb38398b91e5e3ad1698d1b72a52" + url: "https://pub.dev" + source: hosted + version: "10.0.2" + share_plus_platform_interface: + dependency: transitive + description: + name: share_plus_platform_interface + sha256: "6ababf341050edff57da8b6990f11f4e99eaba837865e2e6defe16d039619db5" + url: "https://pub.dev" + source: hosted + version: "5.0.0" shelf: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index fc1bfdb..0a4ac94 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -32,6 +32,7 @@ isar_version: &isar_version ^4.0.0-dev.13 # define the version to be used dependencies: animated_list_plus: ^0.5.2 animated_theme_switcher: ^2.0.10 + archive: ^3.6.1 audio_service: ^0.18.15 audio_session: ^0.1.19 audio_video_progress_bar: ^2.0.2 @@ -44,6 +45,7 @@ dependencies: device_info_plus: ^10.1.0 duration_picker: ^1.2.0 easy_stepper: ^0.8.4 + file_picker: ^8.1.2 flutter: sdk: flutter flutter_animate: ^4.5.0 @@ -69,6 +71,7 @@ dependencies: just_audio_media_kit: ^2.0.4 list_wheel_scroll_view_nls: ^0.0.3 logging: ^1.2.0 + logging_appenders: ^1.3.1 lottie: ^3.1.0 material_symbols_icons: ^4.2785.1 media_kit_libs_linux: any @@ -84,6 +87,7 @@ dependencies: riverpod_annotation: ^2.3.5 scroll_loop_auto_scroll: ^0.0.5 sensors_plus: ^6.0.1 + share_plus: ^10.0.2 shelfsdk: path: ./shelfsdk shimmer: ^3.0.0 @@ -114,6 +118,7 @@ flutter: - assets/ - assets/animations/ - assets/sounds/ + - assets/images/ # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg # An image asset can refer to one or more resolution-specific "variants", see diff --git a/test/features/logging/providers/logs_provider_test.dart b/test/features/logging/providers/logs_provider_test.dart new file mode 100644 index 0000000..68590b8 --- /dev/null +++ b/test/features/logging/providers/logs_provider_test.dart @@ -0,0 +1,24 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:logging/logging.dart'; +import 'package:logging_appenders/logging_appenders.dart'; +import 'package:vaani/features/logging/providers/logs_provider.dart'; + +void main() { + test( + 'Should parse log line', + () async { + final formatter = DefaultLogRecordFormatter(); + final logRecord = LogRecord( + Level.INFO, + 'getting location for name: "logs"', + 'GoRouter', + ); + final expected = parseLogLine( + formatter.format(logRecord), + ); + expect(logRecord.message, expected.message); + expect(logRecord.level, expected.level); + expect(logRecord.loggerName, expected.loggerName); + }, + ); +} diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 1e47bc9..8d09818 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -8,6 +8,7 @@ #include #include +#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { @@ -15,6 +16,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("IsarFlutterLibsPlugin")); MediaKitLibsWindowsAudioPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("MediaKitLibsWindowsAudioPluginCApi")); + SharePlusWindowsPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); UrlLauncherWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index c41e9ee..51689fc 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -5,6 +5,7 @@ list(APPEND FLUTTER_PLUGIN_LIST isar_flutter_libs media_kit_libs_windows_audio + share_plus url_launcher_windows ) From 19c5385b589e52e173d6603fa61c01c96dd112df Mon Sep 17 00:00:00 2001 From: "Dr.Blank" Date: Thu, 3 Oct 2024 06:31:55 -0400 Subject: [PATCH 37/92] fix: enable cleartext traffic in AndroidManifest.xml (#47) --- android/app/src/main/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index cb0a2a5..e67ad10 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -9,7 +9,7 @@ Date: Thu, 3 Oct 2024 06:33:48 -0400 Subject: [PATCH 38/92] fix: reset activeLibraryId on 'Try again' button press in HomePage --- lib/pages/home_page.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart index 4d402b3..4ff81c4 100644 --- a/lib/pages/home_page.dart +++ b/lib/pages/home_page.dart @@ -49,6 +49,9 @@ class HomePage extends HookConsumerWidget { // try again button ElevatedButton( onPressed: () { + ref.read(apiSettingsProvider.notifier).updateState( + apiSettings.copyWith(activeLibraryId: null), + ); ref.invalidate(personalizedViewProvider); }, child: const Text('Try again'), From 2175e6d06ca4639153207b4551b28ac9081f6be8 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Thu, 3 Oct 2024 06:34:50 -0400 Subject: [PATCH 39/92] refactor: formatting --- android/app/src/main/AndroidManifest.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index e67ad10..71b0a89 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -9,7 +9,8 @@ Date: Thu, 3 Oct 2024 06:38:07 -0400 Subject: [PATCH 40/92] chore: bump version to 0.0.11+2 in pubspec.yaml --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 0a4ac94..3ce174f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.0.10+1 +version: 0.0.11+2 environment: sdk: ">=3.3.4 <4.0.0" From 33c57da78f2cb3058fddfc1c20f744ef3963049d Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Thu, 3 Oct 2024 19:04:36 -0400 Subject: [PATCH 41/92] hotfix: add permission handling for external storage and update log file naming --- android/app/src/main/AndroidManifest.xml | 4 ++ .../logging/providers/logs_provider.dart | 3 +- lib/features/logging/view/logs_page.dart | 44 +++++++++++++++++ lib/shared/widgets/add_new_server.dart | 5 +- pubspec.lock | 48 +++++++++++++++++++ pubspec.yaml | 1 + .../flutter/generated_plugin_registrant.cc | 3 ++ windows/flutter/generated_plugins.cmake | 1 + 8 files changed, 106 insertions(+), 3 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 71b0a89..f74b367 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -7,10 +7,14 @@ + + + generateZipFilePath() async { } String generateZipFileName() { - return 'vaani-${DateTime.now().toIso8601String()}.zip'; + return 'vaani-${DateTime.now().microsecondsSinceEpoch}.zip'; } Level parseLevel(String level) { diff --git a/lib/features/logging/view/logs_page.dart b/lib/features/logging/view/logs_page.dart index f5ee104..9fbf50b 100644 --- a/lib/features/logging/view/logs_page.dart +++ b/lib/features/logging/view/logs_page.dart @@ -5,9 +5,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:logging/logging.dart'; +import 'package:permission_handler/permission_handler.dart'; import 'package:share_plus/share_plus.dart'; import 'package:vaani/features/logging/providers/logs_provider.dart'; import 'package:vaani/main.dart'; +import 'package:vaani/settings/metadata/metadata_provider.dart'; class LogsPage extends HookConsumerWidget { const LogsPage({super.key}); @@ -81,6 +83,46 @@ class LogsPage extends HookConsumerWidget { icon: const Icon(Icons.download), onPressed: () async { appLogger.info('Preparing logs for download'); + + if (Platform.isAndroid) { + final androidVersion = + await ref.watch(deviceSdkVersionProvider.future); + + if ((int.parse(androidVersion)) > 29) { + final status = await Permission.manageExternalStorage.status; + if (!status.isGranted) { + appLogger + .info('Requesting manageExternalStorage permission'); + final newStatus = + await Permission.manageExternalStorage.request(); + if (!newStatus.isGranted) { + appLogger + .warning('manageExternalStorage permission denied'); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Storage permission denied'), + ), + ); + return; + } + } + } else { + final status = await Permission.storage.status; + if (!status.isGranted) { + appLogger.info('Requesting storage permission'); + final newStatus = await Permission.storage.request(); + if (!newStatus.isGranted) { + appLogger.warning('Storage permission denied'); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Storage permission denied'), + ), + ); + return; + } + } + } + } final zipLogFilePath = await ref.read(logsProvider.notifier).getZipFilePath(); @@ -88,12 +130,14 @@ class LogsPage extends HookConsumerWidget { String? outputFile = await FilePicker.platform.saveFile( dialogTitle: 'Please select an output file:', fileName: zipLogFilePath.split('/').last, + bytes: await File(zipLogFilePath).readAsBytes(), ); if (outputFile != null) { try { final file = File(outputFile); final zipFile = File(zipLogFilePath); await zipFile.copy(file.path); + appLogger.info('File saved to: $outputFile'); } catch (e) { appLogger.severe('Error saving file: $e'); } diff --git a/lib/shared/widgets/add_new_server.dart b/lib/shared/widgets/add_new_server.dart index c04d8fd..9114c2b 100644 --- a/lib/shared/widgets/add_new_server.dart +++ b/lib/shared/widgets/add_new_server.dart @@ -39,7 +39,10 @@ class AddNewServer extends HookConsumerWidget { controller: controller, keyboardType: TextInputType.url, autofillHints: const [AutofillHints.url], - textInputAction: TextInputAction.next, + textInputAction: TextInputAction.done, + onFieldSubmitted: (_) { + onPressed?.call(); + }, decoration: InputDecoration( labelText: 'Server URI', labelStyle: TextStyle( diff --git a/pubspec.lock b/pubspec.lock index b6de7a9..670cc8f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -991,6 +991,54 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.0" + permission_handler: + dependency: "direct main" + description: + name: permission_handler + sha256: "18bf33f7fefbd812f37e72091a15575e72d5318854877e0e4035a24ac1113ecb" + url: "https://pub.dev" + source: hosted + version: "11.3.1" + permission_handler_android: + dependency: transitive + description: + name: permission_handler_android + sha256: "76e4ab092c1b240d31177bb64d2b0bea43f43d0e23541ec866151b9f7b2490fa" + url: "https://pub.dev" + source: hosted + version: "12.0.12" + permission_handler_apple: + dependency: transitive + description: + name: permission_handler_apple + sha256: e6f6d73b12438ef13e648c4ae56bd106ec60d17e90a59c4545db6781229082a0 + url: "https://pub.dev" + source: hosted + version: "9.4.5" + permission_handler_html: + dependency: transitive + description: + name: permission_handler_html + sha256: af26edbbb1f2674af65a8f4b56e1a6f526156bc273d0e65dd8075fab51c78851 + url: "https://pub.dev" + source: hosted + version: "0.1.3+2" + permission_handler_platform_interface: + dependency: transitive + description: + name: permission_handler_platform_interface + sha256: e9c8eadee926c4532d0305dff94b85bf961f16759c3af791486613152af4b4f9 + url: "https://pub.dev" + source: hosted + version: "4.2.3" + permission_handler_windows: + dependency: transitive + description: + name: permission_handler_windows + sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" + url: "https://pub.dev" + source: hosted + version: "0.2.1" petitparser: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 3ce174f..31df2ab 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -84,6 +84,7 @@ dependencies: package_info_plus: ^8.0.0 path: ^1.9.0 path_provider: ^2.1.0 + permission_handler: ^11.3.1 riverpod_annotation: ^2.3.5 scroll_loop_auto_scroll: ^0.0.5 sensors_plus: ^6.0.1 diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 8d09818..d043b0b 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -16,6 +17,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("IsarFlutterLibsPlugin")); MediaKitLibsWindowsAudioPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("MediaKitLibsWindowsAudioPluginCApi")); + PermissionHandlerWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); SharePlusWindowsPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); UrlLauncherWindowsRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 51689fc..9839b50 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -5,6 +5,7 @@ list(APPEND FLUTTER_PLUGIN_LIST isar_flutter_libs media_kit_libs_windows_audio + permission_handler_windows share_plus url_launcher_windows ) From eda45efbcee7f231d1f7b526ca7fb072a79ce9f1 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Thu, 3 Oct 2024 19:05:29 -0400 Subject: [PATCH 42/92] chore: bump version to 0.0.12+3 in pubspec.yaml --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 31df2ab..1b4fb1c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.0.11+2 +version: 0.0.12+3 environment: sdk: ">=3.3.4 <4.0.0" From fa815ae206d509fcbceecc6e463b9a8dd7bcbf44 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Fri, 4 Oct 2024 02:31:51 -0400 Subject: [PATCH 43/92] refactor: update AuthenticatedUser model to require id and remove password, enhance server URI handling in AddNewServer widget --- lib/api/api_provider.dart | 68 ++++++++- lib/api/api_provider.g.dart | 133 +++++++++++++++++- .../view/onboarding_single_page.dart | 2 +- .../view/user_login_with_password.dart | 1 - lib/models/error_response.dart | 6 +- lib/settings/models/authenticated_user.dart | 3 +- .../models/authenticated_user.freezed.dart | 62 +++----- lib/settings/models/authenticated_user.g.dart | 4 +- lib/shared/extensions/obfuscation.dart | 48 ++++++- lib/shared/widgets/add_new_server.dart | 42 ++++-- 10 files changed, 297 insertions(+), 72 deletions(-) diff --git a/lib/api/api_provider.dart b/lib/api/api_provider.dart index 1d3745f..bc50f8a 100644 --- a/lib/api/api_provider.dart +++ b/lib/api/api_provider.dart @@ -7,7 +7,9 @@ import 'package:logging/logging.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:shelfsdk/audiobookshelf_api.dart'; import 'package:vaani/db/cache_manager.dart'; +import 'package:vaani/models/error_response.dart'; import 'package:vaani/settings/api_settings_provider.dart'; +import 'package:vaani/settings/models/authenticated_user.dart'; import 'package:vaani/shared/extensions/obfuscation.dart'; part 'api_provider.g.dart'; @@ -49,6 +51,7 @@ AudiobookshelfApi authenticatedApi(AuthenticatedApiRef ref) { final apiSettings = ref.watch(apiSettingsProvider); final user = apiSettings.activeUser; if (user == null) { + _logger.severe('No active user can not provide authenticated api'); throw StateError('No active user'); } return AudiobookshelfApi( @@ -97,17 +100,26 @@ class PersonalizedView extends _$PersonalizedView { final api = ref.watch(authenticatedApiProvider); final apiSettings = ref.watch(apiSettingsProvider); final user = apiSettings.activeUser; + if (user == null) { + _logger.warning('no active user'); + yield []; + return; + } if (apiSettings.activeLibraryId == null) { // set it to default user library by logging in and getting the library id - final login = - await api.login(username: user!.username!, password: user.password!); + final login = await ref.read(loginProvider().future); + if (login == null) { + _logger.shout('failed to login, not building personalized view'); + yield []; + return; + } ref.read(apiSettingsProvider.notifier).updateState( - apiSettings.copyWith(activeLibraryId: login!.userDefaultLibraryId), + apiSettings.copyWith(activeLibraryId: login.userDefaultLibraryId), ); } // try to find in cache // final cacheKey = 'personalizedView:${apiSettings.activeLibraryId}'; - var key = 'personalizedView:${apiSettings.activeLibraryId! + user!.id!}'; + final key = 'personalizedView:${apiSettings.activeLibraryId! + user.id}'; final cachedRes = await apiResponseCacheManager.getFileFromMemory( key, ) ?? @@ -127,7 +139,7 @@ class PersonalizedView extends _$PersonalizedView { } } - // ! exagerated delay + // ! exaggerated delay // await Future.delayed(const Duration(seconds: 2)); final res = await api.libraries .getPersonalized(libraryId: apiSettings.activeLibraryId!); @@ -151,6 +163,7 @@ class PersonalizedView extends _$PersonalizedView { // method to force refresh the view and ignore the cache Future forceRefresh() async { // clear the cache + // TODO: find a better way to clear the cache for only personalized view key return apiResponseCacheManager.emptyCache(); } } @@ -173,6 +186,47 @@ FutureOr me( MeRef ref, ) async { final api = ref.watch(authenticatedApiProvider); - final res = await api.me.getUser(); - return res!; + final errorResponseHandler = ErrorResponseHandler(); + final res = await api.me.getUser( + responseErrorHandler: errorResponseHandler.storeError, + ); + if (res == null) { + _logger.severe( + 'me failed, got response: ${errorResponseHandler.response.obfuscate()}', + ); + throw StateError('me failed'); + } + return res; +} + +@riverpod +FutureOr login( + LoginRef ref, { + AuthenticatedUser? user, +}) async { + if (user == null) { + // try to get the user from settings + final apiSettings = ref.watch(apiSettingsProvider); + user = apiSettings.activeUser; + if (user == null) { + _logger.severe('no active user to login'); + return null; + } + _logger.fine('no user provided, using active user: ${user.obfuscate()}'); + } + final api = ref.watch(audiobookshelfApiProvider(user.server.serverUrl)); + api.token = user.authToken; + var errorResponseHandler = ErrorResponseHandler(); + _logger.fine('logging in with authenticated api'); + final res = await api.misc.authorize( + responseErrorHandler: errorResponseHandler.storeError, + ); + if (res == null) { + _logger.severe( + 'login failed, got response: ${errorResponseHandler.response.obfuscate()}', + ); + return null; + } + _logger.fine('login response: ${res.obfuscate()}'); + return res; } diff --git a/lib/api/api_provider.g.dart b/lib/api/api_provider.g.dart index 7758c7b..796adf7 100644 --- a/lib/api/api_provider.g.dart +++ b/lib/api/api_provider.g.dart @@ -168,7 +168,7 @@ class _AudiobookshelfApiProviderElement Uri? get baseUrl => (origin as AudiobookshelfApiProvider).baseUrl; } -String _$authenticatedApiHash() => r'f555efb6eede590b5a8d60cad2e6bfc2847e2d14'; +String _$authenticatedApiHash() => r'e662465f01ab1a6384db4738a3ae49b5fab48a4f'; /// get the api instance for the authenticated user /// @@ -507,7 +507,7 @@ final fetchContinueListeningProvider = typedef FetchContinueListeningRef = AutoDisposeFutureProviderRef; -String _$meHash() => r'bdc664c4fd867ad13018fa769ce7a6913248c44f'; +String _$meHash() => r'da5f40b8063b0c0a6651fdcc4ac2d192d0dc7df6'; /// See also [me]. @ProviderFor(me) @@ -521,7 +521,134 @@ final meProvider = AutoDisposeFutureProvider.internal( ); typedef MeRef = AutoDisposeFutureProviderRef; -String _$personalizedViewHash() => r'4c392ece4650bdc36d7195a0ddb8810e8fe4caa9'; +String _$loginHash() => r'eb1c4fcef1818dce994846c1adb8eca8f6ec9259'; + +/// See also [login]. +@ProviderFor(login) +const loginProvider = LoginFamily(); + +/// See also [login]. +class LoginFamily extends Family> { + /// See also [login]. + const LoginFamily(); + + /// See also [login]. + LoginProvider call({ + AuthenticatedUser? user, + }) { + return LoginProvider( + user: user, + ); + } + + @override + LoginProvider getProviderOverride( + covariant LoginProvider provider, + ) { + return call( + user: provider.user, + ); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'loginProvider'; +} + +/// See also [login]. +class LoginProvider extends AutoDisposeFutureProvider { + /// See also [login]. + LoginProvider({ + AuthenticatedUser? user, + }) : this._internal( + (ref) => login( + ref as LoginRef, + user: user, + ), + from: loginProvider, + name: r'loginProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$loginHash, + dependencies: LoginFamily._dependencies, + allTransitiveDependencies: LoginFamily._allTransitiveDependencies, + user: user, + ); + + LoginProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.user, + }) : super.internal(); + + final AuthenticatedUser? user; + + @override + Override overrideWith( + FutureOr Function(LoginRef provider) create, + ) { + return ProviderOverride( + origin: this, + override: LoginProvider._internal( + (ref) => create(ref as LoginRef), + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + user: user, + ), + ); + } + + @override + AutoDisposeFutureProviderElement createElement() { + return _LoginProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is LoginProvider && other.user == user; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, user.hashCode); + + return _SystemHash.finish(hash); + } +} + +mixin LoginRef on AutoDisposeFutureProviderRef { + /// The parameter `user` of this provider. + AuthenticatedUser? get user; +} + +class _LoginProviderElement + extends AutoDisposeFutureProviderElement with LoginRef { + _LoginProviderElement(super.provider); + + @override + AuthenticatedUser? get user => (origin as LoginProvider).user; +} + +String _$personalizedViewHash() => r'65c0bc60e312d290498ab488496495114d407ccb'; /// fetch the personalized view /// diff --git a/lib/features/onboarding/view/onboarding_single_page.dart b/lib/features/onboarding/view/onboarding_single_page.dart index 5ceff08..79f0d63 100644 --- a/lib/features/onboarding/view/onboarding_single_page.dart +++ b/lib/features/onboarding/view/onboarding_single_page.dart @@ -17,7 +17,7 @@ class OnboardingSinglePage extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final apiSettings = ref.watch(apiSettingsProvider); final serverUriController = useTextEditingController( - text: apiSettings.activeServer?.serverUrl.toString() ?? '', + text: apiSettings.activeServer?.serverUrl.toString() ?? 'https://', ); var audiobookshelfUri = makeBaseUrl(serverUriController.text); diff --git a/lib/features/onboarding/view/user_login_with_password.dart b/lib/features/onboarding/view/user_login_with_password.dart index 91eeea0..43a52e5 100644 --- a/lib/features/onboarding/view/user_login_with_password.dart +++ b/lib/features/onboarding/view/user_login_with_password.dart @@ -76,7 +76,6 @@ class UserLoginWithPassword extends HookConsumerWidget { final authenticatedUser = model.AuthenticatedUser( server: addServer(), id: success.user.id, - password: password, username: username, authToken: api.token!, ); diff --git a/lib/models/error_response.dart b/lib/models/error_response.dart index 954f3f3..13352be 100644 --- a/lib/models/error_response.dart +++ b/lib/models/error_response.dart @@ -7,14 +7,18 @@ final _logger = Logger('ErrorResponse'); class ErrorResponseHandler { String? name; http.Response _response; + bool logRawResponse; ErrorResponseHandler({ this.name, http.Response? response, + this.logRawResponse = false, }) : _response = response ?? http.Response('', 418); void storeError(http.Response response, [Object? error]) { - _logger.fine('for $name got response: ${response.obfuscate()}'); + if (logRawResponse) { + _logger.fine('for $name got response: ${response.obfuscate()}'); + } _response = response; } diff --git a/lib/settings/models/authenticated_user.dart b/lib/settings/models/authenticated_user.dart index 04f2bd0..321c885 100644 --- a/lib/settings/models/authenticated_user.dart +++ b/lib/settings/models/authenticated_user.dart @@ -10,9 +10,8 @@ class AuthenticatedUser with _$AuthenticatedUser { const factory AuthenticatedUser({ required AudiobookShelfServer server, required String authToken, - String? id, + required String id, String? username, - String? password, }) = _AuthenticatedUser; factory AuthenticatedUser.fromJson(Map json) => diff --git a/lib/settings/models/authenticated_user.freezed.dart b/lib/settings/models/authenticated_user.freezed.dart index e582928..2a7ce53 100644 --- a/lib/settings/models/authenticated_user.freezed.dart +++ b/lib/settings/models/authenticated_user.freezed.dart @@ -22,9 +22,8 @@ AuthenticatedUser _$AuthenticatedUserFromJson(Map json) { mixin _$AuthenticatedUser { AudiobookShelfServer get server => throw _privateConstructorUsedError; String get authToken => throw _privateConstructorUsedError; - String? get id => throw _privateConstructorUsedError; + String get id => throw _privateConstructorUsedError; String? get username => throw _privateConstructorUsedError; - String? get password => throw _privateConstructorUsedError; /// Serializes this AuthenticatedUser to a JSON map. Map toJson() => throw _privateConstructorUsedError; @@ -45,9 +44,8 @@ abstract class $AuthenticatedUserCopyWith<$Res> { $Res call( {AudiobookShelfServer server, String authToken, - String? id, - String? username, - String? password}); + String id, + String? username}); $AudiobookShelfServerCopyWith<$Res> get server; } @@ -69,9 +67,8 @@ class _$AuthenticatedUserCopyWithImpl<$Res, $Val extends AuthenticatedUser> $Res call({ Object? server = null, Object? authToken = null, - Object? id = freezed, + Object? id = null, Object? username = freezed, - Object? password = freezed, }) { return _then(_value.copyWith( server: null == server @@ -82,18 +79,14 @@ class _$AuthenticatedUserCopyWithImpl<$Res, $Val extends AuthenticatedUser> ? _value.authToken : authToken // ignore: cast_nullable_to_non_nullable as String, - id: freezed == id + id: null == id ? _value.id : id // ignore: cast_nullable_to_non_nullable - as String?, + as String, username: freezed == username ? _value.username : username // ignore: cast_nullable_to_non_nullable as String?, - password: freezed == password - ? _value.password - : password // ignore: cast_nullable_to_non_nullable - as String?, ) as $Val); } @@ -119,9 +112,8 @@ abstract class _$$AuthenticatedUserImplCopyWith<$Res> $Res call( {AudiobookShelfServer server, String authToken, - String? id, - String? username, - String? password}); + String id, + String? username}); @override $AudiobookShelfServerCopyWith<$Res> get server; @@ -142,9 +134,8 @@ class __$$AuthenticatedUserImplCopyWithImpl<$Res> $Res call({ Object? server = null, Object? authToken = null, - Object? id = freezed, + Object? id = null, Object? username = freezed, - Object? password = freezed, }) { return _then(_$AuthenticatedUserImpl( server: null == server @@ -155,18 +146,14 @@ class __$$AuthenticatedUserImplCopyWithImpl<$Res> ? _value.authToken : authToken // ignore: cast_nullable_to_non_nullable as String, - id: freezed == id + id: null == id ? _value.id : id // ignore: cast_nullable_to_non_nullable - as String?, + as String, username: freezed == username ? _value.username : username // ignore: cast_nullable_to_non_nullable as String?, - password: freezed == password - ? _value.password - : password // ignore: cast_nullable_to_non_nullable - as String?, )); } } @@ -177,9 +164,8 @@ class _$AuthenticatedUserImpl implements _AuthenticatedUser { const _$AuthenticatedUserImpl( {required this.server, required this.authToken, - this.id, - this.username, - this.password}); + required this.id, + this.username}); factory _$AuthenticatedUserImpl.fromJson(Map json) => _$$AuthenticatedUserImplFromJson(json); @@ -189,15 +175,13 @@ class _$AuthenticatedUserImpl implements _AuthenticatedUser { @override final String authToken; @override - final String? id; + final String id; @override final String? username; - @override - final String? password; @override String toString() { - return 'AuthenticatedUser(server: $server, authToken: $authToken, id: $id, username: $username, password: $password)'; + return 'AuthenticatedUser(server: $server, authToken: $authToken, id: $id, username: $username)'; } @override @@ -210,15 +194,12 @@ class _$AuthenticatedUserImpl implements _AuthenticatedUser { other.authToken == authToken) && (identical(other.id, id) || other.id == id) && (identical(other.username, username) || - other.username == username) && - (identical(other.password, password) || - other.password == password)); + other.username == username)); } @JsonKey(includeFromJson: false, includeToJson: false) @override - int get hashCode => - Object.hash(runtimeType, server, authToken, id, username, password); + int get hashCode => Object.hash(runtimeType, server, authToken, id, username); /// Create a copy of AuthenticatedUser /// with the given fields replaced by the non-null parameter values. @@ -241,9 +222,8 @@ abstract class _AuthenticatedUser implements AuthenticatedUser { const factory _AuthenticatedUser( {required final AudiobookShelfServer server, required final String authToken, - final String? id, - final String? username, - final String? password}) = _$AuthenticatedUserImpl; + required final String id, + final String? username}) = _$AuthenticatedUserImpl; factory _AuthenticatedUser.fromJson(Map json) = _$AuthenticatedUserImpl.fromJson; @@ -253,11 +233,9 @@ abstract class _AuthenticatedUser implements AuthenticatedUser { @override String get authToken; @override - String? get id; + String get id; @override String? get username; - @override - String? get password; /// Create a copy of AuthenticatedUser /// with the given fields replaced by the non-null parameter values. diff --git a/lib/settings/models/authenticated_user.g.dart b/lib/settings/models/authenticated_user.g.dart index 0752807..4ff5a06 100644 --- a/lib/settings/models/authenticated_user.g.dart +++ b/lib/settings/models/authenticated_user.g.dart @@ -12,9 +12,8 @@ _$AuthenticatedUserImpl _$$AuthenticatedUserImplFromJson( server: AudiobookShelfServer.fromJson(json['server'] as Map), authToken: json['authToken'] as String, - id: json['id'] as String?, + id: json['id'] as String, username: json['username'] as String?, - password: json['password'] as String?, ); Map _$$AuthenticatedUserImplToJson( @@ -24,5 +23,4 @@ Map _$$AuthenticatedUserImplToJson( 'authToken': instance.authToken, 'id': instance.id, 'username': instance.username, - 'password': instance.password, }; diff --git a/lib/shared/extensions/obfuscation.dart b/lib/shared/extensions/obfuscation.dart index c70715a..6ff85fe 100644 --- a/lib/shared/extensions/obfuscation.dart +++ b/lib/shared/extensions/obfuscation.dart @@ -1,5 +1,6 @@ import 'package:flutter/foundation.dart'; import 'package:http/http.dart' as http; +import 'package:shelfsdk/audiobookshelf_api.dart' as shelfsdk; import 'package:vaani/settings/models/api_settings.dart'; import 'package:vaani/settings/models/audiobookshelf_server.dart'; import 'package:vaani/settings/models/authenticated_user.dart'; @@ -67,7 +68,6 @@ extension ObfuscateAuthenticatedUser on AuthenticatedUser { return this; } return copyWith( - password: password == null ? null : 'passwordObfuscated', username: username == null ? null : 'usernameObfuscated', authToken: 'authTokenObfuscated', server: server.obfuscate(), @@ -116,10 +116,54 @@ extension ObfuscateResponse on http.Response { return this; } return http.Response( - body, + obfuscateBody(), statusCode, headers: headers, request: request?.obfuscate(), ); } + + String obfuscateBody() { + if (!kReleaseMode) { + return body; + } + // replace any email addresses with emailObfuscated + // replace any phone numbers with phoneObfuscated + // replace any urls with urlObfuscated + // replace any tokens with tokenObfuscated + // token regex is `"token": "..."` + return body + .replaceAll( + RegExp(r'(\b\w+@\w+\.\w+\b)|' + r'(\b\d{3}-\d{3}-\d{4}\b)|' + r'(\bhttps?://\S+\b)'), + 'obfuscated', + ) + .replaceAll( + RegExp(r'"?token"?:?\s*"[^"]+"'), + '"token": "tokenObfuscated"', + ); + } +} + +extension ObfuscateLoginResponse on shelfsdk.LoginResponse { + shelfsdk.LoginResponse obfuscate() { + if (!kReleaseMode) { + return this; + } + return copyWith( + user: user.obfuscate(), + ); + } +} + +extension ObfuscateUser on shelfsdk.User { + shelfsdk.User obfuscate() { + if (!kReleaseMode) { + return this; + } + return shelfsdk.User.fromJson( + toJson()..['token'] = 'tokenObfuscated', + ); + } } diff --git a/lib/shared/widgets/add_new_server.dart b/lib/shared/widgets/add_new_server.dart index 9114c2b..a0c10e6 100644 --- a/lib/shared/widgets/add_new_server.dart +++ b/lib/shared/widgets/add_new_server.dart @@ -2,6 +2,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:vaani/api/api_provider.dart'; +import 'package:vaani/main.dart'; + +final httpUrlRegExp = RegExp('https?://'); class AddNewServer extends HookConsumerWidget { const AddNewServer({ @@ -25,7 +28,8 @@ class AddNewServer extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final myController = controller ?? useTextEditingController(); + final myController = + controller ?? useTextEditingController(text: 'https://'); var newServerURI = useValueListenable(myController); final isServerAlive = ref.watch(isServerAliveProvider(newServerURI.text)); bool isServerAliveValue = isServerAlive.when( @@ -34,15 +38,33 @@ class AddNewServer extends HookConsumerWidget { error: (error, _) => false, ); + Uri parsedUri = Uri.parse(''); + + try { + parsedUri = Uri.parse(newServerURI.text); + } on FormatException { + // prepend https:// if not present + if (!newServerURI.text.startsWith(httpUrlRegExp)) { + myController.text = 'https://${newServerURI.text}'; + parsedUri = Uri.parse(myController.text); + } + } catch (e) { + // do nothing + appLogger.severe('Error parsing URI: $e'); + } + final canSubmit = !readOnly && + (isServerAliveValue || (allowEmpty && newServerURI.text.isEmpty)); return TextFormField( readOnly: readOnly, controller: controller, keyboardType: TextInputType.url, autofillHints: const [AutofillHints.url], textInputAction: TextInputAction.done, - onFieldSubmitted: (_) { - onPressed?.call(); - }, + onFieldSubmitted: canSubmit + ? (_) { + onPressed?.call(); + } + : null, decoration: InputDecoration( labelText: 'Server URI', labelStyle: TextStyle( @@ -50,8 +72,8 @@ class AddNewServer extends HookConsumerWidget { ), border: const OutlineInputBorder(), prefixText: - myController.text.startsWith(RegExp('https?://')) ? '' : 'https://', - prefixIcon: ServerAliveIcon(server: Uri.parse(newServerURI.text)), + myController.text.startsWith(httpUrlRegExp) ? '' : 'https://', + prefixIcon: ServerAliveIcon(server: parsedUri), // add server button suffixIcon: onPressed == null @@ -65,10 +87,10 @@ class AddNewServer extends HookConsumerWidget { focusColor: Theme.of(context).colorScheme.onSurface, // should be enabled when - onPressed: !readOnly && - (isServerAliveValue || - (allowEmpty && newServerURI.text.isEmpty)) - ? onPressed + onPressed: canSubmit + ? () { + onPressed?.call(); + } : null, // disable button if server is not alive ), ), From 758e4cdc8337d9f19fe93fff6779db9cae856197 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Sat, 5 Oct 2024 04:48:52 -0400 Subject: [PATCH 44/92] refactor: update personalized view handling, improve GitHub issue link, and adjust VaaniLogo size --- lib/api/api_provider.dart | 2 ++ lib/api/api_provider.g.dart | 2 +- lib/features/onboarding/view/user_login_with_password.dart | 7 +++++-- lib/features/you/view/you_page.dart | 5 +++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/api/api_provider.dart b/lib/api/api_provider.dart index bc50f8a..fb0a938 100644 --- a/lib/api/api_provider.dart +++ b/lib/api/api_provider.dart @@ -116,6 +116,8 @@ class PersonalizedView extends _$PersonalizedView { ref.read(apiSettingsProvider.notifier).updateState( apiSettings.copyWith(activeLibraryId: login.userDefaultLibraryId), ); + yield []; + return; } // try to find in cache // final cacheKey = 'personalizedView:${apiSettings.activeLibraryId}'; diff --git a/lib/api/api_provider.g.dart b/lib/api/api_provider.g.dart index 796adf7..ec2eeab 100644 --- a/lib/api/api_provider.g.dart +++ b/lib/api/api_provider.g.dart @@ -648,7 +648,7 @@ class _LoginProviderElement AuthenticatedUser? get user => (origin as LoginProvider).user; } -String _$personalizedViewHash() => r'65c0bc60e312d290498ab488496495114d407ccb'; +String _$personalizedViewHash() => r'425e89d99d7e4712b4d6a688f3a12442bd66584f'; /// fetch the personalized view /// diff --git a/lib/features/onboarding/view/user_login_with_password.dart b/lib/features/onboarding/view/user_login_with_password.dart index 43a52e5..7628959 100644 --- a/lib/features/onboarding/view/user_login_with_password.dart +++ b/lib/features/onboarding/view/user_login_with_password.dart @@ -9,6 +9,7 @@ import 'package:vaani/api/authenticated_user_provider.dart'; import 'package:vaani/hacks/fix_autofill_losing_focus.dart'; import 'package:vaani/models/error_response.dart'; import 'package:vaani/router/router.dart'; +import 'package:vaani/settings/constants.dart'; import 'package:vaani/settings/models/models.dart' as model; import 'package:vaani/shared/utils.dart'; @@ -206,8 +207,10 @@ Future handleServerError( onPressed: () { // open an issue on the github page handleLaunchUrl( - Uri.parse( - 'https://github.com/Dr-Blank/Vaani/issues', + AppMetadata.githubRepo + // append the issue url + .replace( + path: '${AppMetadata.githubRepo.path}/issues/new', ), ); }, diff --git a/lib/features/you/view/you_page.dart b/lib/features/you/view/you_page.dart index 2a7bee2..11fa89d 100644 --- a/lib/features/you/view/you_page.dart +++ b/lib/features/you/view/you_page.dart @@ -105,7 +105,6 @@ class YouPage extends HookConsumerWidget { showNotImplementedToast(context); }, ), - AboutListTile( icon: const Icon(Icons.info), applicationName: AppMetadata.appName, @@ -128,7 +127,9 @@ class YouPage extends HookConsumerWidget { Theme.of(context).colorScheme.primary, BlendMode.srcIn, ), - child: const VaaniLogo(), + child: const VaaniLogo( + size: 48, + ), ), ), ], From ff83c2cc63c417853ef56a3bdc9d0e3409771154 Mon Sep 17 00:00:00 2001 From: "Dr.Blank" Date: Sat, 5 Oct 2024 10:01:08 -0400 Subject: [PATCH 45/92] feat: multiple theming options (#50) * refactor: consolidate theme definitions by removing separate dark and light theme files * feat: integrate dynamic color support and enhance theme settings management * feat: add theme settings route and update theme management in app settings * feat: enhance theme management by integrating high contrast support in various components * feat: implement mode selection dialog for theme settings and enhance button functionality * refactor: update theme import paths and consolidate theme provider files * feat: enhance theme management by integrating theme selection based on audiobook playback * refactor: update default value for useMaterialThemeFromSystem to false in theme settings * refactor: adjust high contrast condition order in theme settings for consistency * refactor: rename useMaterialThemeOfPlayingItem to useCurrentPlayerThemeThroughoutApp for clarity * refactor: correct spelling in system theme provider and replace with updated implementation * refactor: extract restore backup dialog into a separate widget for improved readability * refactor: reorganize settings sections for clarity and improve restore dialog functionality --- .vscode/settings.json | 1 + .../view/library_item_hero_section.dart | 11 +- .../player/view/audiobook_player.dart | 4 +- lib/main.dart | 77 +++++- lib/router/constants.dart | 5 + lib/router/router.dart | 8 + lib/settings/app_settings_provider.dart | 5 - lib/settings/app_settings_provider.g.dart | 2 +- lib/settings/models/app_settings.dart | 5 +- lib/settings/models/app_settings.freezed.dart | 114 ++++++-- lib/settings/models/app_settings.g.dart | 18 +- lib/settings/view/app_settings_page.dart | 247 +++++++++-------- lib/settings/view/buttons.dart | 4 + lib/settings/view/theme_settings_page.dart | 261 ++++++++++++++++++ lib/shared/widgets/shelves/book_shelf.dart | 2 +- lib/theme/dark.dart | 10 - lib/theme/light.dart | 10 - .../providers/system_theme_provider.dart | 73 +++++ .../providers/system_theme_provider.g.dart | 177 ++++++++++++ .../theme_from_cover_provider.dart | 21 +- .../theme_from_cover_provider.g.dart | 40 ++- lib/theme/theme.dart | 16 +- linux/flutter/generated_plugin_registrant.cc | 4 + linux/flutter/generated_plugins.cmake | 1 + pubspec.lock | 8 + pubspec.yaml | 1 + .../flutter/generated_plugin_registrant.cc | 3 + windows/flutter/generated_plugins.cmake | 1 + 28 files changed, 935 insertions(+), 194 deletions(-) create mode 100644 lib/settings/view/theme_settings_page.dart delete mode 100644 lib/theme/dark.dart delete mode 100644 lib/theme/light.dart create mode 100644 lib/theme/providers/system_theme_provider.dart create mode 100644 lib/theme/providers/system_theme_provider.g.dart rename lib/theme/{ => providers}/theme_from_cover_provider.dart (81%) rename lib/theme/{ => providers}/theme_from_cover_provider.g.dart (86%) diff --git a/.vscode/settings.json b/.vscode/settings.json index ffa9f03..b4c5fa8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -12,6 +12,7 @@ "audioplayers", "autolabeler", "Autovalidate", + "Checkmark", "deeplinking", "fullscreen", "Lerp", diff --git a/lib/features/item_viewer/view/library_item_hero_section.dart b/lib/features/item_viewer/view/library_item_hero_section.dart index 83b5555..856c5a5 100644 --- a/lib/features/item_viewer/view/library_item_hero_section.dart +++ b/lib/features/item_viewer/view/library_item_hero_section.dart @@ -15,7 +15,7 @@ import 'package:vaani/settings/app_settings_provider.dart'; import 'package:vaani/shared/extensions/duration_format.dart'; import 'package:vaani/shared/extensions/model_conversions.dart'; import 'package:vaani/shared/widgets/shelves/book_shelf.dart'; -import 'package:vaani/theme/theme_from_cover_provider.dart'; +import 'package:vaani/theme/providers/theme_from_cover_provider.dart'; class LibraryItemHeroSection extends HookConsumerWidget { const LibraryItemHeroSection({ @@ -353,16 +353,17 @@ class _BookCover extends HookConsumerWidget { final coverImage = ref.watch(coverImageProvider(itemId)); final themeData = Theme.of(context); // final item = ref.watch(libraryItemProvider(itemId)); - final useMaterialThemeOnItemPage = - ref.watch(appSettingsProvider).themeSettings.useMaterialThemeOnItemPage; + final themeSettings = ref.watch(appSettingsProvider).themeSettings; ColorScheme? coverColorScheme; - if (useMaterialThemeOnItemPage) { + if (themeSettings.useMaterialThemeOnItemPage) { coverColorScheme = ref .watch( themeOfLibraryItemProvider( itemId, brightness: Theme.of(context).brightness, + highContrast: themeSettings.highContrast || + MediaQuery.of(context).highContrast, ), ) .valueOrNull; @@ -371,7 +372,7 @@ class _BookCover extends HookConsumerWidget { return ThemeSwitcher( builder: (context) { // change theme after 2 seconds - if (useMaterialThemeOnItemPage) { + if (themeSettings.useMaterialThemeOnItemPage) { Future.delayed(150.ms, () { try { ThemeSwitcher.of(context).changeTheme( diff --git a/lib/features/player/view/audiobook_player.dart b/lib/features/player/view/audiobook_player.dart index 46ed7aa..1940ba7 100644 --- a/lib/features/player/view/audiobook_player.dart +++ b/lib/features/player/view/audiobook_player.dart @@ -14,7 +14,7 @@ import 'package:vaani/features/player/providers/player_form.dart'; import 'package:vaani/settings/app_settings_provider.dart'; import 'package:vaani/shared/extensions/inverse_lerp.dart'; import 'package:vaani/shared/widgets/shelves/book_shelf.dart'; -import 'package:vaani/theme/theme_from_cover_provider.dart'; +import 'package:vaani/theme/providers/theme_from_cover_provider.dart'; import 'player_when_expanded.dart'; import 'player_when_minimized.dart'; @@ -65,6 +65,8 @@ class AudiobookPlayer extends HookConsumerWidget { themeOfLibraryItemProvider( itemBeingPlayed.valueOrNull?.id, brightness: Theme.of(context).brightness, + highContrast: appSettings.themeSettings.highContrast || + MediaQuery.of(context).highContrast, ), ); diff --git a/lib/main.dart b/lib/main.dart index 7f54ec1..0da35ae 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,4 @@ +import 'package:dynamic_color/dynamic_color.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:logging/logging.dart'; @@ -7,12 +8,15 @@ import 'package:vaani/features/downloads/providers/download_manager.dart'; import 'package:vaani/features/logging/core/logger.dart'; import 'package:vaani/features/playback_reporting/providers/playback_reporter_provider.dart'; import 'package:vaani/features/player/core/init.dart'; -import 'package:vaani/features/player/providers/audiobook_player.dart'; +import 'package:vaani/features/player/providers/audiobook_player.dart' + show audiobookPlayerProvider, simpleAudiobookPlayerProvider; import 'package:vaani/features/shake_detection/providers/shake_detector.dart'; import 'package:vaani/features/sleep_timer/providers/sleep_timer_provider.dart'; import 'package:vaani/router/router.dart'; import 'package:vaani/settings/api_settings_provider.dart'; import 'package:vaani/settings/app_settings_provider.dart'; +import 'package:vaani/theme/providers/system_theme_provider.dart'; +import 'package:vaani/theme/providers/theme_from_cover_provider.dart'; import 'package:vaani/theme/theme.dart'; final appLogger = Logger('vaani'); @@ -51,16 +55,77 @@ class MyApp extends ConsumerWidget { if (needOnboarding) { routerConfig.goNamed(Routes.onboarding.name); } + final appSettings = ref.watch(appSettingsProvider); + final themeSettings = appSettings.themeSettings; + ColorScheme lightColorScheme = brandLightColorScheme; + ColorScheme darkColorScheme = brandDarkColorScheme; + + final shouldUseHighContrast = + themeSettings.highContrast || MediaQuery.of(context).highContrast; + + if (shouldUseHighContrast) { + lightColorScheme = lightColorScheme.copyWith( + surface: Colors.white, + ); + darkColorScheme = darkColorScheme.copyWith( + surface: Colors.black, + ); + } + + if (themeSettings.useMaterialThemeFromSystem) { + var themes = + ref.watch(systemThemeProvider(highContrast: shouldUseHighContrast)); + if (themes.valueOrNull != null) { + lightColorScheme = themes.valueOrNull!.$1; + darkColorScheme = themes.valueOrNull!.$2; + } + } + + if (themeSettings.useCurrentPlayerThemeThroughoutApp) { + final player = ref.watch(audiobookPlayerProvider); + if (player.book != null) { + final themeLight = ref.watch( + themeOfLibraryItemProvider( + player.book!.libraryItemId, + highContrast: shouldUseHighContrast, + brightness: Brightness.light, + ), + ); + final themeDark = ref.watch( + themeOfLibraryItemProvider( + player.book!.libraryItemId, + highContrast: shouldUseHighContrast, + brightness: Brightness.dark, + ), + ); + if (themeLight.valueOrNull != null && themeDark.valueOrNull != null) { + lightColorScheme = themeLight.valueOrNull!; + darkColorScheme = themeDark.valueOrNull!; + } + } + } + final appThemeLight = ThemeData( + useMaterial3: true, + colorScheme: lightColorScheme.harmonized(), + ); + final appThemeDark = ThemeData( + useMaterial3: true, + colorScheme: darkColorScheme.harmonized(), + brightness: Brightness.dark, + // TODO bottom sheet theme is not working + bottomSheetTheme: BottomSheetThemeData( + backgroundColor: darkColorScheme.surface, + ), + ); try { return MaterialApp.router( // debugShowCheckedModeBanner: false, - theme: lightTheme, - darkTheme: darkTheme, - themeMode: ref.watch(appSettingsProvider).themeSettings.isDarkMode - ? ThemeMode.dark - : ThemeMode.light, + theme: appThemeLight, + darkTheme: appThemeDark, + themeMode: themeSettings.themeMode, routerConfig: routerConfig, + themeAnimationCurve: Curves.easeInOut, ); } catch (e) { debugPrintStack(stackTrace: StackTrace.current, label: e.toString()); diff --git a/lib/router/constants.dart b/lib/router/constants.dart index 9d01c29..f36d706 100644 --- a/lib/router/constants.dart +++ b/lib/router/constants.dart @@ -27,6 +27,11 @@ class Routes { pathName: 'config', name: 'settings', ); + static const themeSettings = _SimpleRoute( + pathName: 'theme', + name: 'themeSettings', + parentRoute: settings, + ); static const autoSleepTimerSettings = _SimpleRoute( pathName: 'autoSleepTimer', name: 'autoSleepTimerSettings', diff --git a/lib/router/router.dart b/lib/router/router.dart index c5b1a67..5e9f71e 100644 --- a/lib/router/router.dart +++ b/lib/router/router.dart @@ -17,6 +17,7 @@ import 'package:vaani/settings/view/auto_sleep_timer_settings_page.dart'; import 'package:vaani/settings/view/notification_settings_page.dart'; import 'package:vaani/settings/view/player_settings_page.dart'; import 'package:vaani/settings/view/shake_detector_settings_page.dart'; +import 'package:vaani/settings/view/theme_settings_page.dart'; import 'scaffold_with_nav_bar.dart'; import 'transitions/slide.dart'; @@ -178,6 +179,13 @@ class MyAppRouter { // 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, diff --git a/lib/settings/app_settings_provider.dart b/lib/settings/app_settings_provider.dart index 6d61774..b86e736 100644 --- a/lib/settings/app_settings_provider.dart +++ b/lib/settings/app_settings_provider.dart @@ -47,11 +47,6 @@ class AppSettings extends _$AppSettings { _logger.fine('wrote settings to box: $state'); } - void toggleDarkMode() { - state = state.copyWith - .themeSettings(isDarkMode: !state.themeSettings.isDarkMode); - } - void update(model.AppSettings newSettings) { state = newSettings; } diff --git a/lib/settings/app_settings_provider.g.dart b/lib/settings/app_settings_provider.g.dart index df95738..85d58cd 100644 --- a/lib/settings/app_settings_provider.g.dart +++ b/lib/settings/app_settings_provider.g.dart @@ -6,7 +6,7 @@ part of 'app_settings_provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$appSettingsHash() => r'f51d55f117692d4fb9f4b4febf02906c0953d334'; +String _$appSettingsHash() => r'314d7936f54550f57d308056a99230402342a6d0'; /// See also [AppSettings]. @ProviderFor(AppSettings) diff --git a/lib/settings/models/app_settings.dart b/lib/settings/models/app_settings.dart index 80262ea..e486ac4 100644 --- a/lib/settings/models/app_settings.dart +++ b/lib/settings/models/app_settings.dart @@ -28,7 +28,10 @@ class AppSettings with _$AppSettings { @freezed class ThemeSettings with _$ThemeSettings { const factory ThemeSettings({ - @Default(true) bool isDarkMode, + @Default(ThemeMode.system) ThemeMode themeMode, + @Default(false) bool highContrast, + @Default(false) bool useMaterialThemeFromSystem, + @Default('#FF311B92') String customThemeColor, @Default(true) bool useMaterialThemeOnItemPage, @Default(true) bool useCurrentPlayerThemeThroughoutApp, }) = _ThemeSettings; diff --git a/lib/settings/models/app_settings.freezed.dart b/lib/settings/models/app_settings.freezed.dart index 3f8fd48..fc52047 100644 --- a/lib/settings/models/app_settings.freezed.dart +++ b/lib/settings/models/app_settings.freezed.dart @@ -378,7 +378,10 @@ ThemeSettings _$ThemeSettingsFromJson(Map json) { /// @nodoc mixin _$ThemeSettings { - bool get isDarkMode => throw _privateConstructorUsedError; + ThemeMode get themeMode => throw _privateConstructorUsedError; + bool get highContrast => throw _privateConstructorUsedError; + bool get useMaterialThemeFromSystem => throw _privateConstructorUsedError; + String get customThemeColor => throw _privateConstructorUsedError; bool get useMaterialThemeOnItemPage => throw _privateConstructorUsedError; bool get useCurrentPlayerThemeThroughoutApp => throw _privateConstructorUsedError; @@ -400,7 +403,10 @@ abstract class $ThemeSettingsCopyWith<$Res> { _$ThemeSettingsCopyWithImpl<$Res, ThemeSettings>; @useResult $Res call( - {bool isDarkMode, + {ThemeMode themeMode, + bool highContrast, + bool useMaterialThemeFromSystem, + String customThemeColor, bool useMaterialThemeOnItemPage, bool useCurrentPlayerThemeThroughoutApp}); } @@ -420,15 +426,30 @@ class _$ThemeSettingsCopyWithImpl<$Res, $Val extends ThemeSettings> @pragma('vm:prefer-inline') @override $Res call({ - Object? isDarkMode = null, + Object? themeMode = null, + Object? highContrast = null, + Object? useMaterialThemeFromSystem = null, + Object? customThemeColor = null, Object? useMaterialThemeOnItemPage = null, Object? useCurrentPlayerThemeThroughoutApp = null, }) { return _then(_value.copyWith( - isDarkMode: null == isDarkMode - ? _value.isDarkMode - : isDarkMode // ignore: cast_nullable_to_non_nullable + themeMode: null == themeMode + ? _value.themeMode + : themeMode // ignore: cast_nullable_to_non_nullable + as ThemeMode, + highContrast: null == highContrast + ? _value.highContrast + : highContrast // ignore: cast_nullable_to_non_nullable as bool, + useMaterialThemeFromSystem: null == useMaterialThemeFromSystem + ? _value.useMaterialThemeFromSystem + : useMaterialThemeFromSystem // ignore: cast_nullable_to_non_nullable + as bool, + customThemeColor: null == customThemeColor + ? _value.customThemeColor + : customThemeColor // ignore: cast_nullable_to_non_nullable + as String, useMaterialThemeOnItemPage: null == useMaterialThemeOnItemPage ? _value.useMaterialThemeOnItemPage : useMaterialThemeOnItemPage // ignore: cast_nullable_to_non_nullable @@ -451,7 +472,10 @@ abstract class _$$ThemeSettingsImplCopyWith<$Res> @override @useResult $Res call( - {bool isDarkMode, + {ThemeMode themeMode, + bool highContrast, + bool useMaterialThemeFromSystem, + String customThemeColor, bool useMaterialThemeOnItemPage, bool useCurrentPlayerThemeThroughoutApp}); } @@ -469,15 +493,30 @@ class __$$ThemeSettingsImplCopyWithImpl<$Res> @pragma('vm:prefer-inline') @override $Res call({ - Object? isDarkMode = null, + Object? themeMode = null, + Object? highContrast = null, + Object? useMaterialThemeFromSystem = null, + Object? customThemeColor = null, Object? useMaterialThemeOnItemPage = null, Object? useCurrentPlayerThemeThroughoutApp = null, }) { return _then(_$ThemeSettingsImpl( - isDarkMode: null == isDarkMode - ? _value.isDarkMode - : isDarkMode // ignore: cast_nullable_to_non_nullable + themeMode: null == themeMode + ? _value.themeMode + : themeMode // ignore: cast_nullable_to_non_nullable + as ThemeMode, + highContrast: null == highContrast + ? _value.highContrast + : highContrast // ignore: cast_nullable_to_non_nullable as bool, + useMaterialThemeFromSystem: null == useMaterialThemeFromSystem + ? _value.useMaterialThemeFromSystem + : useMaterialThemeFromSystem // ignore: cast_nullable_to_non_nullable + as bool, + customThemeColor: null == customThemeColor + ? _value.customThemeColor + : customThemeColor // ignore: cast_nullable_to_non_nullable + as String, useMaterialThemeOnItemPage: null == useMaterialThemeOnItemPage ? _value.useMaterialThemeOnItemPage : useMaterialThemeOnItemPage // ignore: cast_nullable_to_non_nullable @@ -495,7 +534,10 @@ class __$$ThemeSettingsImplCopyWithImpl<$Res> @JsonSerializable() class _$ThemeSettingsImpl implements _ThemeSettings { const _$ThemeSettingsImpl( - {this.isDarkMode = true, + {this.themeMode = ThemeMode.system, + this.highContrast = false, + this.useMaterialThemeFromSystem = false, + this.customThemeColor = '#FF311B92', this.useMaterialThemeOnItemPage = true, this.useCurrentPlayerThemeThroughoutApp = true}); @@ -504,7 +546,16 @@ class _$ThemeSettingsImpl implements _ThemeSettings { @override @JsonKey() - final bool isDarkMode; + final ThemeMode themeMode; + @override + @JsonKey() + final bool highContrast; + @override + @JsonKey() + final bool useMaterialThemeFromSystem; + @override + @JsonKey() + final String customThemeColor; @override @JsonKey() final bool useMaterialThemeOnItemPage; @@ -514,7 +565,7 @@ class _$ThemeSettingsImpl implements _ThemeSettings { @override String toString() { - return 'ThemeSettings(isDarkMode: $isDarkMode, useMaterialThemeOnItemPage: $useMaterialThemeOnItemPage, useCurrentPlayerThemeThroughoutApp: $useCurrentPlayerThemeThroughoutApp)'; + return 'ThemeSettings(themeMode: $themeMode, highContrast: $highContrast, useMaterialThemeFromSystem: $useMaterialThemeFromSystem, customThemeColor: $customThemeColor, useMaterialThemeOnItemPage: $useMaterialThemeOnItemPage, useCurrentPlayerThemeThroughoutApp: $useCurrentPlayerThemeThroughoutApp)'; } @override @@ -522,8 +573,16 @@ class _$ThemeSettingsImpl implements _ThemeSettings { return identical(this, other) || (other.runtimeType == runtimeType && other is _$ThemeSettingsImpl && - (identical(other.isDarkMode, isDarkMode) || - other.isDarkMode == isDarkMode) && + (identical(other.themeMode, themeMode) || + other.themeMode == themeMode) && + (identical(other.highContrast, highContrast) || + other.highContrast == highContrast) && + (identical(other.useMaterialThemeFromSystem, + useMaterialThemeFromSystem) || + other.useMaterialThemeFromSystem == + useMaterialThemeFromSystem) && + (identical(other.customThemeColor, customThemeColor) || + other.customThemeColor == customThemeColor) && (identical(other.useMaterialThemeOnItemPage, useMaterialThemeOnItemPage) || other.useMaterialThemeOnItemPage == @@ -536,8 +595,14 @@ class _$ThemeSettingsImpl implements _ThemeSettings { @JsonKey(includeFromJson: false, includeToJson: false) @override - int get hashCode => Object.hash(runtimeType, isDarkMode, - useMaterialThemeOnItemPage, useCurrentPlayerThemeThroughoutApp); + int get hashCode => Object.hash( + runtimeType, + themeMode, + highContrast, + useMaterialThemeFromSystem, + customThemeColor, + useMaterialThemeOnItemPage, + useCurrentPlayerThemeThroughoutApp); /// Create a copy of ThemeSettings /// with the given fields replaced by the non-null parameter values. @@ -557,7 +622,10 @@ class _$ThemeSettingsImpl implements _ThemeSettings { abstract class _ThemeSettings implements ThemeSettings { const factory _ThemeSettings( - {final bool isDarkMode, + {final ThemeMode themeMode, + final bool highContrast, + final bool useMaterialThemeFromSystem, + final String customThemeColor, final bool useMaterialThemeOnItemPage, final bool useCurrentPlayerThemeThroughoutApp}) = _$ThemeSettingsImpl; @@ -565,7 +633,13 @@ abstract class _ThemeSettings implements ThemeSettings { _$ThemeSettingsImpl.fromJson; @override - bool get isDarkMode; + ThemeMode get themeMode; + @override + bool get highContrast; + @override + bool get useMaterialThemeFromSystem; + @override + String get customThemeColor; @override bool get useMaterialThemeOnItemPage; @override diff --git a/lib/settings/models/app_settings.g.dart b/lib/settings/models/app_settings.g.dart index 90b317e..45bb74b 100644 --- a/lib/settings/models/app_settings.g.dart +++ b/lib/settings/models/app_settings.g.dart @@ -46,7 +46,12 @@ Map _$$AppSettingsImplToJson(_$AppSettingsImpl instance) => _$ThemeSettingsImpl _$$ThemeSettingsImplFromJson(Map json) => _$ThemeSettingsImpl( - isDarkMode: json['isDarkMode'] as bool? ?? true, + themeMode: $enumDecodeNullable(_$ThemeModeEnumMap, json['themeMode']) ?? + ThemeMode.system, + highContrast: json['highContrast'] as bool? ?? false, + useMaterialThemeFromSystem: + json['useMaterialThemeFromSystem'] as bool? ?? false, + customThemeColor: json['customThemeColor'] as String? ?? '#FF311B92', useMaterialThemeOnItemPage: json['useMaterialThemeOnItemPage'] as bool? ?? true, useCurrentPlayerThemeThroughoutApp: @@ -55,12 +60,21 @@ _$ThemeSettingsImpl _$$ThemeSettingsImplFromJson(Map json) => Map _$$ThemeSettingsImplToJson(_$ThemeSettingsImpl instance) => { - 'isDarkMode': instance.isDarkMode, + 'themeMode': _$ThemeModeEnumMap[instance.themeMode]!, + 'highContrast': instance.highContrast, + 'useMaterialThemeFromSystem': instance.useMaterialThemeFromSystem, + 'customThemeColor': instance.customThemeColor, 'useMaterialThemeOnItemPage': instance.useMaterialThemeOnItemPage, 'useCurrentPlayerThemeThroughoutApp': instance.useCurrentPlayerThemeThroughoutApp, }; +const _$ThemeModeEnumMap = { + ThemeMode.system: 'system', + ThemeMode.light: 'light', + ThemeMode.dark: 'dark', +}; + _$PlayerSettingsImpl _$$PlayerSettingsImplFromJson(Map json) => _$PlayerSettingsImpl( miniPlayerSettings: json['miniPlayerSettings'] == null diff --git a/lib/settings/view/app_settings_page.dart b/lib/settings/view/app_settings_page.dart index 77afaae..aebe867 100644 --- a/lib/settings/view/app_settings_page.dart +++ b/lib/settings/view/app_settings_page.dart @@ -7,11 +7,10 @@ import 'package:flutter_settings_ui/flutter_settings_ui.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:material_symbols_icons/symbols.dart'; -import 'package:vaani/api/authenticated_user_provider.dart'; -import 'package:vaani/api/server_provider.dart'; import 'package:vaani/router/router.dart'; import 'package:vaani/settings/app_settings_provider.dart'; import 'package:vaani/settings/models/app_settings.dart' as model; +import 'package:vaani/settings/view/buttons.dart'; import 'package:vaani/settings/view/simple_settings_page.dart'; import 'package:vaani/settings/view/widgets/navigation_with_switch_tile.dart'; @@ -23,58 +22,11 @@ class AppSettingsPage extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final appSettings = ref.watch(appSettingsProvider); - final registeredServers = ref.watch(audiobookShelfServerProvider); - final registeredServersAsList = registeredServers.toList(); - final availableUsers = ref.watch(authenticatedUserProvider); - final serverURIController = useTextEditingController(); final sleepTimerSettings = appSettings.sleepTimerSettings; return SimpleSettingsPage( title: const Text('App Settings'), sections: [ - // Appearance section - SettingsSection( - margin: const EdgeInsetsDirectional.symmetric( - horizontal: 16.0, - vertical: 8.0, - ), - title: Text( - 'Appearance', - style: Theme.of(context).textTheme.titleLarge, - ), - tiles: [ - SettingsTile.switchTile( - initialValue: appSettings.themeSettings.isDarkMode, - title: const Text('Dark Mode'), - description: const Text('we all know dark mode is better'), - leading: appSettings.themeSettings.isDarkMode - ? const Icon(Icons.dark_mode) - : const Icon(Icons.light_mode), - onToggle: (value) { - ref.read(appSettingsProvider.notifier).toggleDarkMode(); - }, - ), - SettingsTile.switchTile( - initialValue: - appSettings.themeSettings.useMaterialThemeOnItemPage, - title: const Text('Adaptive Theme on Item Page'), - description: const Text( - 'get fancy with the colors on the item page at the cost of some performance', - ), - leading: appSettings.themeSettings.useMaterialThemeOnItemPage - ? const Icon(Icons.auto_fix_high) - : const Icon(Icons.auto_fix_off), - onToggle: (value) { - ref.read(appSettingsProvider.notifier).update( - appSettings.copyWith.themeSettings( - useMaterialThemeOnItemPage: value, - ), - ); - }, - ), - ], - ), - // General section SettingsSection( margin: const EdgeInsetsDirectional.symmetric( @@ -86,6 +38,16 @@ class AppSettingsPage extends HookConsumerWidget { style: Theme.of(context).textTheme.titleLarge, ), tiles: [ + SettingsTile( + title: const Text('Player Settings'), + leading: const Icon(Icons.play_arrow), + description: const Text( + 'Customize the player settings', + ), + onPressed: (context) { + context.pushNamed(Routes.playerSettings.name); + }, + ), NavigationWithSwitchTile( title: const Text('Auto Turn On Sleep Timer'), description: const Text( @@ -106,26 +68,6 @@ class AppSettingsPage extends HookConsumerWidget { ); }, ), - SettingsTile( - title: const Text('Notification Media Player'), - leading: const Icon(Icons.play_lesson), - description: const Text( - 'Customize the media player in notifications', - ), - onPressed: (context) { - context.pushNamed(Routes.notificationSettings.name); - }, - ), - SettingsTile( - title: const Text('Player Settings'), - leading: const Icon(Icons.play_arrow), - description: const Text( - 'Customize the player settings', - ), - onPressed: (context) { - context.pushNamed(Routes.playerSettings.name); - }, - ), NavigationWithSwitchTile( title: const Text('Shake Detector'), leading: const Icon(Icons.vibration), @@ -146,6 +88,41 @@ class AppSettingsPage extends HookConsumerWidget { ), ], ), + + // Appearance section + SettingsSection( + margin: const EdgeInsetsDirectional.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + title: Text( + 'Appearance', + style: Theme.of(context).textTheme.titleLarge, + ), + tiles: [ + SettingsTile.navigation( + leading: const Icon(Icons.color_lens), + title: const Text('Theme Settings'), + description: const Text( + 'Customize the app theme', + ), + onPressed: (context) { + context.pushNamed(Routes.themeSettings.name); + }, + ), + SettingsTile( + title: const Text('Notification Media Player'), + leading: const Icon(Icons.play_lesson), + description: const Text( + 'Customize the media player in notifications', + ), + onPressed: (context) { + context.pushNamed(Routes.notificationSettings.name); + }, + ), + ], + ), + // Backup and Restore section SettingsSection( margin: const EdgeInsetsDirectional.symmetric( @@ -185,61 +162,11 @@ class AppSettingsPage extends HookConsumerWidget { 'Restore the app settings from the backup', ), onPressed: (context) { - final formKey = GlobalKey(); // show a dialog to get the backup showDialog( context: context, builder: (context) { - return AlertDialog( - title: const Text('Restore Backup'), - content: Form( - key: formKey, - child: TextFormField( - controller: serverURIController, - decoration: const InputDecoration( - labelText: 'Backup', - hintText: 'Paste the backup here', - ), - validator: (value) { - if (value == null || value.isEmpty) { - return 'Please paste the backup here'; - } - return null; - }, - ), - ), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: const Text('Cancel'), - ), - TextButton( - onPressed: () { - if (formKey.currentState!.validate()) { - final backup = serverURIController.text; - final newSettings = model.AppSettings.fromJson( - // decode the backup as json - jsonDecode(backup), - ); - ref - .read(appSettingsProvider.notifier) - .update(newSettings); - Navigator.of(context).pop(); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Settings restored'), - ), - ); - // clear the backup - serverURIController.clear(); - } - }, - child: const Text('Restore'), - ), - ], - ); + return RestoreDialogue(); }, ); }, @@ -292,3 +219,83 @@ class AppSettingsPage extends HookConsumerWidget { ); } } + +class RestoreDialogue extends HookConsumerWidget { + const RestoreDialogue({ + super.key, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final formKey = useMemoized(() => GlobalKey()); + final settings = useState(null); + + final settingsInputController = useTextEditingController(); + return AlertDialog( + title: const Text('Restore Backup'), + content: Form( + key: formKey, + child: TextFormField( + autofocus: true, + decoration: InputDecoration( + labelText: 'Backup', + hintText: 'Paste the backup here', + // clear button + suffixIcon: IconButton( + icon: Icon(Icons.clear), + onPressed: () { + settingsInputController.clear(); + }, + ), + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please paste the backup here'; + } + try { + // try to decode the backup + settings.value = model.AppSettings.fromJson( + jsonDecode(value), + ); + } catch (e) { + return 'Invalid backup'; + } + return null; + }, + ), + ), + actions: [ + CancelButton(), + TextButton( + onPressed: () { + if (formKey.currentState!.validate()) { + if (settings.value == null) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Invalid backup'), + ), + ); + return; + } + ref.read(appSettingsProvider.notifier).update(settings.value!); + settingsInputController.clear(); + Navigator.of(context).pop(); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Settings restored'), + ), + ); + } else { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Invalid backup'), + ), + ); + } + }, + child: const Text('Restore'), + ), + ], + ); + } +} diff --git a/lib/settings/view/buttons.dart b/lib/settings/view/buttons.dart index 0dea11f..4a15b41 100644 --- a/lib/settings/view/buttons.dart +++ b/lib/settings/view/buttons.dart @@ -20,12 +20,16 @@ class OkButton extends StatelessWidget { class CancelButton extends StatelessWidget { const CancelButton({ super.key, + this.onPressed, }); + final void Function()? onPressed; + @override Widget build(BuildContext context) { return TextButton( onPressed: () { + onPressed?.call(); Navigator.of(context).pop(); }, child: const Text('Cancel'), diff --git a/lib/settings/view/theme_settings_page.dart b/lib/settings/view/theme_settings_page.dart new file mode 100644 index 0000000..0bb746b --- /dev/null +++ b/lib/settings/view/theme_settings_page.dart @@ -0,0 +1,261 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:flutter_settings_ui/flutter_settings_ui.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:vaani/settings/app_settings_provider.dart'; +import 'package:vaani/settings/view/buttons.dart'; +import 'package:vaani/settings/view/simple_settings_page.dart'; +import 'package:vaani/shared/extensions/enum.dart'; + +class ThemeSettingsPage extends HookConsumerWidget { + const ThemeSettingsPage({ + super.key, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final appSettings = ref.watch(appSettingsProvider); + final themeSettings = appSettings.themeSettings; + final primaryColor = Theme.of(context).colorScheme.primary; + + return SimpleSettingsPage( + title: const Text('Theme Settings'), + sections: [ + SettingsSection( + margin: const EdgeInsetsDirectional.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + tiles: [ + // choose system , light or dark theme + SettingsTile.navigation( + title: const Text('Theme Mode'), + description: Text.rich( + TextSpan( + text: themeSettings.themeMode == ThemeMode.system + ? 'Using mode from ' + : 'Using ', + children: [ + TextSpan( + text: themeSettings.themeMode.pascalCase, + style: TextStyle( + color: primaryColor, + ), + ), + if (themeSettings.themeMode != ThemeMode.system) + const TextSpan(text: ' mode'), + ], + ), + ), + leading: const Icon(Icons.color_lens), + trailing: themeSettings.themeMode == ThemeMode.system + ? const Icon(Icons.auto_awesome) + : themeSettings.themeMode == ThemeMode.light + ? const Icon(Icons.light_mode) + : const Icon(Icons.dark_mode), + onPressed: (context) async { + final themeMode = await showDialog( + context: context, + builder: (context) { + return ModeSelectionDialog( + themeMode: themeSettings.themeMode, + ); + }, + ); + if (themeMode != null) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.themeSettings( + themeMode: themeMode, + ), + ); + } + }, + ), + + // high contrast mode + SettingsTile.switchTile( + leading: themeSettings.highContrast + ? const Icon(Icons.accessibility) + : const Icon(Icons.accessibility_new_outlined), + initialValue: themeSettings.highContrast, + title: const Text('High Contrast Mode'), + description: const Text( + 'Increase the contrast between the background and the text', + ), + onToggle: (value) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.themeSettings( + highContrast: value, + ), + ); + }, + ), + + // use material theme from system + SettingsTile.switchTile( + initialValue: themeSettings.useMaterialThemeFromSystem, + title: Platform.isAndroid + ? const Text('Use Material You') + : const Text('Material Theme from System'), + description: const Text( + 'Use the system theme colors for the app', + ), + leading: themeSettings.useMaterialThemeFromSystem + ? const Icon(Icons.auto_awesome) + : const Icon(Icons.auto_fix_off), + onToggle: (value) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.themeSettings( + useMaterialThemeFromSystem: value, + ), + ); + }, + ), + + // TODO choose the primary color + // SettingsTile.navigation( + // title: const Text('Primary Color'), + // description: const Text( + // 'Choose the primary color for the app', + // ), + // leading: const Icon(Icons.colorize), + // trailing: Icon( + // Icons.circle, + // color: themeSettings.customThemeColor.toColor(), + // ), + // onPressed: (context) async { + // final selectedColor = await showDialog( + // context: context, + // builder: (context) { + // return SimpleDialog( + // title: const Text('Select Primary Color'), + // children: [ + // for (final color in Colors.primaries) + // SimpleDialogOption( + // onPressed: () { + // Navigator.pop(context, color); + // }, + // child: Container( + // color: color, + // height: 48, + // ), + // ), + // ], + // ); + // }, + // ); + // if (selectedColor != null) { + // ref.read(appSettingsProvider.notifier).update( + // appSettings.copyWith.themeSettings( + // customThemeColor: selectedColor.toHexString(), + // ), + // ); + // } + // }, + // ), + + // use theme throughout the app when playing item + SettingsTile.switchTile( + initialValue: themeSettings.useCurrentPlayerThemeThroughoutApp, + title: const Text('Adapt theme from currently playing item'), + description: const Text( + 'Use the theme colors from the currently playing item for the app', + ), + leading: themeSettings.useCurrentPlayerThemeThroughoutApp + ? const Icon(Icons.auto_fix_high) + : const Icon(Icons.auto_fix_off), + onToggle: (value) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.themeSettings( + useCurrentPlayerThemeThroughoutApp: value, + ), + ); + }, + ), + + SettingsTile.switchTile( + initialValue: themeSettings.useMaterialThemeOnItemPage, + title: const Text('Adaptive Theme on Item Page'), + description: const Text( + 'get fancy with the colors on the item page at the cost of some performance', + ), + leading: themeSettings.useMaterialThemeOnItemPage + ? const Icon(Icons.auto_fix_high) + : const Icon(Icons.auto_fix_off), + onToggle: (value) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.themeSettings( + useMaterialThemeOnItemPage: value, + ), + ); + }, + ), + ], + ), + ], + ); + } +} + +extension ColorExtension on Color { + String toHexString() { + return '#${value.toRadixString(16).substring(2)}'; + } +} + +extension StringExtension on String { + Color toColor() { + return Color(int.parse('0xff$substring(1)')); + } +} + +class ModeSelectionDialog extends HookConsumerWidget { + final ThemeMode themeMode; + + const ModeSelectionDialog({ + super.key, + required this.themeMode, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final selectedTheme = useState(themeMode); + // a wrap of chips to show the available modes with icons + return AlertDialog( + title: const Text('Select Theme Mode'), + content: Wrap( + spacing: 8.0, + runSpacing: 8.0, + children: ThemeMode.values + .map( + (mode) => ChoiceChip( + avatar: switch (mode) { + ThemeMode.system => const Icon(Icons.auto_awesome), + ThemeMode.light => const Icon(Icons.light_mode), + ThemeMode.dark => const Icon(Icons.dark_mode), + }, + showCheckmark: false, + label: Text(mode.pascalCase), + selected: mode == selectedTheme.value, + onSelected: (selected) { + if (selected) { + selectedTheme.value = mode; + } + }, + ), + ) + .toList(), + ), + actions: [ + CancelButton(), + OkButton( + onPressed: () { + Navigator.pop(context, selectedTheme.value); + }, + ), + ], + ); + } +} diff --git a/lib/shared/widgets/shelves/book_shelf.dart b/lib/shared/widgets/shelves/book_shelf.dart index 692d3b3..db6c1b3 100644 --- a/lib/shared/widgets/shelves/book_shelf.dart +++ b/lib/shared/widgets/shelves/book_shelf.dart @@ -17,7 +17,7 @@ import 'package:vaani/router/router.dart'; import 'package:vaani/settings/app_settings_provider.dart'; import 'package:vaani/shared/extensions/model_conversions.dart'; import 'package:vaani/shared/widgets/shelves/home_shelf.dart'; -import 'package:vaani/theme/theme_from_cover_provider.dart'; +import 'package:vaani/theme/providers/theme_from_cover_provider.dart'; /// A shelf that displays books on the home page class BookHomeShelf extends HookConsumerWidget { diff --git a/lib/theme/dark.dart b/lib/theme/dark.dart deleted file mode 100644 index 5473632..0000000 --- a/lib/theme/dark.dart +++ /dev/null @@ -1,10 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:vaani/theme/theme.dart'; - -final ThemeData darkTheme = ThemeData( - brightness: Brightness.dark, - colorScheme: ColorScheme.fromSeed( - seedColor: brandColor, - brightness: Brightness.dark, - ), -); diff --git a/lib/theme/light.dart b/lib/theme/light.dart deleted file mode 100644 index aa6ba4d..0000000 --- a/lib/theme/light.dart +++ /dev/null @@ -1,10 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:vaani/theme/theme.dart'; - -final ThemeData lightTheme = ThemeData( - brightness: Brightness.light, - colorScheme: ColorScheme.fromSeed( - seedColor: brandColor, - brightness: Brightness.light, - ), -); diff --git a/lib/theme/providers/system_theme_provider.dart b/lib/theme/providers/system_theme_provider.dart new file mode 100644 index 0000000..a38b9c6 --- /dev/null +++ b/lib/theme/providers/system_theme_provider.dart @@ -0,0 +1,73 @@ +import 'package:dynamic_color/dynamic_color.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:logging/logging.dart'; +import 'package:material_color_utilities/material_color_utilities.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'system_theme_provider.g.dart'; + +final _logger = Logger('SystemThemeProvider'); + +/// copied from [DynamicColorBuilder] +@Riverpod(keepAlive: true) +FutureOr<(ColorScheme light, ColorScheme dark)?> systemTheme( + SystemThemeRef ref, { + bool highContrast = false, +}) async { + _logger.fine('Generating system theme'); + ColorScheme? schemeLight; + ColorScheme? schemeDark; + // Platform messages may fail, so we use a try/catch PlatformException. + try { + CorePalette? corePalette = await DynamicColorPlugin.getCorePalette(); + + if (corePalette != null) { + _logger.fine('dynamic_color: Core palette detected.'); + schemeLight = corePalette.toColorScheme(brightness: Brightness.light); + schemeDark = corePalette.toColorScheme(brightness: Brightness.dark); + } + } on PlatformException { + _logger.warning('dynamic_color: Failed to obtain core palette.'); + } + + if (schemeLight == null || schemeDark == null) { + try { + final Color? accentColor = await DynamicColorPlugin.getAccentColor(); + + if (accentColor != null) { + _logger.fine('dynamic_color: Accent color detected.'); + schemeLight = ColorScheme.fromSeed( + seedColor: accentColor, + brightness: Brightness.light, + ); + schemeDark = ColorScheme.fromSeed( + seedColor: accentColor, + brightness: Brightness.dark, + ); + } + } on PlatformException { + _logger.warning('dynamic_color: Failed to obtain accent color.'); + } + } + + if (schemeLight == null || schemeDark == null) { + _logger + .warning('dynamic_color: Dynamic color not detected on this device.'); + return null; + } + // set high contrast theme + if (highContrast) { + schemeLight = schemeLight + .copyWith( + surface: Colors.white, + ) + .harmonized(); + schemeDark = schemeDark + .copyWith( + surface: Colors.black, + ) + .harmonized(); + } + return (schemeLight, schemeDark); +} diff --git a/lib/theme/providers/system_theme_provider.g.dart b/lib/theme/providers/system_theme_provider.g.dart new file mode 100644 index 0000000..1b4b8db --- /dev/null +++ b/lib/theme/providers/system_theme_provider.g.dart @@ -0,0 +1,177 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'system_theme_provider.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$systemThemeHash() => r'0af4a012a2a2b2fa91642a1313515cba02cd3535'; + +/// 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)); + } +} + +/// copied from [DynamicColorBuilder] +/// +/// Copied from [systemTheme]. +@ProviderFor(systemTheme) +const systemThemeProvider = SystemThemeFamily(); + +/// copied from [DynamicColorBuilder] +/// +/// Copied from [systemTheme]. +class SystemThemeFamily + extends Family> { + /// copied from [DynamicColorBuilder] + /// + /// Copied from [systemTheme]. + const SystemThemeFamily(); + + /// copied from [DynamicColorBuilder] + /// + /// Copied from [systemTheme]. + SystemThemeProvider call({ + bool highContrast = false, + }) { + return SystemThemeProvider( + highContrast: highContrast, + ); + } + + @override + SystemThemeProvider getProviderOverride( + covariant SystemThemeProvider provider, + ) { + return call( + highContrast: provider.highContrast, + ); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'systemThemeProvider'; +} + +/// copied from [DynamicColorBuilder] +/// +/// Copied from [systemTheme]. +class SystemThemeProvider + extends FutureProvider<(ColorScheme light, ColorScheme dark)?> { + /// copied from [DynamicColorBuilder] + /// + /// Copied from [systemTheme]. + SystemThemeProvider({ + bool highContrast = false, + }) : this._internal( + (ref) => systemTheme( + ref as SystemThemeRef, + highContrast: highContrast, + ), + from: systemThemeProvider, + name: r'systemThemeProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$systemThemeHash, + dependencies: SystemThemeFamily._dependencies, + allTransitiveDependencies: + SystemThemeFamily._allTransitiveDependencies, + highContrast: highContrast, + ); + + SystemThemeProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.highContrast, + }) : super.internal(); + + final bool highContrast; + + @override + Override overrideWith( + FutureOr<(ColorScheme light, ColorScheme dark)?> Function( + SystemThemeRef provider) + create, + ) { + return ProviderOverride( + origin: this, + override: SystemThemeProvider._internal( + (ref) => create(ref as SystemThemeRef), + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + highContrast: highContrast, + ), + ); + } + + @override + FutureProviderElement<(ColorScheme light, ColorScheme dark)?> + createElement() { + return _SystemThemeProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is SystemThemeProvider && other.highContrast == highContrast; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, highContrast.hashCode); + + return _SystemHash.finish(hash); + } +} + +mixin SystemThemeRef + on FutureProviderRef<(ColorScheme light, ColorScheme dark)?> { + /// The parameter `highContrast` of this provider. + bool get highContrast; +} + +class _SystemThemeProviderElement + extends FutureProviderElement<(ColorScheme light, ColorScheme dark)?> + with SystemThemeRef { + _SystemThemeProviderElement(super.provider); + + @override + bool get highContrast => (origin as SystemThemeProvider).highContrast; +} +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/theme/theme_from_cover_provider.dart b/lib/theme/providers/theme_from_cover_provider.dart similarity index 81% rename from lib/theme/theme_from_cover_provider.dart rename to lib/theme/providers/theme_from_cover_provider.dart index a535f2f..a61a381 100644 --- a/lib/theme/theme_from_cover_provider.dart +++ b/lib/theme/providers/theme_from_cover_provider.dart @@ -1,3 +1,4 @@ +import 'package:dynamic_color/dynamic_color.dart'; import 'package:flutter/material.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:logging/logging.dart'; @@ -13,15 +14,25 @@ Future> themeFromCover( ThemeFromCoverRef ref, ImageProvider img, { Brightness brightness = Brightness.dark, + bool highContrast = false, }) async { // ! add deliberate delay to simulate a long running task as it interferes with other animations await Future.delayed(500.ms); _logger.fine('Generating color scheme from cover image'); - return ColorScheme.fromImageProvider( + var theme = await ColorScheme.fromImageProvider( provider: img, brightness: brightness, ); + // set high contrast theme + if (highContrast) { + theme = theme + .copyWith( + surface: brightness == Brightness.light ? Colors.white : Colors.black, + ) + .harmonized(); + } + return theme; // TODO isolate is not working // see https://github.com/flutter/flutter/issues/119207 // use isolate to generate the color scheme @@ -50,14 +61,18 @@ FutureOr themeOfLibraryItem( ThemeOfLibraryItemRef ref, String? itemId, { Brightness brightness = Brightness.dark, + bool highContrast = false, }) async { if (itemId == null) { return null; } final coverImage = await ref.watch(coverImageProvider(itemId).future); final val = await ref.watch( - themeFromCoverProvider(MemoryImage(coverImage), brightness: brightness) - .future, + themeFromCoverProvider( + MemoryImage(coverImage), + brightness: brightness, + highContrast: highContrast, + ).future, ); return val; // coverImage.when( diff --git a/lib/theme/theme_from_cover_provider.g.dart b/lib/theme/providers/theme_from_cover_provider.g.dart similarity index 86% rename from lib/theme/theme_from_cover_provider.g.dart rename to lib/theme/providers/theme_from_cover_provider.g.dart index 61a86a9..07b5790 100644 --- a/lib/theme/theme_from_cover_provider.g.dart +++ b/lib/theme/providers/theme_from_cover_provider.g.dart @@ -6,7 +6,7 @@ part of 'theme_from_cover_provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$themeFromCoverHash() => r'a549513a0dcdff76be94488baf38a8b886ce63eb'; +String _$themeFromCoverHash() => r'f656614e2d4851acdfa16d249b3198ae0e1d6d6f'; /// Copied from Dart SDK class _SystemHash { @@ -42,10 +42,12 @@ class ThemeFromCoverFamily extends Family>> { ThemeFromCoverProvider call( ImageProvider img, { Brightness brightness = Brightness.dark, + bool highContrast = false, }) { return ThemeFromCoverProvider( img, brightness: brightness, + highContrast: highContrast, ); } @@ -56,6 +58,7 @@ class ThemeFromCoverFamily extends Family>> { return call( provider.img, brightness: provider.brightness, + highContrast: provider.highContrast, ); } @@ -80,11 +83,13 @@ class ThemeFromCoverProvider extends FutureProvider> { ThemeFromCoverProvider( ImageProvider img, { Brightness brightness = Brightness.dark, + bool highContrast = false, }) : this._internal( (ref) => themeFromCover( ref as ThemeFromCoverRef, img, brightness: brightness, + highContrast: highContrast, ), from: themeFromCoverProvider, name: r'themeFromCoverProvider', @@ -97,6 +102,7 @@ class ThemeFromCoverProvider extends FutureProvider> { ThemeFromCoverFamily._allTransitiveDependencies, img: img, brightness: brightness, + highContrast: highContrast, ); ThemeFromCoverProvider._internal( @@ -108,10 +114,12 @@ class ThemeFromCoverProvider extends FutureProvider> { required super.from, required this.img, required this.brightness, + required this.highContrast, }) : super.internal(); final ImageProvider img; final Brightness brightness; + final bool highContrast; @override Override overrideWith( @@ -129,6 +137,7 @@ class ThemeFromCoverProvider extends FutureProvider> { debugGetCreateSourceHash: null, img: img, brightness: brightness, + highContrast: highContrast, ), ); } @@ -142,7 +151,8 @@ class ThemeFromCoverProvider extends FutureProvider> { bool operator ==(Object other) { return other is ThemeFromCoverProvider && other.img == img && - other.brightness == brightness; + other.brightness == brightness && + other.highContrast == highContrast; } @override @@ -150,6 +160,7 @@ class ThemeFromCoverProvider extends FutureProvider> { var hash = _SystemHash.combine(0, runtimeType.hashCode); hash = _SystemHash.combine(hash, img.hashCode); hash = _SystemHash.combine(hash, brightness.hashCode); + hash = _SystemHash.combine(hash, highContrast.hashCode); return _SystemHash.finish(hash); } @@ -161,6 +172,9 @@ mixin ThemeFromCoverRef on FutureProviderRef> { /// The parameter `brightness` of this provider. Brightness get brightness; + + /// The parameter `highContrast` of this provider. + bool get highContrast; } class _ThemeFromCoverProviderElement @@ -172,10 +186,12 @@ class _ThemeFromCoverProviderElement ImageProvider get img => (origin as ThemeFromCoverProvider).img; @override Brightness get brightness => (origin as ThemeFromCoverProvider).brightness; + @override + bool get highContrast => (origin as ThemeFromCoverProvider).highContrast; } String _$themeOfLibraryItemHash() => - r'a1d0e5d81f4debe88d5a6ce46c3af28623ad4273'; + r'b2677daf31a6a53f3f237e5204c62dff5ec43171'; /// See also [themeOfLibraryItem]. @ProviderFor(themeOfLibraryItem) @@ -190,10 +206,12 @@ class ThemeOfLibraryItemFamily extends Family> { ThemeOfLibraryItemProvider call( String? itemId, { Brightness brightness = Brightness.dark, + bool highContrast = false, }) { return ThemeOfLibraryItemProvider( itemId, brightness: brightness, + highContrast: highContrast, ); } @@ -204,6 +222,7 @@ class ThemeOfLibraryItemFamily extends Family> { return call( provider.itemId, brightness: provider.brightness, + highContrast: provider.highContrast, ); } @@ -228,11 +247,13 @@ class ThemeOfLibraryItemProvider extends FutureProvider { ThemeOfLibraryItemProvider( String? itemId, { Brightness brightness = Brightness.dark, + bool highContrast = false, }) : this._internal( (ref) => themeOfLibraryItem( ref as ThemeOfLibraryItemRef, itemId, brightness: brightness, + highContrast: highContrast, ), from: themeOfLibraryItemProvider, name: r'themeOfLibraryItemProvider', @@ -245,6 +266,7 @@ class ThemeOfLibraryItemProvider extends FutureProvider { ThemeOfLibraryItemFamily._allTransitiveDependencies, itemId: itemId, brightness: brightness, + highContrast: highContrast, ); ThemeOfLibraryItemProvider._internal( @@ -256,10 +278,12 @@ class ThemeOfLibraryItemProvider extends FutureProvider { required super.from, required this.itemId, required this.brightness, + required this.highContrast, }) : super.internal(); final String? itemId; final Brightness brightness; + final bool highContrast; @override Override overrideWith( @@ -276,6 +300,7 @@ class ThemeOfLibraryItemProvider extends FutureProvider { debugGetCreateSourceHash: null, itemId: itemId, brightness: brightness, + highContrast: highContrast, ), ); } @@ -289,7 +314,8 @@ class ThemeOfLibraryItemProvider extends FutureProvider { bool operator ==(Object other) { return other is ThemeOfLibraryItemProvider && other.itemId == itemId && - other.brightness == brightness; + other.brightness == brightness && + other.highContrast == highContrast; } @override @@ -297,6 +323,7 @@ class ThemeOfLibraryItemProvider extends FutureProvider { var hash = _SystemHash.combine(0, runtimeType.hashCode); hash = _SystemHash.combine(hash, itemId.hashCode); hash = _SystemHash.combine(hash, brightness.hashCode); + hash = _SystemHash.combine(hash, highContrast.hashCode); return _SystemHash.finish(hash); } @@ -308,6 +335,9 @@ mixin ThemeOfLibraryItemRef on FutureProviderRef { /// The parameter `brightness` of this provider. Brightness get brightness; + + /// The parameter `highContrast` of this provider. + bool get highContrast; } class _ThemeOfLibraryItemProviderElement @@ -319,6 +349,8 @@ class _ThemeOfLibraryItemProviderElement @override Brightness get brightness => (origin as ThemeOfLibraryItemProvider).brightness; + @override + bool get highContrast => (origin as ThemeOfLibraryItemProvider).highContrast; } // ignore_for_file: type=lint // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/theme/theme.dart b/lib/theme/theme.dart index 72e81b1..35f4ad8 100644 --- a/lib/theme/theme.dart +++ b/lib/theme/theme.dart @@ -1,9 +1,15 @@ -import 'dart:ui'; - -export 'dark.dart'; -export 'light.dart'; - +import 'package:flutter/material.dart'; // brand color rgb(49, 27, 146) rgb(96, 76, 236) const brandColor = Color(0xFF311B92); const brandColorLight = Color(0xFF604CEC); + +final brandLightColorScheme = ColorScheme.fromSeed( + seedColor: brandColor, + brightness: Brightness.light, +); + +final brandDarkColorScheme = ColorScheme.fromSeed( + seedColor: brandColor, + brightness: Brightness.dark, +); diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 879195f..606c5a6 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,11 +6,15 @@ #include "generated_plugin_registrant.h" +#include #include #include #include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) dynamic_color_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin"); + dynamic_color_plugin_register_with_registrar(dynamic_color_registrar); g_autoptr(FlPluginRegistrar) isar_flutter_libs_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "IsarFlutterLibsPlugin"); isar_flutter_libs_plugin_register_with_registrar(isar_flutter_libs_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 026cbff..6023074 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + dynamic_color isar_flutter_libs media_kit_libs_linux url_launcher_linux diff --git a/pubspec.lock b/pubspec.lock index 670cc8f..a6ff204 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -390,6 +390,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + dynamic_color: + dependency: "direct main" + description: + name: dynamic_color + sha256: eae98052fa6e2826bdac3dd2e921c6ce2903be15c6b7f8b6d8a5d49b5086298d + url: "https://pub.dev" + source: hosted + version: "1.7.0" easy_stepper: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 1b4fb1c..6366275 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -44,6 +44,7 @@ dependencies: cupertino_icons: ^1.0.6 device_info_plus: ^10.1.0 duration_picker: ^1.2.0 + dynamic_color: ^1.7.0 easy_stepper: ^0.8.4 file_picker: ^8.1.2 flutter: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index d043b0b..de21556 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,6 +6,7 @@ #include "generated_plugin_registrant.h" +#include #include #include #include @@ -13,6 +14,8 @@ #include void RegisterPlugins(flutter::PluginRegistry* registry) { + DynamicColorPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("DynamicColorPluginCApi")); IsarFlutterLibsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("IsarFlutterLibsPlugin")); MediaKitLibsWindowsAudioPluginCApiRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 9839b50..13d504d 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + dynamic_color isar_flutter_libs media_kit_libs_windows_audio permission_handler_windows From e7205ed874d98e0e9914523a10d6bcbb1e6ee2e9 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Sat, 5 Oct 2024 10:05:26 -0400 Subject: [PATCH 46/92] chore: bump version to 0.0.13+4 in pubspec.yaml --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 6366275..9e37321 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.0.12+3 +version: 0.0.13+4 environment: sdk: ">=3.3.4 <4.0.0" From 747dbdb46f442cc2252aac1538f999f504a78c66 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Sat, 5 Oct 2024 21:02:14 -0400 Subject: [PATCH 47/92] fix: bad state when reading player for theme and new login --- lib/main.dart | 47 ++++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 0da35ae..6020a6a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -83,26 +83,32 @@ class MyApp extends ConsumerWidget { } if (themeSettings.useCurrentPlayerThemeThroughoutApp) { - final player = ref.watch(audiobookPlayerProvider); - if (player.book != null) { - final themeLight = ref.watch( - themeOfLibraryItemProvider( - player.book!.libraryItemId, - highContrast: shouldUseHighContrast, - brightness: Brightness.light, - ), - ); - final themeDark = ref.watch( - themeOfLibraryItemProvider( - player.book!.libraryItemId, - highContrast: shouldUseHighContrast, - brightness: Brightness.dark, - ), - ); - if (themeLight.valueOrNull != null && themeDark.valueOrNull != null) { - lightColorScheme = themeLight.valueOrNull!; - darkColorScheme = themeDark.valueOrNull!; + try { + final player = ref.watch(audiobookPlayerProvider); + if (player.book != null) { + final themeLight = ref.watch( + themeOfLibraryItemProvider( + player.book!.libraryItemId, + highContrast: shouldUseHighContrast, + brightness: Brightness.light, + ), + ); + final themeDark = ref.watch( + themeOfLibraryItemProvider( + player.book!.libraryItemId, + highContrast: shouldUseHighContrast, + brightness: Brightness.dark, + ), + ); + if (themeLight.valueOrNull != null && themeDark.valueOrNull != null) { + lightColorScheme = themeLight.valueOrNull!; + darkColorScheme = themeDark.valueOrNull!; + } } + } catch (e) { + debugPrintStack(stackTrace: StackTrace.current, label: e.toString()); + appLogger.severe('not building with player theme'); + appLogger.severe(e.toString()); } } final appThemeLight = ThemeData( @@ -129,6 +135,8 @@ class MyApp extends ConsumerWidget { ); } catch (e) { debugPrintStack(stackTrace: StackTrace.current, label: e.toString()); + appLogger.severe(e.toString()); + if (needOnboarding) { routerConfig.goNamed(Routes.onboarding.name); } @@ -155,6 +163,7 @@ class _EagerInitialization extends ConsumerWidget { ref.watch(shakeDetectorProvider); } catch (e) { debugPrintStack(stackTrace: StackTrace.current, label: e.toString()); + appLogger.severe(e.toString()); } return child; From e8903081b7b4a08cd9538c32a8e83eed76ae87ba Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Sun, 6 Oct 2024 03:02:44 -0400 Subject: [PATCH 48/92] chore: bump version to 0.0.14+5 in pubspec.yaml --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 9e37321..af06e50 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.0.13+4 +version: 0.0.14+5 environment: sdk: ">=3.3.4 <4.0.0" From 09eafb2c280f9d9da2c3c0e999ecc400da679c40 Mon Sep 17 00:00:00 2001 From: "Dr.Blank" Date: Sun, 6 Oct 2024 05:45:14 -0400 Subject: [PATCH 49/92] fix: content behind miniplayer not visible (#53) --- .../item_viewer/view/library_item_page.dart | 6 ++---- lib/features/player/providers/player_form.dart | 18 ++++++++++++++++++ .../player/providers/player_form.g.dart | 15 +++++++++++++++ .../view/mini_player_bottom_padding.dart | 16 ++++++++++++++++ lib/features/you/view/server_manager.dart | 4 ++++ lib/features/you/view/you_page.dart | 2 ++ lib/settings/view/simple_settings_page.dart | 2 ++ 7 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 lib/features/player/view/mini_player_bottom_padding.dart diff --git a/lib/features/item_viewer/view/library_item_page.dart b/lib/features/item_viewer/view/library_item_page.dart index 9e98003..53db17e 100644 --- a/lib/features/item_viewer/view/library_item_page.dart +++ b/lib/features/item_viewer/view/library_item_page.dart @@ -6,7 +6,7 @@ import 'package:flutter_animate/flutter_animate.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:vaani/api/library_item_provider.dart'; import 'package:vaani/features/item_viewer/view/library_item_sliver_app_bar.dart'; -import 'package:vaani/features/player/providers/player_form.dart'; +import 'package:vaani/features/player/view/mini_player_bottom_padding.dart'; import 'package:vaani/router/models/library_item_extras.dart'; import 'package:vaani/shared/widgets/expandable_description.dart'; @@ -56,9 +56,7 @@ class LibraryItemPage extends HookConsumerWidget { child: LibraryItemDescription(id: itemId), ), // a padding at the bottom to make sure the last item is not hidden by mini player - const SliverToBoxAdapter( - child: SizedBox(height: playerMinHeight), - ), + const SliverToBoxAdapter(child: MiniPlayerBottomPadding()), ], ), ), diff --git a/lib/features/player/providers/player_form.dart b/lib/features/player/providers/player_form.dart index 975f47f..b4e2f2e 100644 --- a/lib/features/player/providers/player_form.dart +++ b/lib/features/player/providers/player_form.dart @@ -6,6 +6,7 @@ import 'package:flutter/widgets.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:miniplayer/miniplayer.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:vaani/features/player/providers/audiobook_player.dart'; part 'player_form.g.dart'; @@ -60,3 +61,20 @@ double playerHeight( } final audioBookMiniplayerController = MiniplayerController(); + +@Riverpod(keepAlive: true) +bool isPlayerActive( + IsPlayerActiveRef ref, +) { + try { + final player = ref.watch(audiobookPlayerProvider); + if (player.book != null) { + return true; + } else { + final playerHeight = ref.watch(playerHeightProvider); + return playerHeight < playerMinHeight; + } + } catch (e) { + return false; + } +} diff --git a/lib/features/player/providers/player_form.g.dart b/lib/features/player/providers/player_form.g.dart index b3b73d9..5e8d071 100644 --- a/lib/features/player/providers/player_form.g.dart +++ b/lib/features/player/providers/player_form.g.dart @@ -38,5 +38,20 @@ final playerHeightProvider = Provider.internal( ); typedef PlayerHeightRef = ProviderRef; +String _$isPlayerActiveHash() => r'147e13cd7fd6fd3823623557ce4f300dc15b6fe6'; + +/// See also [isPlayerActive]. +@ProviderFor(isPlayerActive) +final isPlayerActiveProvider = Provider.internal( + isPlayerActive, + name: r'isPlayerActiveProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$isPlayerActiveHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef IsPlayerActiveRef = ProviderRef; // ignore_for_file: type=lint // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/features/player/view/mini_player_bottom_padding.dart b/lib/features/player/view/mini_player_bottom_padding.dart new file mode 100644 index 0000000..c403361 --- /dev/null +++ b/lib/features/player/view/mini_player_bottom_padding.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:vaani/features/player/providers/player_form.dart'; + +class MiniPlayerBottomPadding extends HookConsumerWidget { + const MiniPlayerBottomPadding({super.key}); + @override + Widget build(BuildContext context, WidgetRef ref) { + return AnimatedSize( + duration: const Duration(milliseconds: 200), + child: ref.watch(isPlayerActiveProvider) + ? const SizedBox(height: playerMinHeight + 8) + : const SizedBox.shrink(), + ); + } +} diff --git a/lib/features/you/view/server_manager.dart b/lib/features/you/view/server_manager.dart index 8a385f2..6d198a4 100644 --- a/lib/features/you/view/server_manager.dart +++ b/lib/features/you/view/server_manager.dart @@ -5,6 +5,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:vaani/api/api_provider.dart'; import 'package:vaani/api/authenticated_user_provider.dart'; import 'package:vaani/api/server_provider.dart'; +import 'package:vaani/features/player/view/mini_player_bottom_padding.dart'; import 'package:vaani/main.dart'; import 'package:vaani/models/error_response.dart'; import 'package:vaani/router/router.dart'; @@ -260,6 +261,9 @@ class ServerManagerPage extends HookConsumerWidget { }, ), ), + + MiniPlayerBottomPadding(), + ], ), ), diff --git a/lib/features/you/view/you_page.dart b/lib/features/you/view/you_page.dart index 11fa89d..c15e80f 100644 --- a/lib/features/you/view/you_page.dart +++ b/lib/features/you/view/you_page.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:vaani/api/api_provider.dart'; +import 'package:vaani/features/player/view/mini_player_bottom_padding.dart'; import 'package:vaani/router/router.dart'; import 'package:vaani/settings/constants.dart'; import 'package:vaani/shared/utils.dart'; @@ -136,6 +137,7 @@ class YouPage extends HookConsumerWidget { ), ), ), + SliverToBoxAdapter(child: MiniPlayerBottomPadding()), ], ), ); diff --git a/lib/settings/view/simple_settings_page.dart b/lib/settings/view/simple_settings_page.dart index 471b022..ea9107d 100644 --- a/lib/settings/view/simple_settings_page.dart +++ b/lib/settings/view/simple_settings_page.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_settings_ui/flutter_settings_ui.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:vaani/features/player/view/mini_player_bottom_padding.dart'; class SimpleSettingsPage extends HookConsumerWidget { const SimpleSettingsPage({ @@ -48,6 +49,7 @@ class SimpleSettingsPage extends HookConsumerWidget { ), // some padding at the bottom const SliverPadding(padding: EdgeInsets.only(bottom: 20)), + SliverToBoxAdapter(child: MiniPlayerBottomPadding()), ], ), ); From 5b896e8b09969dfe717252e3b638ca300455b3de Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Sun, 6 Oct 2024 05:52:29 -0400 Subject: [PATCH 50/92] refactor: fade in images on home screen --- lib/shared/widgets/shelves/book_shelf.dart | 65 +++++++++++----------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/lib/shared/widgets/shelves/book_shelf.dart b/lib/shared/widgets/shelves/book_shelf.dart index db6c1b3..4d23237 100644 --- a/lib/shared/widgets/shelves/book_shelf.dart +++ b/lib/shared/widgets/shelves/book_shelf.dart @@ -114,38 +114,41 @@ class BookOnShelf extends HookConsumerWidget { heroTagSuffix, child: ClipRRect( borderRadius: BorderRadius.circular(10), - child: coverImage.when( - data: (image) { - // return const BookCoverSkeleton(); - if (image.isEmpty) { + child: AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + child: coverImage.when( + data: (image) { + // return const BookCoverSkeleton(); + if (image.isEmpty) { + return const Icon(Icons.error); + } + var imageWidget = Image.memory( + image, + fit: BoxFit.fill, + cacheWidth: (height * + 1.2 * + MediaQuery.of(context) + .devicePixelRatio) + .round(), + ); + return Container( + decoration: BoxDecoration( + color: Theme.of(context) + .colorScheme + .onPrimaryContainer, + ), + child: imageWidget, + ); + }, + loading: () { + return const Center( + child: BookCoverSkeleton(), + ); + }, + error: (error, stack) { return const Icon(Icons.error); - } - var imageWidget = Image.memory( - image, - fit: BoxFit.fill, - cacheWidth: (height * - 1.2 * - MediaQuery.of(context) - .devicePixelRatio) - .round(), - ); - return Container( - decoration: BoxDecoration( - color: Theme.of(context) - .colorScheme - .onPrimaryContainer, - ), - child: imageWidget, - ); - }, - loading: () { - return const Center( - child: BookCoverSkeleton(), - ); - }, - error: (error, stack) { - return const Icon(Icons.error); - }, + }, + ), ), ), ), From 781e266a5fab08df82a4cbfe1872bcb7f7fb015a Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Mon, 7 Oct 2024 14:28:51 -0400 Subject: [PATCH 51/92] docs: update README for clearer instructions on joining Playstore testing --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c50a48f..0df2e00 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,12 @@ Client for [Audiobookshelf](https://github.com/advplyr/audiobookshelf) server ma Playstore App is in closed testing. To join testing 1. [Join the Google Group](https://groups.google.com/g/vaani-app) -2. [Join on Android](https://play.google.com/store/apps/details?id=dr.blank.vaani) Or [Join on Web](https://play.google.com/apps/testing/dr.blank.vaani) +2. [Join on Web](https://play.google.com/apps/testing/dr.blank.vaani) (preferred) or [Join on Android](https://play.google.com/store/apps/details?id=dr.blank.vaani) by becoming a tester. + - Make sure it is the same account as the one you joined group. +3. Send me an email on drblankdev@gmail.com asking for a promo code. + - I only have limited codes, so first come first serve. +4. Redeem the code on Playstore and install the app. + ## Screencaps From 630219dfbe8b27c37a394150655da0e2791de99d Mon Sep 17 00:00:00 2001 From: "Dr.Blank" Date: Fri, 11 Oct 2024 11:25:41 -0400 Subject: [PATCH 52/92] fix: disable dependency metadata in APKs and App Bundles (#57) --- android/app/build.gradle | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/android/app/build.gradle b/android/app/build.gradle index b13356f..b53ca6d 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -46,6 +46,15 @@ android { main.java.srcDirs += 'src/main/kotlin' } + // see: https://gitlab.com/IzzyOnDroid/repo/-/issues/623#note_2149548690 + // https://android.izzysoft.de/articles/named/iod-scan-apkchecks#blobs + dependenciesInfo { + // Disables dependency metadata when building APKs. + includeInApk = false + // Disables dependency metadata when building Android App Bundles. + includeInBundle = false + } + defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "dr.blank.vaani" From 11b768d41cc4b253e76a367fc8f41cca16ea835b Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Fri, 11 Oct 2024 12:01:14 -0400 Subject: [PATCH 53/92] chore: bump version to 0.0.15+6 in pubspec.yaml --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index af06e50..9a38a3e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.0.14+5 +version: 0.0.15+6 environment: sdk: ">=3.3.4 <4.0.0" From 3488ae97fbbb8f43d97df7d29092eeeaaffa646c Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Mon, 28 Oct 2024 05:45:28 +0530 Subject: [PATCH 54/92] fix overflow error for onboarding --- .../view/onboarding_single_page.dart | 100 +++++++++--------- 1 file changed, 51 insertions(+), 49 deletions(-) diff --git a/lib/features/onboarding/view/onboarding_single_page.dart b/lib/features/onboarding/view/onboarding_single_page.dart index 79f0d63..bd69fb0 100644 --- a/lib/features/onboarding/view/onboarding_single_page.dart +++ b/lib/features/onboarding/view/onboarding_single_page.dart @@ -40,61 +40,63 @@ class OnboardingSinglePage extends HookConsumerWidget { } return Scaffold( - body: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - 'Welcome to Vaani', - style: Theme.of(context).textTheme.headlineSmall, + body: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + 'Welcome to Vaani', + style: Theme.of(context).textTheme.headlineSmall, + ), ), - ), - const SizedBox.square( - dimension: 16.0, - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: AnimatedSwitcher( + const SizedBox.square( + dimension: 16.0, + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: AnimatedSwitcher( + duration: 500.ms, + transitionBuilder: fadeSlideTransitionBuilder, + child: canUserLogin.value + ? Text( + 'Server connected, please login', + key: const ValueKey('connected'), + style: Theme.of(context).textTheme.bodyMedium, + ) + : Text( + 'Please enter the URL of your AudiobookShelf Server', + key: const ValueKey('not_connected'), + style: Theme.of(context).textTheme.bodyMedium, + ), + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: AddNewServer( + controller: serverUriController, + allowEmpty: true, + onPressed: () { + canUserLogin.value = serverUriController.text.isNotEmpty; + }, + ), + ), + AnimatedSwitcher( duration: 500.ms, transitionBuilder: fadeSlideTransitionBuilder, child: canUserLogin.value - ? Text( - 'Server connected, please login', - key: const ValueKey('connected'), - style: Theme.of(context).textTheme.bodyMedium, + ? UserLoginWidget( + server: audiobookshelfUri, ) - : Text( - 'Please enter the URL of your AudiobookShelf Server', - key: const ValueKey('not_connected'), - style: Theme.of(context).textTheme.bodyMedium, - ), + // ).animate().fade(duration: 600.ms).slideY(begin: 0.3, end: 0) + : const RedirectToABS().animate().fadeIn().slideY( + curve: Curves.easeInOut, + duration: 500.ms, + ), ), - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: AddNewServer( - controller: serverUriController, - allowEmpty: true, - onPressed: () { - canUserLogin.value = serverUriController.text.isNotEmpty; - }, - ), - ), - AnimatedSwitcher( - duration: 500.ms, - transitionBuilder: fadeSlideTransitionBuilder, - child: canUserLogin.value - ? UserLoginWidget( - server: audiobookshelfUri, - ) - // ).animate().fade(duration: 600.ms).slideY(begin: 0.3, end: 0) - : const RedirectToABS().animate().fadeIn().slideY( - curve: Curves.easeInOut, - duration: 500.ms, - ), - ), - ], + ], + ), ), ); } From c2cf999398b80004496aeef4bceaf60858b1596a Mon Sep 17 00:00:00 2001 From: "Dr.Blank" <64108942+Dr-Blank@users.noreply.github.com> Date: Sat, 7 Dec 2024 12:26:59 +0530 Subject: [PATCH 55/92] dart fix --- lib/features/item_viewer/view/library_item_actions.dart | 1 - .../item_viewer/view/library_item_hero_section.dart | 8 -------- lib/features/item_viewer/view/library_item_metadata.dart | 1 - lib/features/onboarding/view/callback_page.dart | 1 - lib/features/you/view/server_manager.dart | 1 - lib/shared/widgets/shelves/book_shelf.dart | 1 - 6 files changed, 13 deletions(-) diff --git a/lib/features/item_viewer/view/library_item_actions.dart b/lib/features/item_viewer/view/library_item_actions.dart index 1b1b5a8..fe5525f 100644 --- a/lib/features/item_viewer/view/library_item_actions.dart +++ b/lib/features/item_viewer/view/library_item_actions.dart @@ -425,7 +425,6 @@ class DownloadSheet extends HookConsumerWidget { class _LibraryItemPlayButton extends HookConsumerWidget { const _LibraryItemPlayButton({ - super.key, required this.item, }); diff --git a/lib/features/item_viewer/view/library_item_hero_section.dart b/lib/features/item_viewer/view/library_item_hero_section.dart index 856c5a5..45edc02 100644 --- a/lib/features/item_viewer/view/library_item_hero_section.dart +++ b/lib/features/item_viewer/view/library_item_hero_section.dart @@ -78,7 +78,6 @@ class LibraryItemHeroSection extends HookConsumerWidget { class _BookDetails extends HookConsumerWidget { const _BookDetails({ - super.key, required this.id, this.extraMap, }); @@ -136,7 +135,6 @@ class _BookDetails extends HookConsumerWidget { class _LibraryItemProgressIndicator extends HookConsumerWidget { const _LibraryItemProgressIndicator({ - super.key, required this.id, }); @@ -213,7 +211,6 @@ class _LibraryItemProgressIndicator extends HookConsumerWidget { class _HeroSectionSubLabelWithIcon extends HookConsumerWidget { const _HeroSectionSubLabelWithIcon({ - super.key, required this.icon, required this.text, }); @@ -260,7 +257,6 @@ class _HeroSectionSubLabelWithIcon extends HookConsumerWidget { class _BookSeries extends StatelessWidget { const _BookSeries({ - super.key, required this.itemBookMetadata, required this.bookDetailsCached, }); @@ -306,7 +302,6 @@ class _BookSeries extends StatelessWidget { class _BookNarrators extends StatelessWidget { const _BookNarrators({ - super.key, required this.itemBookMetadata, required this.bookDetailsCached, }); @@ -342,7 +337,6 @@ class _BookNarrators extends StatelessWidget { class _BookCover extends HookConsumerWidget { const _BookCover({ - super.key, required this.itemId, }); @@ -416,7 +410,6 @@ class _BookCover extends HookConsumerWidget { class _BookTitle extends StatelessWidget { const _BookTitle({ - super.key, required this.extraMap, required this.itemBookMetadata, }); @@ -461,7 +454,6 @@ class _BookTitle extends StatelessWidget { class _BookAuthors extends StatelessWidget { const _BookAuthors({ - super.key, required this.itemBookMetadata, required this.bookDetailsCached, }); diff --git a/lib/features/item_viewer/view/library_item_metadata.dart b/lib/features/item_viewer/view/library_item_metadata.dart index 5874a92..b08948e 100644 --- a/lib/features/item_viewer/view/library_item_metadata.dart +++ b/lib/features/item_viewer/view/library_item_metadata.dart @@ -109,7 +109,6 @@ class LibraryItemMetadata extends HookConsumerWidget { /// key-value pair to display as column class _MetadataItem extends StatelessWidget { const _MetadataItem({ - super.key, required this.title, required this.value, }); diff --git a/lib/features/onboarding/view/callback_page.dart b/lib/features/onboarding/view/callback_page.dart index dd3de86..f4bb098 100644 --- a/lib/features/onboarding/view/callback_page.dart +++ b/lib/features/onboarding/view/callback_page.dart @@ -98,7 +98,6 @@ class BackToLoginButton extends StatelessWidget { class _SomethingWentWrong extends StatelessWidget { const _SomethingWentWrong({ - super.key, this.message = 'Error with OAuth flow', }); diff --git a/lib/features/you/view/server_manager.dart b/lib/features/you/view/server_manager.dart index 6d198a4..43c8d24 100644 --- a/lib/features/you/view/server_manager.dart +++ b/lib/features/you/view/server_manager.dart @@ -274,7 +274,6 @@ class ServerManagerPage extends HookConsumerWidget { class _AddUserDialog extends HookConsumerWidget { const _AddUserDialog({ - super.key, required this.server, }); diff --git a/lib/shared/widgets/shelves/book_shelf.dart b/lib/shared/widgets/shelves/book_shelf.dart index 4d23237..1ef7089 100644 --- a/lib/shared/widgets/shelves/book_shelf.dart +++ b/lib/shared/widgets/shelves/book_shelf.dart @@ -200,7 +200,6 @@ class BookOnShelf extends HookConsumerWidget { class _BookOnShelfPlayButton extends HookConsumerWidget { const _BookOnShelfPlayButton({ - super.key, required this.libraryItemId, }); From 2a715f6fa8c5a08b4056b931bde9b3d43d9ab806 Mon Sep 17 00:00:00 2001 From: "Dr.Blank" <64108942+Dr-Blank@users.noreply.github.com> Date: Sat, 7 Dec 2024 21:07:48 +0530 Subject: [PATCH 56/92] remove manage external storage permission --- android/app/src/main/AndroidManifest.xml | 1 - lib/features/logging/view/logs_page.dart | 133 ++++++++++++----------- 2 files changed, 68 insertions(+), 66 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index f74b367..3856060 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -9,7 +9,6 @@ - 29) { - final status = await Permission.manageExternalStorage.status; - if (!status.isGranted) { - appLogger - .info('Requesting manageExternalStorage permission'); - final newStatus = - await Permission.manageExternalStorage.request(); - if (!newStatus.isGranted) { - appLogger - .warning('manageExternalStorage permission denied'); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Storage permission denied'), - ), - ); - return; - } - } - } else { - final status = await Permission.storage.status; - if (!status.isGranted) { - appLogger.info('Requesting storage permission'); - final newStatus = await Permission.storage.request(); - if (!newStatus.isGranted) { - appLogger.warning('Storage permission denied'); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Storage permission denied'), - ), - ); - return; - } - } - } - } - final zipLogFilePath = - await ref.read(logsProvider.notifier).getZipFilePath(); + // if (Platform.isAndroid) { + // final androidVersion = + // await ref.watch(deviceSdkVersionProvider.future); - // save to folder - String? outputFile = await FilePicker.platform.saveFile( - dialogTitle: 'Please select an output file:', - fileName: zipLogFilePath.split('/').last, - bytes: await File(zipLogFilePath).readAsBytes(), - ); - if (outputFile != null) { - try { - final file = File(outputFile); - final zipFile = File(zipLogFilePath); - await zipFile.copy(file.path); - appLogger.info('File saved to: $outputFile'); - } catch (e) { - appLogger.severe('Error saving file: $e'); - } - } else { - appLogger.info('Download cancelled'); - } - }, - ), + // if ((int.parse(androidVersion)) > 29) { + // final status = await Permission.storage.status; + // if (!status.isGranted) { + // appLogger + // .info('Requesting storage permission'); + // final newStatus = + // await Permission.storage.request(); + // if (!newStatus.isGranted) { + // appLogger + // .warning('storage permission denied'); + // ScaffoldMessenger.of(context).showSnackBar( + // const SnackBar( + // content: Text('Storage permission denied'), + // ), + // ); + // return; + // } + // } + // } else { + // final status = await Permission.storage.status; + // if (!status.isGranted) { + // appLogger.info('Requesting storage permission'); + // final newStatus = await Permission.storage.request(); + // if (!newStatus.isGranted) { + // appLogger.warning('Storage permission denied'); + // ScaffoldMessenger.of(context).showSnackBar( + // const SnackBar( + // content: Text('Storage permission denied'), + // ), + // ); + // return; + // } + // } + // } + // } + // final zipLogFilePath = + // await ref.read(logsProvider.notifier).getZipFilePath(); + + // // save to folder + // String? outputFile = await FilePicker.platform.saveFile( + // dialogTitle: 'Please select an output file:', + // fileName: zipLogFilePath.split('/').last, + // bytes: await File(zipLogFilePath).readAsBytes(), + // ); + // if (outputFile != null) { + // try { + // final file = File(outputFile); + // final zipFile = File(zipLogFilePath); + // await zipFile.copy(file.path); + // appLogger.info('File saved to: $outputFile'); + // } catch (e) { + // appLogger.severe('Error saving file: $e'); + // } + // } else { + // appLogger.info('Download cancelled'); + // } + // }, + // ), IconButton( tooltip: 'Refresh logs', icon: const Icon(Icons.refresh), From 247413def0ae03077603e815557685bc07056d74 Mon Sep 17 00:00:00 2001 From: "Dr.Blank" Date: Sun, 8 Dec 2024 01:50:00 +0530 Subject: [PATCH 57/92] fastlane init (#65) --- .gitignore | 5 +- Gemfile | 3 + Gemfile.lock | 221 ++++++++++++++++++ fastlane/Appfile | 2 + fastlane/Fastfile | 38 +++ fastlane/README.md | 48 ++++ .../android/en-US/full_description.txt | 6 + .../android/en-US/images/featureGraphic.png | Bin 0 -> 52790 bytes .../metadata/android/en-US/images/icon.png | Bin 0 -> 76916 bytes .../images/phoneScreenshots/1_en-US.jpeg | Bin 0 -> 303270 bytes .../images/phoneScreenshots/2_en-US.jpeg | Bin 0 -> 764231 bytes .../images/phoneScreenshots/3_en-US.jpeg | Bin 0 -> 311582 bytes .../images/phoneScreenshots/4_en-US.jpeg | Bin 0 -> 290817 bytes .../images/phoneScreenshots/5_en-US.jpeg | Bin 0 -> 281588 bytes .../images/phoneScreenshots/6_en-US.jpeg | Bin 0 -> 154323 bytes .../images/phoneScreenshots/7_en-US.jpeg | Bin 0 -> 227904 bytes .../images/phoneScreenshots/8_en-US.jpeg | Bin 0 -> 352966 bytes .../android/en-US/short_description.txt | 1 + fastlane/metadata/android/en-US/title.txt | 1 + fastlane/metadata/android/en-US/video.txt | 0 fastlane/report.xml | 18 ++ 21 files changed, 342 insertions(+), 1 deletion(-) create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 fastlane/Appfile create mode 100644 fastlane/Fastfile create mode 100644 fastlane/README.md create mode 100644 fastlane/metadata/android/en-US/full_description.txt create mode 100644 fastlane/metadata/android/en-US/images/featureGraphic.png create mode 100644 fastlane/metadata/android/en-US/images/icon.png create mode 100644 fastlane/metadata/android/en-US/images/phoneScreenshots/1_en-US.jpeg create mode 100644 fastlane/metadata/android/en-US/images/phoneScreenshots/2_en-US.jpeg create mode 100644 fastlane/metadata/android/en-US/images/phoneScreenshots/3_en-US.jpeg create mode 100644 fastlane/metadata/android/en-US/images/phoneScreenshots/4_en-US.jpeg create mode 100644 fastlane/metadata/android/en-US/images/phoneScreenshots/5_en-US.jpeg create mode 100644 fastlane/metadata/android/en-US/images/phoneScreenshots/6_en-US.jpeg create mode 100644 fastlane/metadata/android/en-US/images/phoneScreenshots/7_en-US.jpeg create mode 100644 fastlane/metadata/android/en-US/images/phoneScreenshots/8_en-US.jpeg create mode 100644 fastlane/metadata/android/en-US/short_description.txt create mode 100644 fastlane/metadata/android/en-US/title.txt create mode 100644 fastlane/metadata/android/en-US/video.txt create mode 100644 fastlane/report.xml diff --git a/.gitignore b/.gitignore index c137f7a..362c284 100644 --- a/.gitignore +++ b/.gitignore @@ -43,4 +43,7 @@ app.*.map.json /android/app/release # separate git repo for api sdk -/shelfsdk \ No newline at end of file +/shelfsdk + +# secret keys +/secrets \ No newline at end of file diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..7a118b4 --- /dev/null +++ b/Gemfile @@ -0,0 +1,3 @@ +source "https://rubygems.org" + +gem "fastlane" diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..1db5478 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,221 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.7) + base64 + nkf + rexml + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) + artifactory (3.0.17) + atomos (0.1.3) + aws-eventstream (1.3.0) + aws-partitions (1.1018.0) + aws-sdk-core (3.214.0) + aws-eventstream (~> 1, >= 1.3.0) + aws-partitions (~> 1, >= 1.992.0) + aws-sigv4 (~> 1.9) + jmespath (~> 1, >= 1.6.1) + aws-sdk-kms (1.96.0) + aws-sdk-core (~> 3, >= 3.210.0) + aws-sigv4 (~> 1.5) + aws-sdk-s3 (1.176.0) + aws-sdk-core (~> 3, >= 3.210.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.5) + aws-sigv4 (1.10.1) + aws-eventstream (~> 1, >= 1.0.2) + babosa (1.0.4) + base64 (0.2.0) + claide (1.1.0) + colored (1.2) + colored2 (3.1.2) + commander (4.6.0) + highline (~> 2.0.0) + declarative (0.0.20) + digest-crc (0.6.5) + rake (>= 12.0.0, < 14.0.0) + domain_name (0.6.20240107) + dotenv (2.8.1) + emoji_regex (3.2.3) + excon (0.112.0) + faraday (1.10.4) + faraday-em_http (~> 1.0) + faraday-em_synchrony (~> 1.0) + faraday-excon (~> 1.1) + faraday-httpclient (~> 1.0) + faraday-multipart (~> 1.0) + faraday-net_http (~> 1.0) + faraday-net_http_persistent (~> 1.0) + faraday-patron (~> 1.0) + faraday-rack (~> 1.0) + faraday-retry (~> 1.0) + ruby2_keywords (>= 0.0.4) + faraday-cookie_jar (0.0.7) + faraday (>= 0.8.0) + http-cookie (~> 1.0.0) + faraday-em_http (1.0.0) + faraday-em_synchrony (1.0.0) + faraday-excon (1.1.0) + faraday-httpclient (1.0.1) + faraday-multipart (1.0.4) + multipart-post (~> 2) + faraday-net_http (1.0.2) + faraday-net_http_persistent (1.2.0) + faraday-patron (1.0.0) + faraday-rack (1.0.0) + faraday-retry (1.0.3) + faraday_middleware (1.2.1) + faraday (~> 1.0) + fastimage (2.3.1) + fastlane (2.225.0) + CFPropertyList (>= 2.3, < 4.0.0) + addressable (>= 2.8, < 3.0.0) + artifactory (~> 3.0) + aws-sdk-s3 (~> 1.0) + babosa (>= 1.0.3, < 2.0.0) + bundler (>= 1.12.0, < 3.0.0) + colored (~> 1.2) + commander (~> 4.6) + dotenv (>= 2.1.1, < 3.0.0) + emoji_regex (>= 0.1, < 4.0) + excon (>= 0.71.0, < 1.0.0) + faraday (~> 1.0) + faraday-cookie_jar (~> 0.0.6) + faraday_middleware (~> 1.0) + fastimage (>= 2.1.0, < 3.0.0) + fastlane-sirp (>= 1.0.0) + gh_inspector (>= 1.1.2, < 2.0.0) + google-apis-androidpublisher_v3 (~> 0.3) + google-apis-playcustomapp_v1 (~> 0.1) + google-cloud-env (>= 1.6.0, < 2.0.0) + google-cloud-storage (~> 1.31) + highline (~> 2.0) + http-cookie (~> 1.0.5) + json (< 3.0.0) + jwt (>= 2.1.0, < 3) + mini_magick (>= 4.9.4, < 5.0.0) + multipart-post (>= 2.0.0, < 3.0.0) + naturally (~> 2.2) + optparse (>= 0.1.1, < 1.0.0) + plist (>= 3.1.0, < 4.0.0) + rubyzip (>= 2.0.0, < 3.0.0) + security (= 0.1.5) + simctl (~> 1.6.3) + terminal-notifier (>= 2.0.0, < 3.0.0) + terminal-table (~> 3) + tty-screen (>= 0.6.3, < 1.0.0) + tty-spinner (>= 0.8.0, < 1.0.0) + word_wrap (~> 1.0.0) + xcodeproj (>= 1.13.0, < 2.0.0) + xcpretty (~> 0.3.0) + xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) + fastlane-sirp (1.0.0) + sysrandom (~> 1.0) + gh_inspector (1.1.3) + google-apis-androidpublisher_v3 (0.54.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-core (0.11.3) + addressable (~> 2.5, >= 2.5.1) + googleauth (>= 0.16.2, < 2.a) + httpclient (>= 2.8.1, < 3.a) + mini_mime (~> 1.0) + representable (~> 3.0) + retriable (>= 2.0, < 4.a) + rexml + google-apis-iamcredentials_v1 (0.17.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-playcustomapp_v1 (0.13.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-storage_v1 (0.31.0) + google-apis-core (>= 0.11.0, < 2.a) + google-cloud-core (1.7.1) + google-cloud-env (>= 1.0, < 3.a) + google-cloud-errors (~> 1.0) + google-cloud-env (1.6.0) + faraday (>= 0.17.3, < 3.0) + google-cloud-errors (1.4.0) + google-cloud-storage (1.47.0) + addressable (~> 2.8) + digest-crc (~> 0.4) + google-apis-iamcredentials_v1 (~> 0.1) + google-apis-storage_v1 (~> 0.31.0) + google-cloud-core (~> 1.6) + googleauth (>= 0.16.2, < 2.a) + mini_mime (~> 1.0) + googleauth (1.8.1) + faraday (>= 0.17.3, < 3.a) + jwt (>= 1.4, < 3.0) + multi_json (~> 1.11) + os (>= 0.9, < 2.0) + signet (>= 0.16, < 2.a) + highline (2.0.3) + http-cookie (1.0.8) + domain_name (~> 0.5) + httpclient (2.8.3) + jmespath (1.6.2) + json (2.9.0) + jwt (2.9.3) + base64 + mini_magick (4.13.2) + mini_mime (1.1.5) + multi_json (1.15.0) + multipart-post (2.4.1) + nanaimo (0.4.0) + naturally (2.2.1) + nkf (0.2.0) + optparse (0.6.0) + os (1.1.4) + plist (3.7.1) + public_suffix (6.0.1) + rake (13.2.1) + representable (3.2.0) + declarative (< 0.1.0) + trailblazer-option (>= 0.1.1, < 0.2.0) + uber (< 0.2.0) + retriable (3.1.2) + rexml (3.3.9) + rouge (2.0.7) + ruby2_keywords (0.0.5) + rubyzip (2.3.2) + security (0.1.5) + signet (0.19.0) + addressable (~> 2.8) + faraday (>= 0.17.5, < 3.a) + jwt (>= 1.5, < 3.0) + multi_json (~> 1.10) + simctl (1.6.10) + CFPropertyList + naturally + sysrandom (1.0.5) + terminal-notifier (2.0.0) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) + trailblazer-option (0.1.2) + tty-cursor (0.7.1) + tty-screen (0.8.2) + tty-spinner (0.9.3) + tty-cursor (~> 0.7) + uber (0.1.0) + unicode-display_width (2.6.0) + word_wrap (1.0.0) + xcodeproj (1.27.0) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.3) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.4.0) + rexml (>= 3.3.6, < 4.0) + xcpretty (0.3.0) + rouge (~> 2.0.7) + xcpretty-travis-formatter (1.0.1) + xcpretty (~> 0.2, >= 0.0.7) + +PLATFORMS + x64-mingw-ucrt + +DEPENDENCIES + fastlane + +BUNDLED WITH + 2.5.23 diff --git a/fastlane/Appfile b/fastlane/Appfile new file mode 100644 index 0000000..28f043a --- /dev/null +++ b/fastlane/Appfile @@ -0,0 +1,2 @@ +json_key_file("./secrets/play-store-credentials.json") # Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one +package_name("dr.blank.vaani") # e.g. com.krausefx.app diff --git a/fastlane/Fastfile b/fastlane/Fastfile new file mode 100644 index 0000000..ce200d8 --- /dev/null +++ b/fastlane/Fastfile @@ -0,0 +1,38 @@ +# This file contains the fastlane.tools configuration +# You can find the documentation at https://docs.fastlane.tools +# +# For a list of all available actions, check out +# +# https://docs.fastlane.tools/actions +# +# For a list of all available plugins, check out +# +# https://docs.fastlane.tools/plugins/available-plugins +# + +# Uncomment the line if you want fastlane to automatically update itself +# update_fastlane + +default_platform(:android) + +platform :android do + desc "Runs all the tests" + lane :test do + gradle(task: "test", project_dir: 'android/') + end + + desc "Submit a new Beta Build to Crashlytics Beta" + lane :beta do + gradle(task: "clean assembleRelease", project_dir: 'android/') + crashlytics + + # sh "your_script.sh" + # You can also use other beta testing services here + end + + desc "Deploy a new version to the Google Play" + lane :deploy do + gradle(task: "clean assembleRelease", project_dir: 'android/') + upload_to_play_store + end +end diff --git a/fastlane/README.md b/fastlane/README.md new file mode 100644 index 0000000..7ec1207 --- /dev/null +++ b/fastlane/README.md @@ -0,0 +1,48 @@ +fastlane documentation +---- + +# Installation + +Make sure you have the latest version of the Xcode command line tools installed: + +```sh +xcode-select --install +``` + +For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane) + +# Available Actions + +## Android + +### android test + +```sh +[bundle exec] fastlane android test +``` + +Runs all the tests + +### android beta + +```sh +[bundle exec] fastlane android beta +``` + +Submit a new Beta Build to Crashlytics Beta + +### android deploy + +```sh +[bundle exec] fastlane android deploy +``` + +Deploy a new version to the Google Play + +---- + +This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run. + +More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools). + +The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools). diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt new file mode 100644 index 0000000..597bfd3 --- /dev/null +++ b/fastlane/metadata/android/en-US/full_description.txt @@ -0,0 +1,6 @@ +- Functional Player: Speed Control, Sleep Timer, Shake to Control Player +- Save data with Offline listening and caching +- Material Design +- Extensive Settings to customize the every tiny detail + +Note: you need an Audiobookshelf server setup for this app to work. Please see https://www.audiobookshelf.org/ on how to setup one if not already. \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/images/featureGraphic.png b/fastlane/metadata/android/en-US/images/featureGraphic.png new file mode 100644 index 0000000000000000000000000000000000000000..ed9c09d85f252654b16b62d00334e8e4a85cc5b8 GIT binary patch literal 52790 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�_pB@&M7@GZ(ozBlnUY3%rGw{vzUxEt`$>aE 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 literal 0 HcmV?d00001 diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/1_en-US.jpeg b/fastlane/metadata/android/en-US/images/phoneScreenshots/1_en-US.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..a84ddb67a26051bec794d56c240f65e7734225dd GIT binary patch literal 303270 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 Hj=Qo2GD3jh;)>%%^Go~xBmxRtxchQr}(us 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 ?r5G&Sd?$M9>t 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

uOU&qIEu!!*Rq_3nPnbv{5--B(AosNc zr++x$20(gtH$(HHTa}80V08IWM3Timw~_b$t~ zG7k|X1rd+hC*xfIr=99Q*YZz2ev=Jr@7();jD-HTM#g(?Wt2Rdo(?sxYa|8yM4+=B ze|h7IuY@caUxAG|lStQp7!Y~k{l7nC?ms?c)4R;_H(9|nm-Pv{YHKfNvqF|-JLyQd zGvO_8Q#$Q^oXjb0R=y+Gs3br4XBfYJw2+W}CS4)V=RT$mC%)n)lZPIv@2-3d%hyCS z;-Fgrb~g4Yn>d~_ypg6wT>*_aHNHr9;EI##vc;Yc3AvM-pwdeM^6BF1iuEXz7kX4BMSLw0x4d zI7saNUPk8$C|K@7z2#hFf8snw9W1Ru%^8w_<^Ol6Z``LSH0ZO6Rx5X3XydOmlbwZ zRJop&rZPXz;>>(QspXriqw5PVQD_u0^dX%N=Vnp-GwCGE1GL>@PVi+>Op)HBSd?z` z1G;5h*aPWhU4-yU-KQmnIdt~-)kxTf1mgq}^nr{_Nc_$Jm_PgXi~c07s3rdznegFUf literal 0 HcmV?d00001 diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/2_en-US.jpeg b/fastlane/metadata/android/en-US/images/phoneScreenshots/2_en-US.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..7b6c86b56f8faf9952d744844b1ab376cffb014d GIT binary patch literal 764231 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�+0wqL^kbw-{$|iiG6`7mHt}F(txc2 zczb4neLnS@PbdF*;ksSyhi4x{IBb_&ZN^&pIa}ybxG#=AwnaPa9)1tDmU)ML+ zP$L|)IiU;c|CmjY7yK$$*9=?-|7~%e*qhF@cQy3!q_-Y(R&C%)7_mXK&*8?^j7xA& z8t3~wHUKor18E2=Caq!q$`W&H%V#bA_s#w1)Ble>Q_{BuiEqun{ix}uLOUwYn%(q& zOIg2!>k%qh%Y6GPaH4pX`kYqzm(W;;BfWCs&*?t^!Nuph_iztyXVa>f|8}tb^Zt(d zV>`{ix7UCmJaqG(*eLtW>J2CVdHXbqPoqy`w)>`W*zMIjWJjy zl*pN6R*zNIyvNv6`5fP;?$q*vLkcAee4JH)dEDp(6Bw(^*@VpLQUnL@HM95;o(5+f z!p8*1Cnmg|HopeR#0^)wm4x7HRCWhYd{}RF4{cs&y$~AIGuxPGkvnmgS=xbUKVZvN5<$t``!+y@7V z$uYL_H!(7q8B2b;EE)TvCb7xs-JQoyZh$V1`vZ_*Y`jaB`ooch_jwIvr16BxRA>M) zA_pbJqh(2#V$4xU(*bDjX@8j>8db+|6O!LM#r<{q_^`OuCnt#y7pwu2c*c*E^jD@f z`=}8E_notX$~=yy@#7F(@7>|2y{E_h-Q6~|={wT?N9@xY_{qHX?yEzU=G{8-phau* zF}LaS2`!iHlxtKTll$Mp*27fWVJ3O#rFu34;yXzxzH`1f**rw$pAS%AIaS%$?~bmq zq1ojL*}l%`MpslKN6{6iQQXfE$O+?m$Z>lf34eP|F z!1|;{Jk~B*W~HL}iL9#Okhg^DdeZjaJG)0f@+v7gzK!(mU#o1DBrMs!%>#C;P2nB( z0Wha&V+AiuL1u!qQA?keuA0+Tj94d;42L*}8=PNLgYt!IG*YeEQC}!8c{Oc;BQoXD z8A0cUlzsWk=6MHv*QDO)A)SeQzl@uXPp+O;cHJS-&M_V<{a;_}mG=o;%vd@Z5fW4hqVNh626a3ET^q`v zQ%oa%{@mo=M|9#BZ<=m1s*Hh}Z8|{ArjK_kz|qM)NmEK)FY6>rrrMbhqq*Cz86J{r zK<-D3^}~JuH~$C4*I~qPSGPj}0%1`0!dE&MkHeiKrZP#=$CuBaZ?p1m`^pE3fV{4m$}P6N??E&SE&~h^jc4b>3<>m*kk-w{9GW8rCg(D+yFaFaRmn8xFEv#t zIn^+~qf=4L{3&Q_GAo_C8jhJwp;g`GD@2(fg9n-^mQ>^K?nIo@rsg{={n4HYT(`Do zmzx1q;P;M#i0Iw`^@WvsW^qnlPGw$jRGHZp?y;OS^iLj4`=XocS*Z zP>CDRzlaK)9waZ<{k8?Z$BpY>8*RSO$6&Bmt_<3*{(Ig=&(XDNbkan+62P#zZ8Kne zf8IIUMj^!TBdo@=I)(m;IU7_`RF(+1cg{94nVgwH&eB6P&#Rk}h9G%6tZ*G8S^ySZ#}IB}^_pnw8{J13oC_U6!c$xw5F`GcyS z`}tY$$oXBL_=&7Df}46I55>&(BW>k7p(nX$58U67Sogq)UTZIF^ryq6gdLu^^M z8CGNE;(#ZU3L=af59Rin3vs}mrYyPJXD{|)k)?q}^}PY)*{W+gJ? z!!o{6*yq-s=}~*-s2bhBNV#0F`TIVUet(yCt(~V6k|diVlYp0raWb~?Z6Iq29_T!^ z3g_LC*Ugbjwe__bNN%dBt9#kiuLehulEAnsD_`@J#73Q)ZO?qab*UoHU_6BPdqdkj zfzu5oZ~e~_G}er@Z0>5@guhc^csy3azlOayMDYVvT9=HL_Jv`9W;r!=RVmjTQ?3T| zbTiL+|LX4gO~ZSj@0{Dw=V7t(*^$G=yfU^wbDG$Q6O~wW60d%<*md8I=&^U*>JZ6* zkei_CbMT(OIHN(eJcFfkpX>yE9B?_Ifya+rtaJBc6qY03sgJyMtb=Vj(H4-NAa(3!=Qm-z@jCx))O@og=P#BLMZ_;;E2ABTxUs)MT?f-UH+fFwF&I8p;-FDmQLO>4 zAT3j()d+4$Nj%1>RTXO5v6CU0=r(;k;{j^TRIgc{nJjK8KQ@&J!_g050b;^Ydpg9m ztFO8mjs+3!{4Y_QqGs|nmwjR$}?=r8+X47b1nGEji z>UkCY0pYagSDzrCk*WG)=|z^VF|8T^@utKcoP7}=EC@H{eDjq#{ZB-C{Qr4G{(ptQ z|2J6t|2}4F_Xe70e%}@Si=yup{|^-##-mwKMrLH>8R?$h6;k4yvo zD8Q$UlW2pzh-`Lv^*AzEB)%6R)9*CBDYqZuA_#vNR~*c6xby;SsGNirl8vnO|!OO=Y{3c^%67E<@yKi^%-{P@V_!(blxFsmQ4XT>3Js2b%c}-&`LVm+@|p)N=XRm z!=Zu?Aj{6Ly{wH%9=lck^E8t` zrF!naEvd6Hird&~xpVA&f6O8@hpU0-w%ciIG ze$A#nIs6W4`SCu=Ee4N!X0J9|cW#E9Xy+ae9o?P|+USfHlU$SH27arh@hAbhpb`;1 z4+va-y#AbqjL+4|W8xv$0V$L1z!SwH>7?RuKM<(1OpO6mZM!?vNwS?9x(!^ASG+d9 zvvQT=u-wJ&M_#6A`I^$fkeZdE#eEa8JA6Hhmrc%Sjb1Zu?59M-p8n?EWMIHY+qp=# zN^GlT4sRnF<0TW;j|rE?B(3-%!{zMB5tdxBhmfOVKF=;{1#<#_jcRgD-l%(*{C{ZzVLEEtJ9dn*Wfum(OCz;`CgIRM59vbJm9jXrKMX zCdz|%A%(qQUBz1CBZxFv(*!9|tt22t1>ppQHBJ)Yax!Jl5PZ5 zdyj!0WjsT4D7-Mf><9=Ia6|y_0^MBEip7X>{d6^#IMD*O4M}LaP>Qw-D?TXRl&{)y z)fdx{8P?9thC{+cAP+w}cz`=#N1^6l_nJvG&Gjmi|5iVDWU#LoA#v@W?lb9F9E$T9 z54Jg)cXrQyVf2;RuZFYbJHDAhyG*hVtaiRv7CgersFE6SxiShu2>9w=m#QAaHi!n7 z-alvVDR?xXWl@mb=F1va_l zy}zn~mg%ynC@dis)m?74ku3d!^i;)@c;XN-drdC&#=GFFcidB3L@!0TeLGVOeBq6y zKhv*=s<0^`elDiEFvB`SQJJZ98VUjL6gf-kxp_z0gPd_3G}+HBspXGG`?iiZ(wS{~ z2p&hI?k-q$tra zD2ElM7B6t3dAoei5Bv5IzNiy!z!=AQKwpgc1Ik{4BT4<6JjB)eRB`A-F;x=N&gm!( zrWc#*A%iM-kCE%9ba`VyY{;t+_vtj~Eu!H;9skbyqr!50-}&LEzXTVZ-yBMrE>pgU z_097k(Fdy?`HzA@ZbehDgQDsAu8YZP>ww0I%tiq$x-kJcz7ESRVJ8mNzHW}usgz_| z`{U!LOh;;HECC^#d*$^~_(tG0FYG9+FUH%mv4c31XNKNa4KBa#FW-hwoqSGySH4la z#kaPs)(ht0jfz9j%=8W<4pJs}8BPTxFi9yD;}2ef`%kuahP9^cKL(u0XG&k(9v|{+ zZ^qW!K1MmOaN(apLwp!g-Ra_-`aCvUn|`P0lPXJh3Ia0?2<)z@bz<)?NZL&hmcC}< zu~k?fm=;>W@2ZklY>v3f4b}}5_UBoW`@IrEh9iRvR>h}UAw=RGw7@^C*AeEfM#Q}6 z3s$r?-%HlZPGawYvs|eW7+u3J98f|k>2KuRM~Fok`h@3~ zI~rQ`JFgeQJeF%;7AQN-F|KHs2*KCye$nG|xhTtw7op}w*SIHq`;2!;Oxv572qeDR zKe`Kx|1s#e<~z+<=ftXs_QMeOC-$>}X%eF=aDgN1w-;LalU>@lXmgqDOPt>(&EloW z8BIA2IE!RGVlzE4?`wXXGYc*k-Z?7D7-;!?d^h(HJC{=KVzm=o8y_4VN7M<+WTeN2d(wSRB#NiDiluORP%(sGgDL2eM`ufo4>&e6w5jx67~=z7vt{yVTov&#gJ=zhBb z(;;3-`h}x)ZHI_6DJPtUR5?DY^-tQ~b5tZPZfVZeX~Pkp4BnW@jNw~nWs8n3bMkra zzmBZ4&XN38XYk6Yz4yZ54rzY+C>;h~Y04Ei<+q&}(g027)5XsXk{ANy;F91#o^Lgp zb(E|mH}7M+OQvGI4yf>4%f&o$30GAQ$&?Se&@3iLAJ??+S1OFs*aeogmVGiLNMtok zI#1VidD=(8I0ht7#I`K{_4N?~(SI?n z55G-(*{4-mB|Fl1onovViuP9LRY{s$Ln`nX1<+@LwQ)*9uuzXtPJ6K)N7GqR{$@@i zj6gPIhc@C22~MnIwb+f?&*MizA1Xs*g?Aize{b*{UwzuV(2{*-@SppU8`@079gZ}N zL;zX`UOD3l?E2v2DD%p+Z-;}_XWs>LEq1*zjR0h*_>?x{E6^PN(QXa?BT!DC@%<;M zk(sEdW8{X7Xs@S*3|{-prFh!O z3~vSejE$H5=RS~iS~W$H^DSs)GBe}efah+O#LQ~$p;d6Swkt_p?qyFF?}ig$+M!2n zgIBfDCmKk*;rnc(efU1vXd}(%=%?sM%Bs;6Fbtj)P5aCCLyJe+4XBI)?~M}cIKQ?6 zDYLxB9JkvH5m?VHnsJu_^Fxc|T+&VZfe3{aRUvLWJ!RCfirU*ymE(WIoNR;QX{9cN ziT|R%9$V4>u7|8hy<&W2F~$3$nf`I0I;IrTBJ?Hj%h7+J#`Hy%j{)RVP0&Xlt-4e^ zc((0#{yVdCr9dxY!g)0EuvXJ7nVX?nZx}PNBls4nNeAnwN4*1CsdAu&^_Ip>EC#zD%3Nt_UY$AxrI^ zi_w_^Xg9LG9FK;ChE$_P4$Evnm{c}~bQ91IG|H|9bp4@#r2cgx|B8*nzQ|+?z4!cl z&`{FFRa=dqXK&+|uAv1hFD7es&GH;*KUJhvw{pZW=o)P8gBVvjhnz4njSp{+(|Yj;{)U=MZLg0eS{@7VhR zdMEDqLyIV-Y1NeH8>McR970r^dGfU5;PB@8(ijVGx_Zji4r0e%5RaDjK= zi|6SejjlngNT)o#e^tFZ_HiYVoe-FU&O-%{0BhI5aI~%7WkxZfJ3skD1iufN@yMp0 zr;$=-vbnRBz2IAlsjO&_Pi7RTQw6DvH4okqf)_ap z>xZ)WStcfi8F3IFp!Aw(JlVJvPNyPa63B8wO>*}By~*d__p{Pw)Z(El4z!~zH*iLK zdvXh%E@MV>iQ?E6Zy7|m$hs?EMm%y5GnI~_KA`0&?{YwGJ#KN9Lv5!vYPl$ugap*0 z>Kn0CR!QaVBgQrs-TXw_KN*r71`Pta5UCj^2`y6qRT=&Fa;GcG7_ ztdLTZH0m|&>0l}PmzM5gV+0;)>=LX(mMKySh%a-b7=1!YKsgef&C7S&1|v7<6Qrw7 zMcp`ZH?>0{Mz0^#K>P9gn!}}w-+d3D5i%iHblDth!jR=p5l(z38Ap)(iELY&p6kzR z0=WT(n$Tc3LX!CO)Qh}QbQgN7Ppz_cmwua&Wb6$xF@YO5Il@oCZpbCQ@hewigeTR9 zj;oplZ*Y&bc|)gf&0I!zd=GrF5K~slN>|N9py#KGrpN}4_eMU3(23#UC~i0AO#@Gq zRon5RZy!ju4VLuY-B?n9Kw9p~vKsH(@(sweD}TAel&Zsq3K|n)Q?SYr%BZ^J{by zBiJqT9cuu+_4HHi^xjN7DPc@cMJ(yXTjY_|Y}CRaFWcrMMnBvI5PzFXc&x8oCjw>r z8&lWefs+~&;wO2kw+?#Vj6|j6LC%h3u{t_Ss$zQ&8-@rTUV)5xWGSg`68LlKqr`&i zwq14+Ac$d%NZ|C);~zk{NF;+`TS_Z!1j886SPe58R`_F}F3mkUBeBi=h#*^8tWv=> zMW8922^xUJT^{+nU8u!)VVO>8M4^2K;&-i^?8?#@lo!|1mB`V-#@F5CH^5^!U*H(e z@gTq>)K1!B1rr@(z8z5HPYjw5?qAhPdcb(V3voVJr19RGH9!h7S>w5~7(gbS;B3o- zaw~F{#mkBW>MI?`agaL~8?fLRH((QgJ}?L^!#~kp!rX>d2M8EtO#NhVhdHsO-MlrD zGFW|5-d9gZ89`ke?M>1m-i8*NKZMwOZR_ zHcP^B%P#J!WB>TVeAjMO?U-6F>64vLd#0!;+b4KzE(b%`NA6mzHxw*SvhB#-JdFmY zlng3WjDEUozpoS!4}6NZQHclR)4QWcG+CWvLYr->9V`y6W=9@GhvzsCf88VN>1s|q zG3-OD8F5R-oo}hQ+ub}5$_zZj46H3I_J9VYzNLf`gKzEL45uYTGS&R1Yla>2N!XXV z*5RG?Pq7_9|E*Sv_(V3W^2K!D&Uu3YwK7V^U!R>AMm9r6zmM!#sLh2uu~=gcJ4PU5fCVimm4$T>xOTrKAESbNO>5aAw`u5`V1pwG zf~|Z#$byF0)1RfvSF*{o2ZKaPZP5IbpoD%|atIU+BcuvQs;K?c3qV2OGp4-K&)2H? zPxC&UhPmnZQS7h+n32pw+%-!ADn&+&87YJQA&SxYBewse1QpA=eIo8Ggs9=mctGB5E zXymQ(?_k-OUR^kab)}nQOk8PQ_b-%x1= z>S8Fc>R@y*;eM0b7KLYH_;4n8V5v0RqzyExCekBIPV#PjOt3~dM$sy!WZ_09)B~q_ z#vf0MlEzO74dC;=XHs5g8;!s-)Le3L9#N84>HQ(_do*aRI(Avjs4Efty12+e&OL`$ z2P6w1oqw};=2frpJ$2;}-fw&FXVJ-n4kFucRy%Aslw;9J27o}ceL<7V&`*piu)sdA ztt7dYa~4F!&`4Y)hE*D3D!gmXnC0oFpr9VX-xImB=0#^G8(#>sInLDAe!c}`b!{5+ z8w!x|zg!9AnlURC3!+H$hOk?im7Q4YfuO9?C5APfB~Bn|HbOlS8Hod#Bc`liwB!Wc zF~sE19?Q}l6Yz3}W2(6e;qX)`q|0<@*t)wtW|6Q+)jqi>d1Z!t1R~Yg;iW$Nkg+v> zRSRJ+;b3Iv*8XaFZcE~24j!3|k2Ta^F)v*iz#S~dwBe1*YZB?$bDvkBw)S7;6p>j^ z=hM`>wRzOBjAd@Wmi@5m*qt@BQYB7Hd(^V`X-IWV&}OiY>vt)V8>h&w!%dJWF^w|S zP1n3^Ti++1Fau`h5w~!Qda|)`ilHVdLmZEIPEb?Xc5AQ_+CpoiNjV1x zE)NS>mfLR0=Dhpenc<2vEjJcT)E-|-j2Jf>r@i9p=dJ06_O&^!D@zWK-r#-b%pg-t zpa}Tc@RsinpW{%k=89;JvH^puk`yXf;SUTiI6+q|%~MpGuV5pSbY)1BtUJIXdNyek zlT`2kMpx!BnE=7Cx=G@iO8P+F)MNfMmA{l8RAq*C|1gJWm48u4xewAXx4SqyYD!X+ zvG76!S)`CMG`{#;^^ZfaCijJ^t&J+z+vw2iHuWRP{}cVq#Tx9n%x<+rMG}wM&oZ0TBk=e^@0O*Hij-b(T>m+ z`YaRm6BgRkvV?d{-XxVDeSuV+4AL6dmK3E6XHVGn2g+SumZ_6mqgN0C=_M_Pel=M| z3Mb+t1=~K|&2C%PJ*qRC*rn*v9Oo2fVUnZRZbe~5gDT98jvq*V>Eq-N=r)zakK8+> zK9uEAhM%~Y`64=s>R1FclTKth+X^Ym_ME0J9*xtn0|seh+||3rI@`DZ*JaA?k1Ts?7!s+4ZW_Q=GTrhE_Q>c8;$d z%;3Zoc}v;8 z)LH&JtM|vbYI{m(&;3KjDSu_;u%xua>-yghEc-V9g}pV%ocVsaTk7>Z{dhm}Ry7*^ z>B~jw+fuB(#`%9=r~L|{-St#wnFr~rM~B2#pwedL^{We4p`hS$U)l;r!~p23p7icS zqJmuizG6!squySvAJ3SKY@(b>e(fLy;3s7FGm&0BKKfCm`yO0bpCHk=$SMi9WPj`| zHdI=Na=4E&8pz?1-xIEPsKe~kJ!$5%bxr6{!@k!?b+tZFwusoNh_}_fh0Nn~Rl%!~ zh%iZwkqogw#ljSe9B_s;7_{&i-$d3wxne|WHm2{p8Ad;h4%vRl4VtoXlC>)9igs6K z?!b8?41gOXa>C9F4ETf}?7SBWzk65CD=F%f9Sl~sJ$X$$+40e2b0DE@ZRnr2cpJ16 zsYrGSLBy?C;Z#q?!ZULgQ zB-@B4rIoX@Hn(#-_%rYH8O^Rjl6xwmL6l7%f&uPg|;EC&+mw$5nUaUx`m5CW`w{)Q|@9R#nTeM;wFXQ6^ zKFK|-fAPe1bS^UJjV%2Yu@;b7aA{;BN%WUoGs9oDH{aWEK?&nqU5ZG@{-!Nb3N0Pg z6F;9PkrSkLgV9q@Qo019NTBGspgi!FGen81tOW=Tet<)J(&Lu=Qz<_U`^L)F^Lf`6 zyo{Gt^ly5OPC8yvDUGZwh9wG4DKp9o1K`|Pcrq?N*Bxsg`k09DK=yNk*&9Vc)e>rK z9&-eCYe1%Sb=$+@bU5kXJssbNFmO|to2xhsu-n{X>*ZR6Tvx-T!qcB5&z#E$_gC3S zh&JBFxMzjX^aMInaQS~Cf=w;DV4z0@xOHr9pb36UwA&+XMDarMnIcxN!vl?#eg7%Q z$e@lwEr|~ZHoc%$8JuUYExjOnvq)w%)_eT$<@%!yk5~H1Q+V6%vG1($L10`IWN7t5?^_`WJ z7pw)iXje~lYeIf<^CIakoq(P6<#e*58D(?xSd?{IYZP*8YzA01P>_137D8{ubFHZ~ z%qDwOsrYz`8TCL(!V;q2@v~GV;1kt#_{gbh@bAP%e(Qn^Ri86T+i4ky(X?kMk279w8#h6n_dBP|yzEli<=La;r>} zw&qsD{JFS5-kR)BO7hlJ_G@GS;XX((=Y8|XJ_BDH?&wvU=mmBc6dj5IAv$*Y&mc)% z*B|`GHy^v*T1!2gF`F}V=YP=a(ZGn0Z<4-r#@Q3I#F1Em<~nA&1AkjoHwgH9z-{wy zPQJ-dyd0W3^NTjU8>%)MOI$ll2~=mpwZ{W!2tC!;P+50kSQ)7aikO(mmNs-@=cU}w z+a0u=CMJ^c8E3NFLE`!tKo=5tQOWkCf^~;37IA69k_kUhQsHy zH@=yj@waBP{R{=-c9eDVRNBeXEg=yR8SPeU(vqVh>1jcg8aBf*Os)q55wD8&W$@;+ zfUFT5_@qKcuHZsi!U6rNeN!{%*30uqVir{^vHtjBGM`azjpYXV`W)O}efUAlwfO$l z(`|cElIn;pNuNJUqI;m;pfhr@h&Rg&Kw5UU0D$%w#m_MC`M%a^W#@=WKb#&-@D3_T zp%|@20vVwWzIJSxN4n=UTG@AH2K5-Y;2rloM8t9g0162rA|k-YfaIv)aPOHU+rmf) zkI-9^Cc~a%w|&DJ5Km-fj4(Nr*SXi=BOI8KU2fN=7t1&KJjA`7Rg`WT*Z&{Ho*hO9h3`zoke(>aGFICq*?APYMU1Y?=bo(JuG z2L%Olrb*QwF|D=cHgZy_y2jWWx231pWa1qtSJpG{5wEICscdys>}pnhSFLQdOu`2a zg;5hN?w%#O?X{oAT((lct7T6aDzt+uP_xH4wQZ3$JQn&Tw4Gq#C+cVnLh_|DlR7BU zNJ!mXoj-LC=V*)?X`;Vpa^O!;jy5TNT}-RWG!SW{7z!w<#*9Bb?zG7tiZ64}GEpgw z)$j$Li!^r;wHX@w=a>G7P@iiWB&e`y9rq~_b!5e>X=M*PRj-VW$;#T11!$bm+1BTb4{#bnVQ0E4@z1;dgcBD zYE~(TN@Ky@UGu|D6ZJm;A64l;KkBD+YF)yQyw$Tzltw*VSQG9^lLF@2lnG}z%}D8$ zxp4%lIkaS)->((tp*Q=UU+_*Tu1T@ivmYg=19!%`l8rym4IQ#LAL2=K*HmbG;<)k% z@Ky_gP?l3}=Fy(mSGZ&@DC)|>29T74X_4Mi+dOh*Xe363Vl=a)Y69bJ=}H3!4&_$Z zkJ-)+V>kvWs>3#Yuq|~49CG-W%$ymSDIb}2wg%KhomUZ?%(^2Cl4{3I8R{O z$n>4C}!JT8G{{TMH1ot!JOBZrt(aFe+8{^r@$(EjLsuAKy(sh70 zPT9?0QmRg@w7APTk4tZb7X-h8-f;$F&~~Tn?cK2?kOwf~@Qii%{i!HVZc0Zbu;&Io zu@9wa12DjzT><2nL<+R+U42XEu-+Jy++>;-qxD!43$(`ZTN5>o8VHr{K?3j?Wit3L1uKIBzTFyfMyAzyCs(sI>tSza%0G}%d;PfIuZt>*vfYf+P zCbpB6rsxa4AV5K2HcU-uWffa?dLH(WIMM30Ev+wXLeghTlp(WRT7 z=RH8hlvO{n&gh$GLPg$jvP3o3^hB7O%gwqoGz~#i$@LtdfrCFbAo~X($2BxTP)tYF zXQp=`F~XAp75S(@D1PMKd^)XQ7M*IGwNGnq?at8VvzB<4mp4Mj|MV67N-E+d&&_`R z)D^=V<{dpEB|24_hgM4j_KFFKu60!8S zdtPe(BEA0!O8kxQmB)SkAFWb*dOSQ$a zL$9K&aXiSL9+yxyx*#VNa847hD%!5PUL2xg{k%T5fdkF>hE}#~aW+wQ-ce)B;WE_% zB?WE=;If!cbr($eSfMJ#)p$%3hQ8xW!fi8NB~1@Yxv(*2_u#cQvgy9`+eg{Do~V;V z!2$5}y5+s*YL}#xTkf_k8l~HIvst@;M1*bNChaS5SRDkQd5;xXxZ!zm<;UuLD@X~Z zv}?C3itcpi^w;SM)6}714P#!a{30Ka;^M2`Ci=qtq#&;3?->3NAv2ya88_IklAGsD zR5jXbJV0oXEL$WwXyvjbryPuBdC~HXF~M`DoOyj%Tyzgt20O zJ>n1K@=1$}-h)tuxw|&%uPR|BVNmr*?JDW7M8#N5LC;(-;(O2E1J{;UpP_ll*M@uI zUV|z}=Nm5HXgBwfFKiN(3$k+$;SJ@ouD-!gia6t33m8x(d|**}NMNt`%GgmP)t zQr)WK+DU_3fOq70Y9=G1Zmo8506HN6R_^`;`NFqH$-S#(`|jeAuG3Ktq`* zSy{)-6^|fq=VA*B{g$}6M2ip=g9fuPcz&C?VkeXRLDeFOae60v>L${05myNR-S?`?V%)o#24|u5f#T9kW9Lu zbTDd38~voE!9aR-zNP*5`JK>RNE1m)|#cn09Zcb}Y^9_o`h}^VYs7oM*!r zu}-)P*-sBE49Z2ubMzqk%zbxOg(D^#CWx{v0`Yq{V;Ft=^Q zrlEWD14gngjxY}W>^$SYAMlWdAdODRV{H=Km~`YDEQ3{f)fKT;K*p%f+kI4Ed-1t^ z&9KM{iSW%xCGG}pqm+@*3YOMVVM%_J(6&4O-ObBuTKQbsE0ZbzKY+IEFOOQCzXGd2 zy)Qm-y0MI>kZ2J6G-k?l=)~u3=>=ivC&k+($CD>hZECOAYeOI@!)tv#V&jfGW)Niw zAkX4%7IvG~W!w3s9NOSzs1Qn*B#E?+=t;-qc5K(j8~D+$R8l_lE(HBXZ^S$qgUZ7N z*YUef%)70qIw1(YT7|e2vZUt29S)~A4&_9I&jfzE!?5mE8|RkBG$cI9;RiWBE_dtp zW-LOXp3AUE6|AL5BhJBU9GjAb8ChwHIvFVlm~Z#O4Xg`tvrQAH5#kZ^b-D4(TF=@D z^U0|pIP=j@ImvHAIz7>)A@$}IS4d>e;%HijX)HKKn&~B9qM_vTX=z&o6J)Z(y#XU1 zL9f8>zc%8@8cZZBd9V4x3md*^zOH8V_*kN9=IlLWsi=p?Z-($Ej#wGOj>g(Uj<{UX z_7-jU>;?Bx#C0_()=I-kIa1wGZXjG!>vO%Yxo?7P-#b;1$W__3gzI&|dl%L;Z_KF_ zph;(2P5Tp*A|2v&+UYz2z3Ty#QF)4j*@{A64axg58N4V^v+q--Jm8M=%!SyG44);e zs#=HurwU-48|zIy4j@6EFNz#)8~BFfTjF*vHQ14y*m5gYG)#B!A?U1M;M z|6_^*-Sa6`Hxdw08=cw6J3jdo76rjRjz^KcHQ0)ndWD z?#R$Y$trm5T#N8ME zLY(+shHKn+u6tpijdY>axg*lesgD1?WIc1V>1Uj8QPrTBDV7fZI~7v5s=6AWUKadG z8ht!8-ME5^K70i`Q89X^bJJCTN@OQ6cj4x-eh>Yl;G^3u?O;z9#E+m19=c4

?Pr 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

%K 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ν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 z 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

`71YG6R23>^TeHq&jibaT?gK%*=GG%>Vq|B! z*vO|c=T?7igt9BL41e9k(v6KY7_5XzkLL8dgW`Pp*WA!D;tst7I@E&V&{w6Qzq&W( zMyHZ#FzGiAdaqV2XS8ZKG>T`~7xeVt{Bmgpuqv)DwX{^k5jGq#7v2CYkh+L`gOs7S z?)uEU9dhL0)5bYAVeU(HJ?^&63*!hGpVISw9fhOsI)WxwJ27wDYu|2+R`gfK2RQf` z#5>8{32g8SZ4ODCLJl~KBhw&#rbYU(5c3|x@Y7XLc1N=JUg~~qzf`1kRRKN%4FG_r zs4VG81^^7thc_&{aWK&!8alAy+zth%d$pvEu<2KL=JUEIPP>xRsH=v-YGCz|U{NZC zJdtbl3P!6*G8aXhR}@xxeBI|*;^>;PK)$IM;T;sL%$4fHHcP(%Clh`4+ zx5xfPJTjygK3N-r>ZEUyf?ZCPo@;F)mSzv}&r(?u6vt+#wLVe)i2n~DqVo@sO8F0v zOLAFwVs%x?yU5Oo0XkfdjqD!zcB&atgq9mY9s>PTuy}ZRN3LWv?mM!Hl3P z(d|w7juYNLt;qn)mrSVH%YZBE2NZ5+jujxkpPJ5rxYzA<*kbAhu(K+T0o6Rm^A0B{ zF61`vj0^WDYSX!$lWHCLilCt=TU7!=2@&J%xhz<{S35~z}D?|L6rmX*g8^g1>wS!JaowMp>3!>&X;yESH#)wIZ; z<~jwV48^1n#4#1T?Qc4rX={k4KJj}FFh_v{-B9CoS4_>;XLdwVm2$w9L!XHnp>`Wg zFEr?jzQLL$>Th`*#%rW?vtr4-kmu7E5Jn5GkN>J6F#ZH0W zK2I{SPoFwxkJV_~3JfaNn6{(BF}NFP=8BTN-uGsEZyNMTET{aF3KeC3cXHrq{;Qof zx>eLez(k~@W|v8mH`5(VtmkGy$Wrb!()F{As&ODWSn)F+IZxQ!A`TXg z63u?5QcpO3Ot+k(U)wrQrF zA~+ZUkm-!T9sP$BvYNls&mupG%r`qJ*0Zc-&SMo?61zdNu60}ZTqy&&tO~3e_EiyB zsv4Z7z!X&4rH$ti9A2l}lt!Zoai&um>s>=e8XRo*LRVqSDw_2O((jUMWh59wBhGu+ zm(-gsq+QQlZ0*zFx=Jk?qejyR1Fiys=`;tjHD!8kaYS2Sm|Q6%nVbYz6^8wHFIDqU z8p0U;ax#$lc;u;KWxDnJQYg2>vcBbv!I7Kx;Nfp3pSK+)(w>kt1Pq7aG0)j~Ou`$#0Aw=I6#Nh<^gPFhd0!4ZT zqt_@aVSX1~og!kL?o#C&;#fMvy3nJah`0i&k4l!CW0D4MvQXNUbC%k!mEa|gw_xG%=4#es>J!L zinps*9ob1tTg8fzGZ(`CaOPGiG@%j7;aRban<3-MK*EDfUtA=8JELWlp(NoXVQ0>p z!OD?UYI-;h9VTM~# z9L2H3A3I|~Bqd8;dv5Dk(h#fAlRy#FPZlFdKh{4v2ItI+eNcqh5$(8TgS}w37q6~; zp_I>4_#r9s5J|Ajxg-AQMF;>+6csh_ z@D#3ql!~aHfidIk)P`~6caw013x7?|016qpY4*=l`bk5`51u<@0Z4_ zQszzn;Q7=9Asd4C2o~PMcH?$?3(oXdp{ORM0_@3TK9)1J8_If)&8H>5t=)U_F0G^% z=q#(1o*%yAH&Qx((H=wH#*)KitKcX+(ybephURE&jbD4S6`Jtc&(nlX^wG|w|U)hp1rWW0`_lME9B2QhkpvD)o3T*Z>c z936cPF_>72HRx4cIgc?%Q!_$wS1)XGCx1Sf{scvcCcWeTKKEi&F`BjZUbpxdC zei_c3L2+l z8tPWsJB-!Ay`+;Cyfb=wBgFey)!&tQ!cV4j)HRcL##?Jf z%l*fRt>pnrHyFIN)ta(-(a$^l4Vji&dCY&$;>NVe8_sV#YVFnzQ7tVfsh!)NO9)ZB zxgD$NSSV#by7%{!FC9(^-fOOPRWwl{b6QCfPiJ^I>sa_0J1{!(xYNyqhel9W!oxnYtym8t~KA!mmC%{ zpW^-w6W+Dw%NoTFWgk)NCIUToT^Hc(u;t z&SAptI%3{YlV?Bc<&A$W-SX{*lx69$Kmd+ZgwjsLirl-w{zh_SPkrF?X7*FegR?NJFX^ z3^M1jwy5*^+s5YIJb|4Pd$m?O(lNWmcS+N=Gar%OVUz(|23(+6bxgo>6gMa$SPzvd zvt=UECgB`7Hl}4s1@~Ij*?y>+ZfT^>%ZOZdl9QU86&$}kak3o~12&oJrPo!)tXtP= zDvnjew>gK&^U^4uBMhZY-urPSzta9WsImF(j^>H}4}foB@LYn#Ub}r5V1`0~W_CDH zH3n|6zrTWrH93OuV^eI4j5yNOiX%PLu};Ot0ass>xLTp!-!O#}i@jCK<=mb@-3u#;6sTNZ{UsPVi1q>;i`$!&* zcDLUmL$}UXeu!)?rC{dEj8yk6+_|n*&gq+;wh6z;N9H2srRh}#y$|L4cO^414W^~t zB^=JtlBO>4MDe*#QY!)<0S!;-cECQS|H3!$te|fjKk^V?-Gp)rV zZ2vZOn3OXH4v1oSr49|Swpzf1sjzAi?ifT>mK~_1+dGnzU5Me2Y-%dyRjJa`!;GczzH&1) zk^i=6nKoBMxXysmj(<)@p~%t-j&K;niD(tg%zWH|BkJN@RqDm$Lr8b#H^{thp=G&n*XBc4 z<_{e!o>AL3*6nEDY9~}^*Nv%YhRg5-oG1;@8(pe=sX?1LKCrQ-@Y!H-m+XLmmvGlo z=|_UPW{Q4tx^^lqFQ{NUcT_FK6DadYMWT3PU*vGlOqBpK;l6FFr|c%&V=|vyzWrug z*$QMBY&X<8`oMqp?nN1FR;>fOWgEFbAD`f6Q?TENT|rKZz@<~JuAq8jIluVL0(^>L zo=%GY111{Lbr3D7O_MoF%FC+@(sM{b|M$*lldx>eb!v}|e^m+J`lF@PqVE$^CVv%n zk7VW$GHAF>ur|Fp^9L*KPme}JJvz5RwrH1b|HlTm8V6n`I^ZJf-iZ{XH!CAcs{?#; zfs4D1ed}bHA3#k!AoWv z%os_#GnsB16RyqJD%=p3e(KLN(-TyQ*@8Wm*UcT>QKUFZUyd4qso76BacXWpIMvF6 ziZO6GIXoF2>}R)0R60x)Cl^e#23fVE&JEpa3Voh?1%sp<&Rxk6B;-NfuZkckj2_Q( z=MwUEHT=C&N?=}ECCQaclaf)h#Efpw=`i7+3^Su&D>EvDekA=~87$S@PGIdGvV$mk zS$;o%3XYoYsNqN{8a+PQ$>8c&zEQ1oE(ShideszS3@D*X==W#p&u!s7rf#WRKayUN zZr~Q}J7e6EiRp;PbbV+#XsA1ddj=EgR`hl2=OOye6IRK_xePS9erlF)mBgeZsVETb zBLaDTK?Q!HNP_#iLpJiVU*1wvWPUwkyH=MMO^0niSuf0WighNs<2&^5{1bFv+v3?f zil1mH%>&o^7aQpPMG1K=vV3&~U@%?V@`h)avBur9$lUPth#l1AT!LHuhv6W6sEoHU zY3myW+*`!`6QOC0-7I#U`vUQI-foS}qO?cGBh%K3DBkb!yoqH5$UsAR$Xf1Gzm7S5 zJXk$2idRDZ8n5$s#k%;;%vt=0o@5C*_+^{A*~sy1qb8H9Q;vuA%G{bC`=`WbRd;`% zy$$jxeGTMO6oPvhJt(ds##Q`|pVE2|zZxY^u+2tOydO_~$)cIpJ%woK9u+ba%~pY& zq4@-6e@h?cb0z6=S{v=O&Zea^DxL^G3^_T6B|DD~h5bDNTQt2QiF{$L7~qYXOs9uo z2`pjbH7^-GO0wk|00SA1xIh~CFSKEHWlJ%6le)+`qPTM|F&ZQ-+C#4vvzM&X<@R6g zsy-%W@YU< z3H2_?x8`8LB?4O8%^+*dSJpMrc_97$*6%5XtO>krIUW8I05wg^_ZJ#9=4IxEvH< zh|&y4x!y14#rzk|cR+I3aCOsO?nE0ar{>S*=cSjC8fj%n@PPAHGytw+3CsjX zOfFfFT2qj2v}1+C+RpvBs5fGDULt$ePHEu1{V2%22pUf+6#IlGSNc;d`)3~-rn>*v z*#e)XGNy>-WnY_x^xFN#2k2wbsX6&?v<{qL_@8A=11jh0-(IxbG~2YlvE9`FKKL&+ zzjDcc*0BEbK>zPXyXOnLfI;SOvmd_i0-=6JDYf)TQdViYoGXR})$w#!oBUO&=(ICV ze3;Ct1=Q~GqfGoxJWQ-dT1jfuhhu6~-y8__JhJ~z#6meb;!6VGk-^UiLr;$znH--0?>l&Pv|_ z_im1fuu;aIUd-NBXZ=+q`Ql%*Xt$CVBvwc5_`xZHK^ZmvsXGJQl`D&?e8G!mF17{3 zi(sa$ZKadu z8f2+YUpq(`+o5O@%jNJU5h?MR1GcgB1*8$QG<&|2T4b>%v6?4L=QNkyCC)HeB zy%91iC8EID*7A_~amj8>IepNESp#{R0OOafOKB3C62_|4IT)4{=Lrjcwnlr<3HG%k z8jfxgd&k`^zyRL zyyWlEF2;XzAGe{Wb$-Dkbs!@L6$(MkB9wS#Os@Zj5pyaz@bg%3-{sP_pR(VnT8~Y4 z{=XeC+FyK6UHu1W-1`Su)PG&9`3Kk}ssBp@4fpKIgaUH*8(aQwcl&=G@4xo6q%sOb zu))4L1Xp>YU`fA4upJ^TP)0CWL91!Ekq|Gzt7KJvz-hwGP{EZg6KP#?H?dZ5f6L38 z&(sG?(WH#zai0-f*zDP5S`0jc&DRmf5Aj!bt+En3{|l}{Erut7>Ub(HK=|%)iBs&; zbW>U%nb*k*o#jUu_i93;5`#(M3z!jugDw+t^5f1EF~m4OW5HVs4L5~?pJ8$oq&5wJ$`D= z^NYN!nbMoGmX6orSv@(xT?6L&R3F99nW`7_nu_QPW;oe!Pi5hrbQB5M?DE)Dd^|1$W8v?+b9n2>1958ZYNxTQ={ipXc41-5D^xv4!}#Vn~{X z;f2TnL$x*rUXA587LF_<(Naq!fxZW5nmy1DYiOvkHNb<3)x8vzH)FfCz0A0Oe9LKG zZl3*Gk1Mz{za13QnSwAi&F<(0Gw{XDfR%>RE+1~<;{%mZ9D(M2%!>f`f+f1MGVu%e3`C=E;pSe*fs1rD|RuIH^jg7pDkd}-T zmEyQtW^cPMi!Ujv_L@%&UN4=(5pAL0J+B^;or7M4t;+&+}U* zkwh!zVI`h&nn2}b3Um8SkjnE>@%#sWsF4<9WkECR2PZv(yQ_`DeH!gpIbLPy@GO?d zbJJ=Ia>Q#qRVbPtD{yJTbApaa(Ul_(ZcJjZlkA&IMY#4TX<1WU?L*K31%~CK^hL}v z>UKxxeWZ)C?NKEb2WnG1$Q&zb-G?m*TlLTW-Iv6I4xnl;Epg9uX-`eTPoPSvxY8bf z5cqN!81%@%^NNqax3G_IZ3vK11juqIJWfr`H((gMBrGR#KfHEp;P?H@Zxn1+m}KFd zWM-cHMg}rg<~gp`7BHE{%h@I}^a`?ctCtg1G|xkJFn3~1WuWbRN24cu$T?YyOh;bZ|l97dAaB&en1DH;lNP4 z5I^8UiPf517Zo{z;{nO5Q#j zQu=Y?<@U|Y`dy4eO$z;>Wi=W6j3j(ExBCPB8-vG`lY;#uT54-NTLfuSe1jYDdo|!c zfLY^w?B6~qo;L`lc=eoXd@5`Vy%wtAPIRYKuq^#=DawvMI4y*J)3!h>@}ca6ZBiQ{ z4?wt9Vr{aD9CD!t<{K8LIS53<=2oqFC#a7doF&I^U5Fg2g;A)u*N8b>BaXL3f6)OG zZMN2bS2G8E5S2~z9&!jM%3cG1q4yTJ-5h1>Wa1qUgVCai2d=zW*sv<-JSZ4L?VIk43tyip!WoA6k5*@5Fwe zfP8L4&3j)S(mvq7#Bx;s6Q#NTd7Db?>+iLNLSQ;nRGAzL_q41I`j4Uv0Mm$l`5*g~ zC=m7Z>vVAlF>kR}=3KNc#)4uH-w$atN+A8ipYlr@5;vRrulcwfORCC(AmnsUvsVCZ zw&TG??IY<;)d)@>BoM4GCnHkVC(VVpT|xd18ypLOs^(u>L}FFJ80A$&`yogj5V2n- zT&EvB0s${qnmv|=iGA4zmiLR-fZ77d72u(h@_j}U1Xd)HGq2Ja& zK*HKAV{%IZTK++S+bE^3>ti*8W$v34?W~f{AIoUh=56;I^d{{5d}3q!tVd@FUSZ7|_1z8}!NTnD+`DZ{hO z-d%2?TkeGU1pK%E6cIoHfH9U^@`A>QJ)Nk2&nWNeN||Jip4w#uo`?u$vQ{g5I$NEZe@L(4UPolnk=pVwkBNSi%|5Y52b1*!s%Dz15;$rv zqyt+WJi90_Te|_8UO1%7)TvAvf$4cDlfuCe@2}zT8*sqB56CwBsfVv;_g$j#@RDpk zUmwBG!iwnFsbrJMu{`oiIM1#U$(H%n(AJf+s9mz_5szVxRb>BXh#^fQ$R*x}hPU_T z;l@_D+3&d0&zuR$Ny>N(Sfd+pS?$oPw_{G_P}4SP7VnoaD1nu!U2Ao{vYGu;wDI~? zA+MmzgKy=tXrxp#MUBcrkSOY4g4Mvg5W)1G-B?0w8ZCZ*$fL2(KvS zhNzV!ltVQ8McMzPe)MyqX~BA59>H}=N}gAG)1}owZDk}&2g90A8>#F{X%tLKMrH%+ z3p*)_%t?oggtz5=ZFy==TbaQa-beBGO=9Fp5AQq$wNNCyEeNORSFFtS(eCi5ptoHdy}vByzSR~FPJ zG7e;Fsqd6sjd+syAxS6F#euM(7*Dn{V#Pc@gWaLs>Dcjfi_o0jwk1m;y?L7hPLNzp zUJP!M>$MI;Q+0TA8c_63$kKnddU;y?Eyy&^-niA>);pj$vNv!Szg6lP*%0xIgEV8J z-OXt?6FH^+M6iIvp7IQ03d68ronH^_?h;+TX9y)(j$*rfUoB#~NQ+ z9f=a2;WrrN|D=Y}6~7WZ9$Y;3y#0Ct8!YBjM_1);>k}U`HXeb*4riy-1e!#N&ECVw zb(5I0I-40S@&7DDFl!wIAPQ+;M%qqSG+TFl5VJT%_LJvcz#*SX_$^!=J%a<9i4@~l zBt1|duvm_LQ#lzZ)Jx)&A65KPAPS=!E;3jxXhUu~37@qhlW3C6XVo02+umZ42hQq# zk6X3BD$?mV1Uvc>*_3r`$SH7k4VU8irzMtIDqM*ZI-ry^BfGIN?Of)sJ1J9@T3^_|HY^IAJ(!`TGD7H%LePdTkHsG@@ zJze;wrzegSoINgNasP7s4TlVCFt3PMnH~kK%EHm7G^C_nG`x zLGgy^G{zipfPh95i-81L(Gej3B0{H?xpSttnn)1&3&+|PTC>|Ev;8L(=A(+U96!J(%!FqCB?=Id zR*;pbCq9whtIDPFX22vb4>W*XIVX>@IJQEe|LJZMQq)}dA~!?mx>8<(sX6qlAPG@vh`F~tg4eI)|?qZP5_ z!%EVfj4tL@Ys}%N&#_Px(U3sEnfN~Wo=&E(5%b%xHnofiVc!(@!jYc|2UGjnGfE!W z*b(Ciden!*HDWmJ4xYeNDAFe(2Bz4G93JOm#O_DYPfO7%OV+xrQXg=7Y6w{5#ReLj zpmqe|0AkXg@p(B1pX7_q#hyRU{}%uKLb6hfaiY(Uyu3y{$c_bzjIrWu(kK!GvxvDe zMYTYgVhT7T&78l`8Hc?h0FB2W4wc+uN%1WdA;~EI1K24e@NHMs*9WpuvRfV2mXr~K z+ytu{`B5wi=z$=RatgL}(d;=50|c8RLQX}0p@K;j*2oS?{9!@s&7u`o@w@N`P@{&hQgoAt4T$67P#hmp~QR-K*SI0&G_ z0K6=!j}cST{49_Lqw=2g_w9PIcO4licYGe{7$t{BOq4x)?B*FZYDeuiR**PlJJMx^ zmXkt>Qh-cIAo^FL;6dz8$!Bq>hN;)cBYsaD1~CCy{FQv5T=cp;2g+mKDd`Fc)A&v1 zpNe!fyPm5xfDM4b#sUDK+OjzSk{kB_uCRFIri>ExLg!4u-X{`jsz^@reC0#^e*;Zl z@i|U^9#NXokdRN+3{6BjTM-&+@hLcNq-@hsLQvy?w3?C~(I(k0#*dy?WK06Ao&{U5 zwsKdYk#KnE;7(8K1x+b`{m|%dHilBWYUCggj7EAK%&Z$Ibho5Z$Pr2V4v6NP78e8m zfbYWc?(P1Rg;*0)5}CnHey}XIGc!*fLTt6PDzBh=nMyOC1caCCf_iJwIHFEy%boH~ z60XLD+8(=)a)zL-jga#h?O+jBo;C*{R;n1fI9AulibU?an!?3% zf)L$66Heo`&4r4EJi!CJ({E#l$;;Wywd*S%p`gkp!+5hcTGVEFoA{cGS{29W{By5! zFVysx|IXWpwsN zlmcER)5CS9pna?R2AzgsTJiYrITW#?ur3Q3dvuQs8owDkstlMkvYuD}x>Y}(euTS* zR&L+a{@a93t?T!cfJy?akiEc0{YtuT8B+jF^TSzzb(2p@-RC2p@gY#qQ%P8p>Fyw1AO zRU5y8pEzk_$eyLuO`Ba!D&(TTnH>`h!LUp!5g>ZZ=XRB-k}S6XSN45lhyg)8Iu1`0 z3+HcracBEXm%@`+?T&xT?o2XgIxIS4< z#xjTzcnM>`HVb0XStv1cBgUyLu(r`Uj?56~UmYBd=Jh~5+cowK8_#Et8(y(^BIvhf zv)+nrbI~f&P`(S%L-^#>*ko=b7j~^7T?nBY%Mlfw#l|TGbLaemmUq4{E^g*40aSc= z3jql)I~+q9t?YkyzFMYL%ZFKeU<(j6`yqcj13dEiPg~~msRE$M$^a557oO~QxW%S1 zg}}gaLD$twckzXdZCjhuXwy_m!51x|<83|F*jP35AHliE#Z5E#j$yHU^7weVhg4`( zDPIWMud@7I+2WO042ofQ{T$860$|)YV>3s%2l^wGkGcz+gW{Mp%Gcz;D%#N9vF=l3zA!dfe%#NAaF+)b@+?n^@@7%g|r|Q+z z)J)w!RFX=qy}MWUUf=3o@W}}Z^D({j06c>|fi>|Q?!KZc(_JChnUH&^Pi{DHu)DeZ+8v8is*|kux)d#SnPL$Xs?tQ0JIpq5!v~P|PlAr3Cbq<6>-zA$Y z4^ju0PX!q`c+*O2tWO<@yR9#)m^_BtEDtkA%ACqj7ruc~y)ctA4vO`mzV5^c>?sfW zh&Ni>V<_Tp=-Sj`bI@Xl<1Q!(4S^Qf;QMIS_j;$fY7?=8>-61oZ7X$;(lrVB2L&^9 ze{lZh(@K_HU?FH+A!L_JJD9fpHK&{eMY)c6wET6Gj*~-(Dp7kzfoeay?SrK?BbKvi zH1=K3{@#wgXXX=PA^u{^J~iPQ6Qx-k;_5WX2QqSwYcus*aU@u&KuQSQg)I~UFSIEG zr0wiv{#!-fH7>P5sKx~B1JrbDOM_Vl^!5V`6-O#_*~rviE*tSnPU-^f?Txw#qZ|wt z6Wrc~qFb}t(_ItMD80yH1_6flAxsl5ahckPZo~?v)HOLW#=# zbj@a99bW5}OmB@VhZS#t0OBY5eznzi9eWwAbfbaQ;Dr4Uhj-N9(=3y_AW&WdU9oagJ<;CEI9~r*DB>+=Q_%M664vmFaCp5 zRY~!d>0YsJ^+pJzjD$KtY;}xD`4`e>c9Eq0`?gpj1n7%bzFTUBsGL%1X?-RALr$>|m)b3)wt_Axk{cc6`~|;8bXdN4eYDh0?GK6to}hkW z!nyM$mHE0(PJ5M;XD{?Yg>*FA(MD0@B+iy@O(_-L;tYWaAh-Y<_1rKc8BY-k;Jb8Z z?J}Z;=vjL%2L+?O#TcUz=yG_bu2)AvW`LD!323X9zsw zIQOZ5Xx+(LW28IxAn9a>pMp(#&6?mTPHocH$<9|jc>vC=YIdmgu*mV?zS;ah)@{A` z3!P;}0mP?DxeYXvcI85w%5U`ZNXT#qM66_6lKuXZ`yL$a*BJ!+{#NEy{?n2?2JUzL z&wbcTO&^D-7pZ^AkD-k{=xC~FloYE(LWg$R=rkxK@PWzHrvgRH){40GT=yJMdw5#R z&3qiGRvqko0!Vazx;!w9SA!+`lCGQlCue01Z#L%cCrQxZ8XW>Osxnq(OxUCq~ z|B93IgBMZ2$hRiSf?YqWRy#{@$X(ac8jpr@Lv*}cG{_M(DI_sGfq_zcXrh^qUFgi> z!9eFbuO#>Ot>>E&U8C6=?iFj7Z95aZ^^V@vL1-LkleK4q^Q#BFW>6oz`mFyXhFMim zt+^g$AgZQPWTtv^cqm18pnS&p9YIEcMsB2(=-_yi_KmVEt6p+!FApy6^nxAB9bz8* zqUEf4wDJxCWft5AEK+*+sR}HTj{C-{=R-?u4{kGEqvC*88TVv0jZ>z)VB?d4&dj_=&m$ z@Hy0c-!^%RbNm41+@~iZ-L=wcs#hp+)H5Pp-!)5RBN@HQZ&f*x2vdoC@pqr-t=$w2 z@?HtS29D{KLx@}Bw$k!yr$w}9`l@-(s0cY`l#=k*PcrD@6y;-tyJd9U2MY%A(ke{gqme6U-%>6Znf0(NO<7-EH z%?gH-eA2c_;~`IO5fzT@$l67S8i2zbFIOUpSKOo)A(tZ|T!fPgVrezK za50+eghLtj+xA(o^@QIF4hMV$_f#f%6L;UN8d6q&P@eRh>S`u0Jxex%13Gy~n`@P$ zd5kFOuTF$=i1pCV>NqryMYw_@fV<7QH5CxIymzPx$eJ=`f`nD@cUf5K*nR0NrY~pr#7-;bz{Lg~lxLTv(48}7qRH;$FuLDcX`TibOgd!tIwV#&M0SgE zfQ!-US{`i%LvA2yY#>I}D3fAlbcpNV?_fdY;ikGB#Z|;XHE+Qq=3z%Hrbb)2W0pzG zS`CQ{(%}hw(4eCft(nRi)k{yT=}e>FjWes*1hb2jKBJy5=kbr?R{8N%n3v46TSecN z)4lLR&BKaD%DK&{1C+%UpX0<^(pz+N!_*}lQKGX~PZU2{ZIQ60nzP<3T_Z$x@`hwP zG}`5tuLl*tRE&!J3KhB`z4I} zOK@svM%Llx0FN~J4rq_rG~skovw0h&V=3X9-SS#|-%Lr@_&WDs3c<6?f=_meS zY5t3~XZ0)_RZ9J_I2=V&U36R-4!C)kV(I-w1;v$~Hr00f`$@>9ODNwsrc1AT;kHu~5 zKQ_bLizBiNn}HrEa8|Qi&~Y@}O^swCvmq91HO7#bRZrqdRwrta=1AsVh?V8aql7nY zloD8nzZfA=S>4C0e9w=aEA=)gCxG>Gw|EnB*AVnR@;kreH&W>n)7#OB%|7?j9fS+6 z(bpW0Yx;gXq~j+Yx;3&x#^nu_=20h*?oyh$PW%x~`}??{m;fs(s+BJ8=uHwb1?~%> z?68LavJXjQf(PRLSnIi<{JV-Kt?^EU^{ zQ?fW#5G}bB4*5SPh`}2@63-_6I+??&D@k_&( zdUakI^;z;ldeVOKO4@0sN`P`Qs25<-&^UfO!8l87O`W)(7>Iy4I<$UMj=(;c0{|QW zFzcej&NsRBi<;3~7iQ_(fGhoC`ki5?31f^wN0qA7jo>WbzgX4>mBPT@M%oCJ)l^PZ zs315>R3O}P5Fe^9T>0b=Ap#AotD=c;lu@qX2lRfols0|Jrf962eu%Hz2dQN!mNK zu8an+S=duM5&6%|a|^Gi5D*Z5(|n>X!=V^MK%9}1onR#ftG0(g`^p7>1Ah6sM`-p3 zkU~I=OQ0$BlV5R%h=?NSsIO|}p*xvrY;o*=CF2DA_5N5ixcza!LxQ?IsnF@wVRrDR)?N{ND$ zHGQK7X#zxJRxGekQ50jpAa{#NcAL#3zxZd#6PE!ACR*r>Z5> zTe<~uy7+VQOw4yM`BB{pU0YZ@fszt(MI&N=;F*exYYV*ziBYtaMCIxJ%4d=uzmsEK z0fL?LTGvJUXo`~cQd08nDF#7jG!Ya4I{WX^kWc5DO#hcd}24LX}an6W$sVR$3l zi}6)ND#Qo!<){t1}2fQySC2T>`S3P0=5*_N+Od00NBMHfS{6K`15=ZeA$Q5pF3P5(X-O z79MZp+Xl!L03f0Z3j_!!!^BO?Q-zvb?NT3PuqD=1t#+P&sknQ6L&0ey0MC?m~+mvJyjF_XqcuW)C_r=l1H%F>OF z%;;*8J7;X&t?qbW=!c zVeaI3hmyZ^o6%VR2uY$8#Z6^eLGW-}>LlwAg7m({vr4nEoFKU?+h&{7LQzDlPflMp zT^y3gnGrOWcoQZ1tQM{~D4XD`D%MR)2-lcrneqxe)37zU9X_KDPJ;RG5JY)RL=Fr@ zD}{J@@Hp$8Y9ocwoMBRnKgYZ;d7$P7Qi@v>z%w8Ex@y%dO8z1ogd)BLxE_?y=`nu~ z`O8Q#=*{~GqTd|f#Oi_uou^j_#YgVEGYr?JiS?S4IBj=2*OGUvkcjeW2pu)-FIOvH zsO#o%s%Yy-_@Vtkjqq?UmA={?ojYo7FDNPHkR*(z{Efij{#q$rk=C%sE<+v#A^Q&SHQXysK6!fvzf4h2=E5F+ruIh;f0r8* zmh(%AhMzb)g;#J*W$6_>VA(54_S(tuNMhk;boR*!#@DO{D;ez~O>s5CXmRN5aN=>6 z-4xvk<(LH0AO~%b6)0Iu6KbGtdfnDEw+_jkUyv6+waqx`Nc^qzeoaNIjULBWyMQW5 zLykrZn+KlIaUTmK9$4g2!jO!of>{ooZQ3_7IX}F0NzVyd-PLt_7ml&_+FkU(BiT*O z1815rJ=?BJwQ?>%(UPvDE=u$UhmDd;ULnUJ(3XNYPG@Ymfx3O?*b062+g|ql)TVRc z-d@Gh^>J>H7+uiIzes=}}gE7bUFQ0>z7N}-~;}} zrn87I)}3-x6^TG`%Qsze=gj5yjW1WA7^IUO6W#Y&SodVAy;?O1cb>9fqlNxh!p@`* z%z%YX4{Q1vH}x5G*UYtYDz!qH=0{6G-U$bnz6{P#+(|TH9|`+Ec?IB* zu8kGDGP94gJ0enwvL)E$sD3J2PEhD+=+U1Wx)DY+s#rH@)%M}{mE3S_9O})TAhp0w zJa27KG1#(%1mU*{j_`rmMZvyAd5qf38P-e=#@5&I3e4xTCHEa$%$63-l<|IBFWF#6 z*9MoH$+H5gdkcih?d3LBvG`vF<;Q-h$6fqY6Q$0dR{sD{^>mLT%hnXjPO&4+!67uE zOs@$t&we#sJ3CV?%UbIME>PH4)uIPG=lBSUP&cQW zRY&c1)NrxIQ@$+K%({Bs6{GSAsf0U}7fRAGn<ege|d$+=d>;+Qbts-#gp81XN$?za11eGxiyiOnM~3mfOOP)nkE)5*v}LH;SYxLPm$CXsSNW z4uSjDS_Q9&G2)0$$sjn{`r3xUcwa!)9?mAoDAJvqy~H+!m*M`)!2LMXV!Q z4%oW+W6>p8|Eq_B_I&|qBV~6mri+0xyD9qtylv2#S9BRoHYC7Hi1ssDw;*NDcyORlXVP$ZMhHJLj zbhK+=7F(1m;i8R8P+XbB7T=S6r==<=&6K@0)!3ZZlGAQtstjReSJ(NOJ5i)zD1OpRw1nrE!1a3y+PQ7Gc3{jVE(ClU}jCm<$f|rJln6XtfR&HM|9bp$K~W29BPPzSB&gIMjNhts#iqzB z>rU|iRAXe$k_u;jpZv^N(AK%ioQv1LXH=D*A~3eZ@=fY3_aRPL(@)se>hBES$VMvH z=*cpgY|e}QaB*oPH+4$6XN~kjs?O#=xsGfrD~UMgIzL<14lfsN1)0H_&0}T7_EDhW zs|Ai`^zQd>eG68lE>q41iQAY)o3cTdQ6U1&Vr0!}JV#fi7hNNzHfCbairu%NJ{BQJ zmxE@+4%8wuKhVP`0&%^4w+Ht)8h||d+-lmG9W_U`-eca_*`a%E{m$sHsf;l`380^p zIZ2H)u-`q4h((z@9QTM*K%O2h8{(4`bm_RXhuo&JTzy>z{wQMD45xxPA2Hf@ zL(-%Cr`hd^+Hn#sZZTlPC_*+N>4HUKPp<)KPxeM1p&GCn6DeD@?Q@wfiw+PO%WG%# zhD_OS!w`w)zt;c6#C-IhYvgL$_K9`TXb)GeZ;w(SZ`K7@zq6V7-qPQuKle#PGp9kM z(7;(E--+>;Vv=q*@zl43k`sOTL{z*}%yDh&O=cifT8@i|-LTh=%cNi&wd-|-bXNq> zg_&ApO=E;VxJ^?Qtvt zLu6r2X$%kSm)Qus_VN!M1IKX)Q_@`BtF4m}Lj`^ti4T;Gat%*1D%`elv2jF0q#VKcU`lZBZI59Cx3u z=%1P|thE-*ihHS;hHa!N=fjhtYdzZ}Lj8L|=Dp_kr{FFW8da$+ipjymygpV;` zx=2aqnv>DrYv}f*Xv3lJ-ZbCa=(gNlvF*X1SWQ0*fj&0TX_6z5E8WNK-)zH_V^`3N z@k-MwrH~dK`$QI{WFOXfyKIn25FDo+`JNW_N=HPCV?ccm-p_%h+%;fR-zk}wi+ZK&2nDY{Ot*GB^CLPa&;lh3Br(NAwCD052s z$2n{py7EjHnIF68N>8c=5v`E0RrFTVvUaR8bVZy~?uLAaQnG0h8|79hF)N& zX5GhbX{?E0qDc3vQZSWqJ}$}~GbT=Fg|H!+#M7tN2T8y!$KIfPISQ}`(g*sR zKB8=QwRYv6595{cP(Qkw>$8~l*zI4CWdKdmi(_=zq`kWQ>FH^dP5TQ3VUmoptzMJ^ z-D>$3ZoYu4PNnKuDnDzd!>>#0)P#y~ULz9Yr11jR17Rpa9WvB@4Gss5MU*Eq1kSJr zidG$r6q{+#`$wj}vdNf4$^lF=pi2J=Ri+IKfr70M3^#^2BU`rhpYah}`cxw2Aal|> z7Fgwa)<#=|tJbMB?T2*CO8`v@pidU7X@5{GQ>?lgsqs>m*+Ils>IV+f;T8mbR>a(z zif(ucb_tr2A-jS6rnFS9j=3A(K#g{<8zqkZ`gMS7T1=RywCFR*YeJpeWLYmW&VgG_ z*JzI25U|k^>cEQ^&7sUZM>5;Qr$pA9FCm)3wHhV_7&aLTb9&2#nZltHDe>0>=7N?JW8%9RyBC8wgs;xX6?Tv7&_O3; zSMHgFe*pKXZ>eHyB*?1wBtPa3e?Pro#M=YbG>(A4w~$C_j(~l<=Yl_g@da^`pc zD!jwtbK82QO9g>Gi(j;a(1?jM?#%QXcDty?-!L%yFW%cP3HGrNRcz17#93Y<0T19$fGd_3fa}ADQSg3FrG$R{fHBq4 zI7d3A@on{v_EZzgv}%oFy%8}3E}E8rd^H(VvQcS_3Xt#eH4T*$HkQ;s+102ulrbD6 zCy9M!=0>vv{g%%5@)jMC9cl1}0*59*iACA|N=MvF79XYDeD@!#Wr?+T#iQZ>$P~~K z?e3wG-E7lcE#b8jgA~-;lkgch2ItSjBj;bq4SC3-`D+UTK;k};3*K~9P&{7R&&QlmVE)-Ve4p<$jq z9%av)-sGBhD!=H_ncB19&x9c0aH&hwSU24Qmd)dLi{hyTZ$Ui9_2koo^C5Ne{^3`s zv71I2;KnQ(1HCH7Ssa+DK^soUthk?rBrkjpmBVy>ng`aV^H7VTB2|{MVwM1i0P42( ztM?nZ=$nvpU&C9CR`E<*!oS8@W8kh|VDX)1!Z50cG)ic@VX7;Wn`4x_5U#OCEcwVJ zNa8n`i)rvqfOiQrG?Yj=xj!Q_ri1|%_4a*3xN_B%3i3cdJyBq z<-I(W$frXYvoGGO689sE<{P9_?M+tqd#%O?xm-5%2>mP2d)n>Fl+eoTg^5Ti2w`l4 z-4bZT;w5oxZ^7rkl&iB27`Wv;fM zayI2+_v17g@AUqYW=4*w!153Ij^E`3YXh*2*`3Mufr2?d=z<|Yy%(|%o+y_P6M>so zzr0&LhH(b**k0{Q#fO%kUy{O*GtwXY@*$iBVvrkD(T4l{4hPGH<$f{$y8ii(tz-K-^(bbqQ-Q~YgRsRSG>|;aS!3xJR_B#BpRsc zS^$oNWh-D5F;SN`K^Eb65CO#e=8wvCL%h>ccC5o<3W;`zc45`RR%f8^FX)Yss-7VI zT(A&f7i5zHs+Ohx?J!oeZKcaCtF?gC>|z^+%w^n(6_=i1u0uh((l0-c8Gy5xC}Tt& z1qp!AS2Lg)`e|Q^*T0*MPgT;}Yf`2wv6^6~lo^AjBq5|sJ*h%*@1w4KZz-KL{`FW%KD6$0-DtPh?f)85w#c8TN-F%J4L{oxSr z5TYYyp+3G}3rO_>FIBA?S7cVW{_TcKBs9~Z*|TrW6k@HzV!sP$%kA`aT(z)Kl0Gu$ zn+Yxwfb%-N&r`!+M%2Os-P9}7%Y5=gMMGu0&2V(ILwLX4`)(3gtIzD`Yg1h@&wUcZ z>1M5TVKTzvM$C}|Wafym1b430x3w}@bw2nZSg9Kw=;623nIlZY%}v9aoSmEjvkxv` z>709#!WnLsHzye8Be5o!;CU;S_fvq;>pWRJ+fTVPn8P_1`@_8Oc+lD?#0C5rWQT;7 z4~E2w1KXfGM}5)tZR2nLh7}zpd3zeFTUFhXp{`)e9SvH>B$+_kpS=jwU&05KP}}D# zKp2nFbLj{1S>AOD;S(jQx@$ww8W;QOWxA#6c}gE=U)Pd8Y)$v{WxUsWvR3lm3)GvP zr&L!E(9Z{07HaIvEP6Q(@wO$yltB}?4ph%yZ!ygSlremSRcru+K`;RPqcv4&@=mjoEqh$tOv*J7P1-)xFIJ=AB+6|z%q6)>2rN0VD2OO5nv`U$0hubjV_N@WvpCSku(gCoH@J6s)&Kh>>ZoSke zr~O(vZ(L zbJ|s{Rj6t<@4UAj%8hn7E<}_wYp@Cg3>_!{U&RJVRwFXTQ_w3h&z=sGNcB+Q@nM6w zL7fgMJx|Wiw3!}}wne;>v^CW^G!cJCP4i5mxKU16G}Qt{v7dhgxFT2%*xB&~bB`B^ ziWgZKf-cGkOeInXpkjrCg98L!G~o-ixD`$6Fv>!Ocr0E>NsdUUaBPgj^!1X)W@-Uo zl83txi=A7NMEs^~{p@g;Pn^h`?}ysJRNv+8tw4w*7&BhN8EK59yJLHqnM;_*PM2U< z4qIfsggK_Q7!{{%DS;*YodNA`by&mypy8$QCq+87}rcxJn>1CcrScr zCzLpRE(ha1DHUHe&0I$x#9dq(v*v8+o?x2JT!*}ss6&SvyltYj$5d%*COVz` z_XvuFfD?kSKY-dx$0zUnLbyGW=dkUb)6TVbgUX(cbDSsZo}#fw_56GE-MW|WneWc= zZ;I0>rS82YHUZD1aUy>J%4Kv{B)^j{^Zq9&NAPiW~0Hug$+^_Fn1ULfTK?FG~Y* zO#c8>Z-b9>>;JQ!mtAym`vd4a&OgKjclLGb+0qU{qwEjhUnEs_ z6vPYrUeNCNd;#XfPOo^Woe4_{YuuISZ%F zhWn-O@ig0tXH+AG4}Ki4yCl!~IV5uDUuEY10RDNif6jv2D$C7WfMoJj*?&#>e@*%S z$xpe0o*$`$cqSIY9K5lb9=sU3dVl&{u~a}}iU@yh!2&Hxh0Hz~$!8w#MNSJAymz2^ zM(Vd+hY87#BLXHDLQ+oq%_qqEC(NTzSP2~t6`j+kZTW2gj893;mQ2Smq{-+!E=?xak+bX!VC6q{>R zz0c|UlBZqJ=ZZH*<1nJ9G8v0rngsd-5HkBNw=bK`YVMUZvEjiG^t;U}E7s_I*}Weq zwt7Ek6Ai+h@Wujl=SG{hyI%JV4d!${NrT{dC0lDvEDUzilJeTA%*rgO4f&EYvNC*6 z6m&GCZ$^Ok5;Ec^Rb9SMyP=r+b8WKp+x;VamE|rO!^Ex4`j+~jMWQdrJBu7sSRD<< zQ!yS%tvFrDP=Q|R%F+nm(ky<{d~o+Fz7p?>{m^n>1^mi<$6KW4f=kw&w@7NZQUjXj zr}3gpYS+lpL>p`X@2Qa6{tEY}-!}2BORTq$X>@_1=saL#OpkM*J*}PS+)5*7cXCOz zg`CnWR!`P1YCQoEHHVl5TRN*;Pjp15n%#5mmR5NK9|b%guKxfAO=eo09kjDroXS3B zHOVl$;7Ro`iZ`TFW^!V*cd!OOS<*aw1J{C?t#bxvrq#(BP9%$i9HQN6PF;R5MZKXO zO6@6gfZMVufHTDt_IRO?z9bBxvdO6ea7$?eQ~s)SL%({k$WXlR8>T-qGOgmAFN(}6 zvV4b2ipIzLrFD1E>m7FKvJQBnnG%obpGXrGkFm2`6S003=H9TQtdINhCFyE>-^dP; znE@5iKc*Plkl(@_&6)tSR8oM^6d<1rw|Ji2A`g!p|7_g#BHd_~vKx;|EC86T#r=HX z2{r_pV+k#!)m2g2e_*}dh1!$vabfM4Uzunt&hjb<1^IJ2Q7aP07j|RQ8Mx;cp&n}f zZo1}p9$@_gn9dcJAe*i`w%oD23o{0%T=1p;mS4&d-f#OGB0Bf(o~ve@4_47 ztK572r0{K-;taQe(;q#MAFU!>s-CqUGvACe0uB}O3mv+) z!BE`u7xJ3_qN!Ujh;*&vSDg9RR{tEL*oN1@yKcZ=a6j=~(Xg@`{rEo@gnwkmZTM^J zzu6e+zIi?B-c++)=l_(Kf6SL$!`UB$KTeUr=X!juZy0WeC{Ol(+cnHjg8r4iWlOwP z|6MEGaK4_B{K))8yzqC|<7evAX_A|@zfCFq8}B#uqZCq@Gtv)Fr!W5#9gXNX&2TxK z+|1wccfR^RWq|22x6N<=kitLK*ncg=zn{qey$caMPqog!2cGuK)EE@FobhlVm7!9d zF*1qBzr4m2!tb|+t9=tHVMqz_18kpaNsbv7&+LFk+i}vmEL0jEw;||=Z@Bc4IalJU zK}(|oisM*WhD)IX2|)4cw+69cOByo+uEAh8Wct+6aB6thU)PZODh&#Jr!gt z^63M`2XpO&aUPEge$izk%J{H29Og}0l^Plj3Kn4sCRXsq0SD@Cg_q4`g9G@$G~qNR zn3dn|08i7zk(`XKfayWO#KuJ4lzszL+^DQ7tJ`eXpDRNsZ#*e4m^40N;IOqMs!aHP z+x8Hes*fzUwd_J`&!y{c;*J}n|6z*#a#(ExCZe|*Q z(IEqNP+_*E!Cy18rM`_rr%8t05pT4IQNAh742)$U&{guWCe1^E*-vq6&GwCfL(SZ} z{V~cwz5Cyai%WS1sn2B7iKB&<>^9UUxtwsuWTQYh+;FleQj?5Q0GpgL1Z^OAkF4H3 z)a*ew{sd*22*y4CE9Z7WUsflvqkZJHc(lVu62tG^eH8|(uU5|@dGvZFL8eyyK&C~V zrovf$+EbqdRyp>8w7|yxhR^Afy=~+4To%gMGYt+bB?U#eL2?-qZ8jSnQU?<#CE+`t zvQ4m6milV{-u}LbOxl{p{{awK?VnXvgs)px#=nqNE6*OlB3vhKNgFx0DUUnv*3*>f zpKQtH@sfypf0^yt78Z})!Fo@2TDlh!emTi69KJ^Q1CVaFeIX%vyHk3@aenpe8Fy5? z7F1j~Rrp(V`;>U~`$rQDGQ3f5*PZzWJS_b48W+OxI8XA&?=%(9-PV5tQoL&&kK&A} zXJ|n2I_Fz_{QGm+QA3w#w@~Tdm+0Ad$S?e#{#Vbe1OEHS$RB{8>Tms#>zzLUx^CgY zJ7LWl{=cF5BJ~jdnb8ro?sqnrSr}~V{8D?v=8n*OmLD)&e*6Qttn`m=e-|*^=PrB9 zD?7O>`y0mu|1)7I&UlcFM8B5){sX|6e=}(Q8=fUQG;?VF8p{8-Q(Bv3hR56=159_p z>;x6h%)5`*0V!Z4^3JbX%>5h59%ODq{#~E`Rix_y#4I=2bFYf3ciwY<12plmfzv-G z=$|s}jNcu4SM?5vJn^s7`P=9y+F+Q*`2CL_{X;na%O<%*Sp44&qXh^K?LTS$A94KP z2b=Ccj`IJ%``3!!&w^cayDU5)!OZJJ+Uv4y(dp(Zj;h&T;m`XCjCDpJ)ln`1Jj(9v zxQk91N zh|nH#;zR8BZKoZ+rz=`5A}H40V7i*u9?tPoM$>YuT_fMydo|~JA+Hzu1(o8pzL9vX zfK&sDSC`(*i=WR=k(WREFBdyie?5rTT^d$CQqXKV86KQxayqP6`-Sbd8SnK>u7vr| zo%s*nuHy2zE_l-n@x$#R^LTy*I>K#7o1QqZj!}6Irj)Dw%c^J#Igp%r+;uzN-nKEX z#WK-cG^8PAbBj(R8ENeSns26=TGb?tYy56X4ExT4n8!@Lod~O7an9PhEbgOrioLiJ zl?`uFJ|MY|p-hFGRLmz+>_S~=gE^=SR^oJ{KwQ8eFA}6GW-kmK*cS*zPl>izC_-d= zEwjRq;0wK@AHPK~;%~G1n7`qh`Ms8(H*_KCy?d|i`)_LoAHx}x+2?EuFaD7;-^U}Z z;de8)$|<$(>}j#%+NMzT#l;X);-XI!xOaHqg&r!JQZafZa5dFOOtr$zzmmCnHsPLQ zz)}yUPlFhy%4_ImM;4cut!H8El#7rl43cng|Wk#%G7mx8)y4iQQ1us(uiunRD^iJ|%KSBrh*#OhJ&*@SseV>;D_Fp8b- zb%gD7VoqM7BNloeaRKC09Z9FdhEM_EREdj}=!ECU`>;eT2H?Kgfv>Up&SQW~XuBN% z&-&eJ*FLa|>d@FAElzMxa8h>j4b*>4HDifr=E#d1-Eou~*1AA&K$n1)T7l=taq@ju zc4Mcn%UjO42VA<<-IB}qGaC%fIM>R>q-cuYrO&>WsGQq{RK339JU zN){ZAYMrWKSxH`U#c4`cW#mw3DN?WZRV>o4hc7nFblRsoer8)prau&9Og33prtIWc zq8;ZZ~r?#zZA3Z{wc{<(+l0awLt_07-m9oUdH^hFlsnb`Jd(ohI6y_H{= z6Ze()(FH3017!IBuQ(Yvc4fCyUIwz08MqoL%ocVP4Dkqx;N&{>_tM*?g2wQ7hZ-Ay zs5{-QcgJn7DaCnF?oS+ND~Q5KuN}_5zhGbQ^Bi2gM#a;OaEI@y@yr(g=v#`<2u>xY z=mPeF4rZPoA}_*x*H`*g-Ul`eY}STSMEo?*Ahf;pk3IlS!i3lKX>exIp86K z;9=tgR-`Sf(x-1CDwO3ZM~7GLhW=8a$}ci11^-s}_kRJjrW(R4B1Oj!E(ytNP3X(+ zo_&ciTHeU?e=%8UI!;qga#T0{V5j?$7_N~Z>sUW0qrs0dt3es9{uX^Yd$fA0_)~Gt zW_r(zPd|?Cx`YGYO@3mfE)Zd@39n=6JBvtQf*~rQBV_$}}fM2)6SjEs|#r zX0jiD+uPQddr8B67yI193b8lcrMz(d@XIt5?VXpFa+1eup2Ga*fDD^-DG2dsS zcxedrEBO*T*eWnn93A-+JufIIDWqNQQ3-e)jZcK?~X<+eQlMy#23@cf+kHBuQPw0Ja z-7Z$K{kC({DwN9w*o);~UV4cWDzg|v;`n~AoeCrT_qV7hl~jb#e?hkY$o$cm3lMvF zY6fAv;N*d`6CM|PywZ;*Z+%G3U#tAZEb}lqBD)*qZ#~4D)5dw7yNa|iv@D%XnA|w>K?6DWK9}7i0UV^stW1Im$~9ybHLS z_-G~z$-Um-0YlhgLgd5PJ>Rz%-|~a?hFrJD>DOv5c{C0F+v7TARXoFlBXhmA)paENSY`Z1c)rGT=l}p@vz%%0QAsXkr}Q`)B_Fpas19{{i#`bE*sP zesrR;_8h+PKhZC1E3i8xAOmUT4v0Zu{ z_Gbg1kR9X0b#esCID)^&1z^-;GQ|fslv-V5>|uSs+3#W}R*2Rx4vo>eSGLhBcBtaS zRpe^gI@s6N;i{>zpVSHKSd7l>sD)SZ9o6RBxe6Y1L491`#1O!^Cftp~lz8bm_sNol zGk-ONd0)+qYd>H1m_yk$AzF9A(R*w2Xlz@XSXY`uz4!5m4vKlX{vc?f}gIq*Awd5OF zEt|Zy5Cg}4lQFTdFas%Dm}pbsDyfo!#6`OdZifN6pgnceEP8q>IIO8(QcYdnC-Fli zrO1E_GP&o%UbHU5WAQEiRg)oS@>gn!$R<_)(Lv>+OgU>~9iG)4<&Lq4(ruP%jg$(h zeF`EPQbR$GoG8rQHh0YagiTs5Lokt+Wm;^iW*j4P(V?V+Z~gsg718RjRo~0JKJJKE zgZ3W)CVQ3xVve!|-!8B{6Ubv#9|)W2n@zEuLsG5;@Jb(R6vFF!4psh6x2`;t^p2{T zk8<6#{Ip)Sof+-RpXEju&Wv~?gOW|1hRBZRbuj12>kBFRD5o(lU&t}HvtHo`QU>foy$ zpLe1r=D66TP5Qu>{QB4M>*oDe`I~DxJB}SZq7-K+JKF-@qCF!!sdRg%afj*J-f)j7 zrivM6~+6S#P~8^Miq~0f~Erf)3x61$v6(cYKaUH^F?9eNOQ_>Jg3KQPRC^q_$~r7N+jp;F zUX;G2Oa$!hLEe7+Eyu5ha=h{!eF~#b$rwC4%+me^(a9>>EdA6BzA8b9+=ISFT;tXE z2Af8yDnOZhITAhp0G`U?{iytJPj)D4Z-$6Hiy4=`#nkw-#dCPdDFlhA}cT>RTRDOoYYBA-pj}Bvl z`WnCA1$(qaNVO~^%F!4K5$*bdn0g=bXcR685= z!!pd$(S?-z$@eHq+C{^081nAZ=*n19;&3Km8@^p%{lMXgMJ&UF(CKIz81xph&&cjD zKNIbmtlLZ5gw(o0kkB6Zd&OS()l3;XRH?n1w1u84D}#l(Xf({pazCLGR<7`VB(6D@ zO$>j7Cu`c`$fs!irI;RT(Ka)EO}1yrtoi-%HchmTS#X!@!w@Ua+DUiq4!+Z*(R6Iw zpaULfDJ498yQpZ>t(tfddim7^&k-$QMY1Zgk7xRg?4Y|M-UN`g{js)zpP-U&{yEf^ zuN58pAvgku{r#3Avm(*6EYo4chc3cm>#Oe-o7(MXX})~1_AggY6SHT0vEhtlke55C zh%=9Hf!+~-jBn%+%W_I2N;NWS@?vUyG6~1@iIZ88<*I06^JF1qWTQqOQ1@8j|8~&* zl}KDblj@&ee=e#>f4Ri_3^(M@;4WO`v!gnO^pLXaDd?9@5{BOUs*sV^Ac4N*Lga~9 zMg26S5yJAlY(C39B*@^Xb3b$&Bif3g1Evad3=4z0G&!{iWkwYh1x>FUk`&T`*vtt) zlJSn~gx5@Bbp#c_3in!xAVo3%^|!^h;vhjO5(!(FE^PrB5XF>lCTF;dlop8^&v_Q` zRYQog#FqDK8i!FkR!f_}opmPVUMlW{yMWkHtC^uS4#HPJB^J0i5_=2J%a-PLPwz(L{wEt9X>kr7(mHjG3+Yi3B%8x_^fZ_``Xe!icA3GTS*HKS-CGB> z8OB?Kw6p~Zg(Ah>odzggC=@LYEiT2227q$gOP&u{KWq&kJiqE!^~-nh)}mKs6&b)TD4tqlTW^tuvgQ5%;n zAegV&PS8@rz9{4%K+|*3JWFjkY>!O$b12In=$r8956od_4cf#JTBgGyDkf7m%1a{i z!>gP*&m zq)&L#y7XL0uXBuSfBgB3EU~4u zUOjn29h6ov=+Zn&sX&0GE2j2D!x)0RO0`6H4H2^YXj&l{IJs;#Y`roT`0|1KpO&9? zq~sg4Y%V_rcnOC`_4aRos>hdDK&!P(A6f97;WcPQ{B9T2Qpzm6F^gcC@$lRJ8?QO* z{AQ0O-LLD75rm(#O`oO$J}Ov$xp(1YdG zfOlQTH}?%x)Kuu~$GSVdq6VTlo4mXlj%=YrIr)j;S9ApS_0<7n72gcfe=9yNX3w;_ zrvujq51|d*8)lLIj%Mpy&#XlVWa2h@ z^UX6&nLdqC(Eb>$E=RWY689WG9DF<@d6<7Ey&hheK^I~|YvA932o2q~d{d2BSPrG6&Tf`Y_Ex}jMXjT?KBw0Yav8~pPZ#7=6^eC3?0RIE%7|Qz%P_~muYm(_@=98Mt6Un{5I03 zYPGY@4+`sC+qjDDB(XLEv|silTeyhWWKZ*xGgZNL@X$(5-cyTxQ7WmA&++Pq2OPK(rj4X3J=(Oz5vYeZSsAjV z$v^n84tFbLg(6dO6yL3F=ik#XbOv4sfc-iUQSW1%)8+DPUw%uy^v^`SGj^%q0sZapvW`{L{ztL=P*&aG>*r8J2* zo=)7(<#HN}Q9Mgswtu}l#B6J+m*#8E{6~wvDT4Sd(JBh?s*iX zK$;lDAr-~Bo=EkEM;#S}61mO2C3}EvKr@B6 z9WE5VNp7vTppkF@?{TS`n?RF{&$=@nm}#N-^-bc)D*LLi*v^1s?zK0K+gfbv-^)n| ziO=cYri*oVfwDqZX0|{0V34;;j}^t+?;sl?E#&y+2T!JNDLxm)Bnj|IQ}K3D`#fo1 z()qNQ?!BQE#++8=N7p|rW#IX$ukk;u->no6FIuBQk|Pq^?l|#qmG_JK>n6iQp8*6! z&Wc!kJx6w-4sIO@mC_>=krj6)fd=jTw+Y6XC|0MNUXTEjt>NpJq`FtU%E3!kT+T3f z*vawcVrMsn=(P99FRDl5jghV4P)}I4r?GZ?_AL;#uH+@pJW-y#JkTEtYeZ@T zVAZHJ$s(zo>FY;R#pfI#)}$8k_97*?NE>3{cE~Zxt8u$V@KOnyC3o4V#G%dtZ-y`W z9YNhDNU^zdvMh+)>k}OXoy+s&Ox$`s-l|OL*ZRl%N199{ zO65C^%M9QOaDaz=enU{-UwmPoseb#~rT!1hmAJ(OTA^b2qsWB~z|}{*UNdw09^$0- z77JAAdL8v~Egx!ss3=lTmlgW& ziMWU$c^Vb$?w_k2ZhK^+)|oQT-}11viGRd#PZjj~4{vMS&m3Jr^Iz^iMIz#D^3;dk zw4Ih64!`7SU0`Dwp0jX*5%bnQZc`wIPE4?o?Z%3GK~J{!b7 zi@}-rx}p^Ij@6f8Nz0{VfRRKh>7b0Om~Qup2Mt53$fNpOY|BU2gV;OjxX15UzAoPP z{d|$MNb{0tf{{TYv+RGsj6C)|-~8`>o5bG7PX@0=RtzMBtgh z{Ztg38mJ=u}<0L1}_Exu#GuG1*lUjx8j-me- zB<$<&KND>%;N{z4@g3p``qg0{Sn9RNHiT8!lln)M|ILQNxmuO=th{-jrXv3(VbJT5 z6mc;_im_J!T~`advq*E6F`@yPK+XK8r)w-@wx#-gRz#chGU&a}ynGp-X%SRJ)TSnJ zO-B{_j24&noD(9p9(R}VvC2wQI_g7sV)nvV<7}4nf~mIOYUsWdqb8xKH{>YOZ5=Ll z&rkZSz2&JY=`d{tqNM8n6yaelQraC1s-+W>4Sk7mZ^o(_5xYn{@s1T>l#;o#`T6ME zVbuoAKGkiF-3eKntxR@GDZsi|(f{Gvo>)mgO1$eR#s{5)gDax*7b;3?@~c9RSmgHo z-ajlPzN<*nowc~QN2i0`*kLu&!h~??B`$~0Z|a$!*7^?bwD!u`UDK>swZw;INkb^N z_y?a@xUG-ZpTnkdU-#d*TL%Di4KwUq7p5jQju}3?JrF?K@&-O@o{*QxX|&H&wQ+k@lS zE_kI8~qZ(^@+8Xier+JSgRY$WS$Bxb= zoTJm@X*ef%tu8x=^w1n_96v@jt&9Zel(qO;+d_ZG4K;?aQ&Tt%P-CUxrJnSQ5mBis z9@`~LU#cY-uf=IR1Q!Zz;?OzL$Y$sHvGh%@1mdh^Wcf~PVny7ou=VB)eJ@1v2H!4WFX2BT0bIx)_!$84-)Ft6V~*yly2 zwNsdPjxJsML%wz3!o(*iDClq!X)N+;LEnMlS6!^gJoO(LTCth+ zM}rpc-)GR*^9|k7(#*+HDWfN}a!5obae&%}PHE#; zmct^hu14QYNsyGY_l$Pz8_|Xu2Lrd5DyzlMF?98LsT=v09Wl3|(T&?)@Bd-73HQm& zd09PB=A<_FZtIht+Tr=qr1~H;jI#Oh2|vS!CYh(a>P4Hs-925Y@$dER4;Exb#!3*5 zeyCUJ5eLPT)ki9HZIZ8ts zAdbhmi1OKmGumSkhLznV{FYw%u8JiK@E1`Y=^%*r0WJ^79@GS z*zi9*y{~avYnd(UauuWuwvr_=0;QfM&kyP%0>(b)LAw=xECt&jS6`x$Cs~;}?E*2E z!7tkMp?N_X>pBmEe^$ANJ8bdnCRbmMO!zlEUyg1qv3oodOzbUK5SiXy!yXS)9a?#Q z3l~n$6CXamF0~phM(o}fI5_Pv`UXr()4vU3NHcPpPXFPl@qb6T{BMX&xcvjLI~7mX zp14ODHC&VEyBX-GiFDOFEbAjg>a6jtG=KBgGC@i?SdgT8pHy{J5|AK8wXPV2S+H)I zrFr=KpNg^rCb1JeipMNw&ZUC?u%fOQU12<~A5W9ms?p(Vt|Y=(HB{K1K69^W8>KB!{?c5^I|AbmQ-2=C}4HtQPK z+?nvY6~!ZzoyC$pEz>wco@zZco`$L2mK>hET`@y*-ilTCXkrd+nqR$uM-zqigmU&v^2LC@the1?mQ`=@FI z6HRtUI4wm^tdz89l9*Xr>s52yNZnZtOpBG|-W_(Mgq0XUniPDZqw8v#uluSy+)ZD5 zy%?(KWbxF4unhdYC7nJ@E7sWSQJ_6KE12L2gA$TPsRAJb^yDFErjL@7tza zwqlX|6RhVoWC~VCUQh65q|_+y)e$XQxt?6^wtibL&zPU8CXtks?{1epVyz8A* zT^Y-{c<~WrV`AW3bFKC6@G(2vo4!#K{2TdB_CZ>SZO`iCCkQ|$yVOKBoFK}d@C8XD z#z>Zj5IkSMS(2hRs0nlg0a?^(Zsd z$PoXa)n8s0U2$%DI76frV!Wl_aLMU8uZD60SL{^CZM6vZhI-wb9a8IPB@|dc8cNmQ z81~A*0YiWVVDG01nrkP4s}7>yi@>u;yb;p;;|;(Ts#shHq=Br!rjrN?t^=TlvQHrN zK?!yALYXdoKl9__pyH&Anv1P1yW~jw4_h3a-^RSQvba214>_Ecdl5$*bYoIZ+kytK zB;{p09{C<6Zo>F9wYJ3hiionzSv*YgB>$d%)(}{?>tRwBO(UL<=y{~pUT7o&V^LnRPh-a z)iz1tiC}j`X3ZRx`$`r|V=~ULg)_p9Bu$f?{!cs$@oNc~ico{B7U3YDpsbdJh1c&o z7+4d}`Qgb~6{|%a#c#ZL7u;c~$~fvSPzS7DL}CAMh_8JeQ3xTNX|DZ}m%5bXv*itB zkRMd)O7^IZkG3SWKpx)cJ-n2e-M~m9!@DJ_-`;3ljdyvWGv#Ib-#Q#V2qET8?w zDip|)TFp$wd6-J!e_r-;wcj)c8`nuSOK7}UfxONt9U>kRU;s`-PC_5Plgr%Eq2_R5 zG7m2^vOaH%;1l#rRemEt{qu@I zx{q&rJK(pOi}k#jy7sM*m#r9AY1Ky1HanlKcRb-e>+KG=ZHF!y$SR)J*f?7MaEiui zSw!BZK=4LysNsl<{MS&1>BXq)ho!6c{+?+i(gk3>fk;QOxrSjF`5GYY@eV_{M$o9< zai}yXd4tTR-U|dwq&QN}w6ik#1=44+Pc}09J$$V72J!-cBlLQE9R@rSt5RKL)spO} z<*lAlKLyhQ%(zF-OQk*}RvM>{Z>%p!gv4U_rXFx*2B7_UiY`GDhhUUgC{~E}>ukSw zqQ7%`O=z)u)HV`Q zYS@+v<(e}r_-fDPo6YlM`16+MC)X-U6|};prS?bpsmr@Nj8*xcv9WdaJSpAlz%VgM zOzH!X)Vhb;^vEU$2T{}-!o*&cQ`n6o5in}wfWl+^f# z!(m<%P*vK}VJ$VPAgo=-nKeF3&2&h_X$3UmKs?kf`EJY1ZQYFDx+7B3Z?(gh)X5Tm z-uc^>L$N`XKZ}dHXbfocx#FoiRw~L>mH&MPm*|1Ux96b>q!SBM(htsw?}LUa1=j5- zW|-?-{B+_rdI=;!>kj1O$DcTf$h2%N zu8Kl2cmm9NXPS$%^qZDW=J?l{L6-jZ z^29$~ime>LUMi;(4b7LkXaxJD(%{<@w+9H!<{>H(Dq zkp72-tu48U-6Hrg3;^~(`+A_~e>9bG7wG;E7~p?OT+-L@j!BMhvaY`~V`2e%>(&SM zFZs=B0!{B&9$vhi*)h$Wn>?=b4}3pNzczE>y%@N11ogk1w7)#L47M|qI1SuGE5m(> znEfHkYv#bbmh&r_7Jt}^xslx_$6LfPk&V^i>cHXZ=wadDZzr_{)e>$QbJ&!@NQ%4J~#jU;;j3sAMpdhTNN7ss>Tx zFFrKfhAmt{a*m1|E|XjpJ^YnYHfcuA(uY3ia!{U31m#*I>8U1XbiMnDXqF*EW3)Z5 zgn~$+0lzl(bWCxbK4lM)w6!dXfdq(v3KQ^mW&i;`;nj+cZC8D|VhI4@r^mA0@t;$j zW5E`rl=AY5bs%LJ48>|xO7m^8w+Qx(*uF)dhR zzf&Y2#|HMhp**4S;hRS0Cgt9<#G}^ks`52%AsrX+SI+E%Uj-i?EB(jShF0ZS&gKAY zbk5o354HnD~(+hdT4p({OmjAHj8h%Wtz|EQpa=?5XKNI?* z&sGC&*6AQaw6U<^Td!LyfkYRc4v`^ilrMvq=Hek83kUNWMbHamJdk|XV^0b8CF7bk zLatmwy>I$)4slE^52#AS6()?JI(}qo+YB6aocsd(;zIILlok7o9``@9?Z#nd zIqk49=rqSR=*rVsf@*(651Yd36@zrN&eOe|8unHD>A1-ezQZpS4IA5nm6*XI>5G}c z6RRJqr~fdBfxM$3tb7v+mb=5ov3CJ#U6me7SH$@xFMJL4v6`gDyZ82)aO&gZD|X=q zm5N_~!p0Po+FU18Qe8^SES$ONxUrCKI&&K~8|u-W@9^y51_5M)ou9f5RvNDo6^G~5 z#vyKIhAuju;kG3g-5?H9t5~Jpsc8+?nCgM+i#Z>ZC%9N&qN--a$IoZPP8!d^n;a+q zr<0i~%4^?9cB~e6WQ$ZmvF`QPDluat3q4Zj5*C+N5hfFe8NI`C7b!m;713B5&Kvdp zUH>wr>>csdk}>!EV`Gldd!~wItIw+O3%VYsVGCY_ z$eK%&b4n6lh-*pd;jIRfodAUb8!flD4yZwsm4n?hRxd3Tq@pC;JbALsA-wzZ4ZkntLc)FseNO6d8jM1(T9}vKo>7AO82>iBi3=%wBNX`h(6|P zFv@ws^LH;hIwmqMT?KnlPi8Lj@>agq5@K!R@`{dp8$fW;)6rfe_m(TI^=$uKm&0vm zVYfPeJ&C0!g)}`|H?>DM7}q>>f4pnuLSUb0PNv%IJxBHZ+C|c`w?MnZedE|=k1PEA zI*@+sZJ#p8x`*e%cyI%i!1p(Zi=E{n9YAw&l3#aIpkZUz*0Icw z!mEY3#eZ0q82c0N!?lK6$9$eLLANCA|Jab`6;Q?*hK*6;<%^R(&-dR{1sR+9zxRLd znjG53$dJPjVB~Er7_ClK zMo`eFeYkzb??!c-sf5JXghV(4VeqRopJ0nZ4NGQJ34`tAW_*l>3r z>=g)^j}e4np+i!q5XDw`cnNtwqr$MdeUSToJWP61`vVQ)^uq@8~^G8A9WegC4K^0AP%$W`~D zxplfP|M$+1SD6TTb*?e5weK3~aLToExAP0k(H2v>^Ir#CZruQmPSu{j=G*!4Sr}1J zPc%{8Vq1Xoh4)DkTKGz{z{^-)rn~F#f{4*SSaWX8;>x>&>KO6%J7QqzzQAW6e)WBw zg>6$R_GryLFtFPNF|+)zbj;uxXkV0^e+BG(n~?*l?d>_5HjVYRF-u~pMdUH>I_IH(DMGMAbute4uFxCB<%0<`Q4JA;p;{wD+H^q#vH0#H2N9fo$@BhO`}ApUHE6b1r6p zD!g%~EZFXONM@cd=jjC0VfpZc_&j1teksY*$c(i4TuU>1`0Cv*=LX&&y&#l$jDu87 zmYmexiQlGpinNk29FMs%)vh*!Ys}AX=G1Q{`+V~I=0zpm339t!>dyk(%gt3qOZ zD*1s^PW^#L`6u?bRt{$FN`itEw^xL2-AZmC6I?~!`+UwH#FayxY2LzCZ!;A62AvzW z?1ax4c&=@HK$knY!OqrH{v#sW^;40VUamt^nHX~oD}>)n3dx&K?Ow*VfQM1ma9bW_ zHRhvr*A;Pb4m%O1=^Qbr*FNSaT9DC%)u>@a6LCXr8~O>Z4u+)h2fSt~8@OJtNogY> zpki~SwUa6s)(SBR<>2B7FUl=dUl!lfSY16>H6eR_8S(7HFeE>qvTc=mRVc@OU}LE3 zwZ}Y9qc{un_V6xZtd^;VH6!}UsdIq6zA+qIs`SkqZ3G(>{_ROCUt5)iAKQNVhwE?J z6Dz7*Tm$QyNy7iT14}q$w!n9umoK>~v>v@(T&12Ao2u1+Q%vq0^b0Z|2gN zjUcYL@0k3I#T;g0T4G8Dgg(vYM@D*gKjR&WFc{4F>;tBEpUDV@cZ@m>jhI&ihcon# zWi&HgQ0yx$Xu1ZP)*r?T!EYunyk@TIS^`b3vT`o`M3?Rx7jGyogB{FYR?4YRzLkC) zk^0&%;Hi^J-amE*&+upr!JXF6YQPErIF=`x1%Y(?s4E23CFJ21uUI@n0b1vp+aOiDhJ zdHSZw$wdm)!1tv&ZNQ*S^zo|e=XsSeQpff`rtC~yub!Zun7!|nlSPo95+WJ`{<57% zc(_9|@dttjVNyO{w!}xzNLnH~oO$*lJQOvCAch6sUCf-ADLgubX4jPRlm66xAstqU zpxw7@S8o8N@)bcp0KBT+EB)sp?}u6AS6l3Qf>P2bhxfbxZ0JV|Q2Epp)D9O9cw6L7Sq@U?W-{R6S zZyMUX8iV&?kO*WjuOQCz?gSvc`?gqA2{ihC- z6^3Ym{@{Ychp8O?0LXz%xJ=)M+33_o+TVXz%|S0sJpC!U0`t44j%Jx9%6Yx|cCq%5 z$k_mHwiqZ;$i%9Q@{cPn>)W$8){YCjTlkrBC&Px%H`3Z`_cOINh2Zv;b~vCtH)eU2 z4!ynDxD~L!u<_3X%lI$o%kdl$moSk3WY4SM&CQLqmtu2hoI8qtSj-s^9N@jj9p}C0 z&Fztix67jR!iD>Zw|$`AWs$2tV(I?g%~yKiKpNDo)WY|&sS@OUv9Ggvyg%QV6>7#5 z5PPyeN(hR2ngiBu?wu;tcn5>%+6n6M%Y|DvR5jYj&|^FdYu1K%*GFTx&{+rU%;ca$ zR+B0k7Css#!MH#sLW!0Ry)oB9!hBuurbD8-VBr^|Kg}y2I6QLzf7`%mCiqnDxyt*v z6;-o!rR<;76okfN|6$P?4d{f%EK>i+8JNS@d-QI9f_6r{;QFb@cehp0cye5#7457Q zpTG2yWn;#-8X9Se2@o;)xls}wCP2E)=YAgsw6SHi-e%}YcFzrBr{`L`kVip?0mpxM zPTtl2q6}dRHNIw`CgXC*^`YRwDSLko9 zdS<0U4_6rU?xR<_5A5a+yXOwKE`fIDPhR94a|Uc5%OK$@YQBM@@M$WI>Ga5yGaEjt ziz9ssUW+BTKaZuP9@jLyl!tqWm4TQAJBl&vuSk{B2kXPV=^RNvkD8pU8+memiz;N0p$QXfe?4)|?KWz+xgM9=Hl4e&F!F;z@z1E$WmldYvEA5Kv?vk5j|58th#=p~ zz9eE9%CV)%c;=}-RO{&gGMLKA4s89^HHZ%z> zJ&dmnHHL4vDvvyVUcK9C)kOawENoXtn8RfJwUY;p6+&Aw^$v^lom0Y^{3(88?(wP*ASW!U;94yu1nCZu)zC{$ADW8x{4?D zzMc}@W%Iyus!EM?nq-LKla@2o^}1B7civx}40cCWO*~)vuw~=2f|?;7)RvWr5t{PEqT>e&@hn!~3_`a%9Ohs-_N{`c6IARHstC7pY^i$R z%w7RJ|-WF|8|79 z2HJ@4qOPdHuvD9GdL4vI?)!m5 zCSMg2E}2f;;=Z0Lih?D*pS8{Ju#=%nN(A(1QZE=~w5Z?m_0!Y&X!_Wl+8+E##GlL$ z85TK2;XkQav+wO+N;_3dk<1yL5r0BpY=6+l^puW{j@b6yia?=aBNax4Yg$zfRukdL z5eX)5D_$qU-w=vJH^%y;<+&*_Yxf&c|L)UDs4;Q(ksoHF#nI-m1(aGlIA-mu7x6=7 zZ4=oRIl%`XPC@Fl5begS1y`XY_3k8w$?zuL14C`?w4 z$6&Ap@Xl0Ht1^AX2%GG&hN9Pm1hD!4>?q!0)M-hP9@b>D=}HMJIdAzGNSSZ=@ubOY z6rZarH`z8Ed{e%5Ds51kWZn|a$@pE#o#$piE@8*@q{Kl?q4(}RT;l~g5oCMQdMdAe zJxIe2Zv#}Te;059G}$qjfPv8hsoe%@hG#Q^&Lld&KffRiDQwYGi|crrWirBSEpB+$ z4;}482i=UIy4j^^+Hx*3$kOuyETY?pNxiK*djAeLdDQJp3XTgDm+ zd$gP<&)cFk9@2{vWiGge7>+dzD?^_A37wIo#n|_jT+YykIBCG7spvV72HO4nI2-gI zT!Dk`X`*wmRA%4=7L2g1S5G%rQ_Z9t- z$ne_VXW0{gt+b02v|bNc%|Lw*<%p-tYLAt)d#hz9MDF0myvsT4tD^Kid<9%+z<`>_hJRQLhnbfbS5Cu5Bwhyu{*Jl(&-iwZazq+LO?c~9hC765Zl0YnyXx{4Y97@V#*`(D#AKt!$!DM zNIbqN2}W?q_q}|k_$R#Rr_Y0TMFo{v1nvE251E2}Lu$P#6Sl3Z=rsv(9ETG-PPCDm z)eB27;y6DTeComzr(Nz{&v8G>eDurHb?Z|$$!@z1s|gGeFWm1^0#p=@xN!tfL>p6hzT}j38OScLdo|jb=Sb zdi*BqGQ;4x%C#l&)?W8uXp!#K4Fh$OfchmXVF4a`zQLn1ac6m4Og- zUl2bmf+8=s1p^6pB&}z^JwAeMhIbu(tbu~?-kY95@M#MC16;(FhogV}8c)59SZw)J zntJBW=$h0w0;F+<|J7pPga5-g=Ktwfo57{$9aSj^iR!wTJP^;5?p|)yJH6>B@;L}_ zd41-yu}0yCKQD2ic$f2biNL^~#&6@Jx)tIuHBRqPd^2F5>r}HI8QS@#$MvuKH?=%C-~*}3H%Au~uXC*V zIV-LsGK>5cYQAMv0>XN8emU%vyFTjM#hHMk10`pBvBQ566DF?I{8dh!z8kYWCG8NLYQO_7F{nS~2@K3HMhLGsE5vP{67L-U$g}JMz zxy+s7QPBVJlTKo17;J0IUTRnxTkN2-8Fdkey7t=zLry)@oXvl_EeJaw#^%CI)R=R8=(^-R z*GA;^+kIRMMp3d!qlRca*ksyzsj#nCN1|}{W=4I+n)YRxA=!kXTfSd@fJD$60z3Ne z41`4qiV8f|8YKO0ZjeNV*J4Gvu0b@du9=<_w4KPgP#hWXfeLQEEJz5xklQ-6{aR7+ zl{M;YKH+o5Pri`G=>&3~NjcUz;aJMSgF{%P%+o`f;KATzQ~;#u@U{pK?PVl>bT>)7 zFxN;bYO&0cga@$gV-g3NR7iuf*3v{PCRGzu9T{lu^&Z5ifbVL6+xih%{arlyIsA%staH33kwIa} z8JQYh?_9oRgZ&DJ0=L>Y*=x=l1+@G|FE@fwCzGFiw2Nh?YE0^^Jke`vWg)9&Xs=Ua zf(K|qrNUuDhk4z^v#QFJT%#>sOL5>Xn-voCHRoR*cP!;g?^K0+9ol4nbtJ`@Al-BgE;XX}k{b@J4r~OR1~lqG zM&5kkFKCC(@_tNpvCM@V*32-L%#S0fd$c_abMQpqu?1d6JIBelDKECW3{V=^yqrIs=l$2B(0R-ZP{>tOg9X?tFgdfJn`sIkL-aS|@VrUHmDA5VIa-Q5V_`fgDNz$5a?Z)Ww5(4 zZ+NlGVAz9OWU6<$CiFM>KJo@UQ?e>^X|M{vYo__s;G)bGdv0+8Ak=-ixsyMo@%}%m zs5Nun4FTjaUMDgCSw$TZ67@F=>BY3M^QcppH;H&c0d+dQ73HycshkhHa~Zg{VCfia zv8i$#HX)wTFI#iUuQgn*H5G4STg^5X1{LQF8xbdWBk}OVoMo|rL>?r;GM>0JKK@_R zu5YVMf9Q?3ylNXVr+i>P9h%D-l;RmUazb&?v}3#{x`q2lU{LX>p#*2mF*h09bmxo$i&YH`=kfdP z!mJ)Jl7N}yBi{HI9w$3kFdGx={?V)!tFIg`6t3br+KS!? z!%@YJl(Z+y6olJ8n9`)U;F9YT-@ zh~C%%=XcvfzPlVKy@L7^sWgaI(wbLtq=15^ZrebI2QPkC4Ub&X0W}K0bbEIw)Qw* zYQ9})xYcjCei%RG4@eRkIh)@*dm&}6XnsD$SNE3#!}6`}=H6`{{MKVK#M{GhP=L2cG8c4)V^{Ohf3-}9i(_iIvDjW#geVW6vD6K` zdWlCxZ|#Y;{OPrGa&ZG$4^Qk=mcd^|T>Qh5lI}MTt*fA)JSwt$b7@|^7NJ>NbsL;> z!4tG~10F3|4ZbvZ7`lVdylE+t`pF8Uen{dc97Kr^JO|N%l|)rpGqsQx+pG7`RA^q} z_%yc?)WkVWg@WYe2=A9`uPx4arQwQLF#98{#ABko$yhWZN$B*_9EV?k82AzqcOt1r z`Qu_BOHZfY;5!8?zb?>~ey$}?E%P`l*%khj-rvMZKcsq;9Wb53SG<)V!e~vH_c*}& z9O{0qOM@&QSg4=_EY!#z^4NDfx@E#ArOA9L@_cayy1rv#Q@C1D+0OV98owIr`4+-> z!5yDh-COutRGd+w#t8^24geS}%|IY#71K#7BqMN5 zH*jYT_lHrt^DVzBUH#K?7)8OmzmSO|w9tw%b=CUJ67rCQ}+G@1HwVh7)F0R3zru5UQ z+gim}X)$e4b@Pd?*wQRBb>GVeg1$pT><0Zj&(9Zuv*`KkrkW5ba-W%a)&Ps|K3mzm zs`w&{myg8R?Ak)%^Xd>k1S!z%&uBkPL$Zbc%k>uvKLw=htpeek0u}#vT~A!g&?>qB zC2`*&wKP07C?UXAhR|*L_n>&?ZPQ90!^&^QQd{Pq7DD`Q+ zpbK|&PaP?;q8Ln|2^x-lTf(p`(OUc3Ogozr2^j!Ra%}RFlIJu2FZSLtDz4_;7bFP@ zAy{w-?(V@oxVttMG&tS32Mg}*3GM`KoS=;pT)NRlg1bwm&pH1y>)f?w?%cWa;oe#6 z{nEQXbgiykdsjVAJ@u2^(x#10gttt*$%lR-ALp;O<|10Lb#{8`?;M0HPLxO&=Q|T} z=iEd*>WpFORBRb7y%TC}j4zDF6knC&k08Bk;e1np#Mp-%AHLE_WR`gP0RFFM^Z%V9 zZ%U)qpvVw9kt%{7L?{4kSkWXkm}X^C++ zau{2y>w~f-2An;(P2SK@6KCRgmVqRBG=0FC%*Tn1UNRox49?WrOTXLl(e{ej_QFy@ z$#K$f_s{GM6Af-z3-}>}9^~3tH$KrB%JqbJ+J3!CYMu7;Q%bWLJ!Z;(cwJ`%kk&6> z?OHyH^LA0q1#}> zKEF;kS-_ppaC7aVz(E$@b^o|U4Lvr$wq?T`*QyW0^37K4D{UYQ^?)lpQu^%TkrD+^7@7EoZ~u|F4i-|U)-#}f7HEM&urf&1#s$PNU;;`)yO<_G zgo9)Lpa*TJDrGD2*1@=u`2`UT&AWQ9y93#uii-rl4EAKB@ppgV*kwt_n0t7@d-H>@ zW4kxShrGG~%N|dYp^w6Bq&ERJ5eNHAk=Z|wu_2)u4Q2^B;2LcTS%pCbGS5~_jLIS- zo&;OFlAo*%7I=Cu5J|tk{@T%ZVn{ipuXOiM*~?XO z7c)q_I97H2pw-5D(o;IYf^t4$#K&B zM<@V$#^F0%W=E6J_dmvves*BXny~XmT$kzjMOoNn#N^ENU4Y*{N(Y4iTcn7@9ZeGF zwN*y2iG-sdh_Q}y;e5iw4QHq=6B+E~Xz zvn^+g8L;I51W&|jJG&EsKSK~qhHx)X({z~^R^(GE){8Uo`Xa(Uj$qR(nL8Ph!O7nI zbPn(jRU_(D?W>0{E zrK*4xZO>R|HYFPLM%Y7%E3(@ml1pQt(yynWzDA@OcWU63fVG~p8XD)S?wZG*-Wg^; zo$H^`=PbIWC+Twp{(A-2pgJwH?yP+yO)JDY3hPn+QK0nXTOA`U67FLVyn!W7rQO5w z73zx0WXW)_N}sjI25BT-(3sb3{q$G)uWzr0A!SI8*Rv9@{XxL}H{4>dyIE?Z0P=3V zN6sn=9IW1xrYEmS4$ky-`+cm2huWn#mstN1=Y5?suf(5wpJZ*PPADE&oh_dYV=I>U zY4Q5+Id6%=nGoL36JJWHzABn$l#V0B<`HIWT+#@K6(k7>2`P7_v-bCAu3uL_5XeRB zQs3TLpZ5uYd}&oJp7}pN{!Coi1aQwaZLz=ItDHV*R@GxY)??3E#yL^u$P!c^+hTh= zWC{!o>*4zz1P*UQ70+)A#pn?It?>9XS2M?A4SfgOtc?l8^)}xh+a$-|xZ(3kj$N@n z5M29U7HI(|?K2;2PV^ME8(EaEki{sP@CxpuecGSM`!A#EHa`Ex~DVDoMEP z3-R8xo5Zui=_PO!NFbJK>%-pYjDLK5U(HGYxjP;&iwQ*sVSi3FoFY=pcF2=J=3ASW z>sO2V8t%_lqfoBjxL~vv(sIT^;iIbULZJL`AO1ir&L@8Gwqy9O=t!I_X^266EPV+{ z+*Ho>MlFBtxl*s}-08_E%&j;5jnl8zK!UT?2e?YNk9bq{L5=@FHX9l6*I->cIx={% zF7sk-GV#l3kgYB-?J-B$cl)gU*Bd#azBAWBRnw2q8L$UU6kIf%F3C~YTKe-bTFL0= z*ZC_jKA3c?o}Cx?qApS(`jY~Kimthh$!v7mevwS%`}VJ%C}I}h?=hs=4|01ZGyaH0 z&GV%;Plh`wZg4~!pQU+8dfnOq?c*#HdKXgH!q4ZizS5d#Hf*z%CTJuM!}K;2t7}*) zG|DEx88>~9YB(K1xQUR*a-t1qx%zBYF%6L*ig-h{qO6GP)xAya;Q##83)LF{U-4bG zA7MG(q|Yf81VC@%8+<9i4{-)C)8+?;yn`kG$|b+QNY>ZsVse?=-Un`X-|{#LIqtut zEnMM_B9!>uR02SrAz|UdN%eTk&un>kF44-Sgq9V*>mQ51IkLR33cUGa~ z@$Xw$ESnp(x(^Q=^Ul2t3p!8TWA~}upeI?YsT1)B)S<9mU)$ zXCq7ybC4#xI7x{Scz@v>09UY3fmrY1)4ib{}}@V$lLJyY!2%;$qy%#4Hi@7D-U5^u|>KMJgGq+I5PR!w-^#SN65U}A$#QcG}#fU7ID&8uZSlAATa(c2V8{48ZD zhC?IrjkFp$8P@n99VC=nsiVtVZv;*DH@lx4bVpP)pu47k`9CpOT629}NN36YG+$M# z#l&EIGU=QCvE13iEWscl<`sxLic-CEwFU;(ekJ2st3*54;JpFmAM{mEoi ztl*{f)ffs-_1nv;F{id*J7MatpYcRD;&K-*RvC{mb9%$`0NmAbwICu1ig|{4&;MG* zTyn;=>=L?2@5ANU^0mPf*dc3hQZa+Y`-spQXDx6UzVklwm>XrR2$lJ+q6jgFFNkoZ zIzisB-uzIp2~vG0x})a8(3{S1>kQI`?NUUz--NpaAi>Q&5rpTvJhf)_yTcxLf76uk z#sc6YDO#zf+R(;fh7!N^Ub}FT&M3kA#OwPCMFCIZiWNqZk`uaI}c4 zuol$j(GVbAF_xxKZGzAMlI7E~5hTbniUhClD_*{>*=^Hs3GPcV9NK_d) zD=%=DNG@)V^d&_!ryOI zNe-dmQpj&LIvHg;8)&tByKH15%4SxnJ|W~T2-uTJ?R4rP_#A8}m}ez4?SdB}Oal@1 z{o?0S^)^SNxArycGg{!Xw@REy-(zsSN`ix2z-j$)Iojt^5~>o~BLnh67Rm7*V)~TjZ59*RxrjnJYD3|dPN>4 zX;Sl9AW@YO){7UZhopho;|R#L921{p1z2QID+RnFr=lRDV$rI&8JCh|yxYArY*ZYd zffht8WnLPa!m{Z6P8`!WKr4~phMC>ZI~By1p4gz$>DMvD=A?A{!FXr_thkq!kdU2c z|BBxkrdy~`PKT>0gXRz?zm%m|G=-sJ`)LUgNlkKvuwH<#em6@J9mJD;6A7OJP~WBn zB#DPG{6(T1S$q7gM?n$@8w8bzBK>MiD3aH@>|iT;!_Y1~#L_KW9Qvw3y> zFA{!(9`|$Hvqq1=OQ?nWR_27QKvsN2VvAX|N0c1EY9J|Tw44Jd9vdsKZXFpTt-3{E zw5drgl_6)CF#R2qry0bxt&Tzr6(l+@?@7HEdS-b)m86A3Bs8fIs)UlHro(REUy;cd z11Q@Y2~!Ym9APx4P8>rm(IVX>qhrjFV1E8@k7=u2Y&Fnd43QHZoL*j*$bCJfsqu;N z4)ABOI6+;TPCkP?7Yh_V?Tzy4-?D?qg)TR2*hB;zRh0xc3F$#rw-5nfG)LGOO`L(+ zYDE9y6p#Ly(jZ%(o<_wOKZJ9N9iE`!&E!Q=Vhj7|mOb?9C$K7vS!9Lp57$B&bbn6+ zBgO~aPgdcc#WwpOc9kcChG@Iv$9O!R5;Xeyb*{A$2kWL0X;b^T(X&IlrW2L30fA1T zg~?2f2 z+8O*p$G0ePYy6pQwAjoMnYx_VBZ8?OnL6^?PE((PL$UWUteGT$v28d3KT!_93kBBp7`%MIg<*ib9*t*jlM+?@5twSRdbjNs8vatzE z9IlPOl)I+s6r!RyK(n~VZTP-(mI;XRB{X08o zLHk_EF3mYgNKMY33X*Mh zt=Q-uyBx2dlS#>PN+zkTin4g9WPcyOm`CMxYp%O2tINnRBYvu7anWB?EZw_#8smbUSct!kb2ypjetAV;kGZF!x7?ti(XNvkvnSmtX z#@mpOU=AVGni46;#y?8=iPt=8Bsln0M;_`|^?ZS~(nA|+V1oXJ%6KsW%V&<ceeWu;aD=+I*Rq2isL36!Ijb<;eQM5TmS^Lc=Q|i3KYRnN? zi}~r3DWOg`-csn(iutNXjM90Za67E1DkL12jR$N^aO>%L-pK|GNCV4Y* z+Gg#L9fevIlRc+y_RFfPv@Ie=cmdYke89Kps%)qBJqnix}Au8eR} z`Lf|`CSo~__w~-|;prCmv||@?8^(iifoFXwHx4He3j&GRY292ZPfl zk%%NPC4WbFRs)$7zj;8)#ZAQD{pWR&<-gthYrw z>nS$HbU8$_G^;c%S*pAIH@5XlNJ~@{Rort!`SOzX zX)VlY4{pE&QG)d7kyuTzq&E18=e360?Y_Nj{u<0Ex#CT*I0{;NiFbDNO96wn_Xc%S zt;aix0R#BKQ1pArK)dcA$RIWtVYE$vg=)moOX`?d#iEu4V;D|X>9Mjrx^Y?duTl>2x3qor0|d(OEzHERm|_ zQ8XVR9WUbWxDTQ_(E_91qpz)G1GYjVdFj@zTUI)_ce@BSyR?3CLL%Ltk0$}|S8gmr z{a%l9L>8ulb5sD$_`jYSO40M!3+2+jQsE8NWUnEYBxXD9a1m^nH z9hTw#bm4dlw8ST8SFEM%!f&O`1~U1lI;t!BW-qhlDb5@4bXUh>Y^Yg0v3SLB0NK#o zb?`~Pf}d6gcg1w?6#z_U)i@B@)fDgB*6!yOLErl_Q-l`0QIp}lmaxTael0~9PqV1P z{n@SVaHjb44sKk2L$B*!r0j{g6hHLF3xa@Clg88Zuw(m1AQtzA>%fZ3`5?}Rd#kAW zr@Jp5DV<4;+HoDz%!If^{nc__e`2hNhot3%RADVt*!hw(g7V&?(o7mVFvs5(H9|gd zh?yb?`AP^V>UMib-|4mV;~~T7no%CioLk1^d*BeOMJF7 zw+~6x!`PZkSTOF1t7TklIglb^Vk36oY<6s(BwO1f+roYEO?NTslh~4-d(<<7Oq)6% z7g#Dcj_2%R;FZ~nxV)D0gWVY2>45hRqytY>V|(O>xtJd;$sMV`BLzh`Wyc-t>CnBS zmQmLa)=@X$;#Mkfo0A_@-sU{;Mp%y=&7^l%g#AT&#vj$GEtdM%6aCMtL*ivj;2}b_ z>o3wF8YJ-EZmznM=@Urd;)fvZ-Txrehs9dF$gQFxaCZCxPebK23##oiVd1FbKd@6K z`bk(rHP}1+vG6jzOssO#iU81Tze2TMcB)LIFV%_~>a_Fp5SFY3$kdt*(zN=&I$cHu8qOo-Ob3OwTc7 zQu)qjc{(y&1MVcOmym9GNOO)SEfhDQ5~BAS?0bf}XE#6lL}z3oZ^kqN!d)lOCTyAjBZJ)MAy9p9!H9aX?!zLiQ`u{bNJ11Q$}g z_|Loeg71hi3bgqaP_cON=X`ugVeBFa(sYg~+z*2e8~HoipSDwPakzsOG4~CMPn9~G zI%(KPB-?mYtw=2*@rik?Xc+gY2~_sqpC6hRW#)Z(WNDe2d=>!Z9p#>V*u~)iE$lFL zSHtWf*^?>hZ}juqw_!uS6i2pF9Bl!S1MSWdhKY$I+_tpIRwgMoR2EUI#5DK}%kMP{ zNRZIo5JHl>8W>;s_6}k$4|eaCn}zQ`p4I+ny%-YkmaV8yj@s~Wi%qotiNrc}K^h+M zq1~(1Lqgb?S2c7@>i=4j{__fW?N1yyBi-CxmWNn_d<*PET)Npo zYAAv?Y(s};ttsjC4Q%(hJx&#Sx^?N}iF6*r&F!p_Ka??FQHT@n&_;(8tWR+d4XQRu zTT*A{WS}V8l>T5ieq_qa3(apotzHqarxV!ox@Cqtv<`rpox?8{IFF1rCN* zZ^Yvb(HVR9%F=;3N!MXQ{MS~ivyY(bi^xik-WG~xw~ge1Sw~;Fp|(&-8&1syvV0eL z{5k{K5jndPMOOPYbdwkSvCblhvg4T!=2lg7ag;#d6aiPfHj9RbUdzU zQ-?vyVqV;_pTEq(u|9^8X^aeL#EK{-sl+!Zg13 zNN&>Ytmx_!h>~6loi1(vb7*|aJ++H5bF0--)y_Z*)2F{{M({|txMi~Dn=agn!n$$* zDYNPCt(SM)Um7(3mQ&wDyTo8~Zc;zjiuus0{dT&5;uX;oA`TNlpz*aAGj^IO<;?$2 zV9$RTPXCP1|94*Te+TvO4~Oo5?cf-v_*%1zoH+U(`jeZcpSs`W8v6%k7Z&B`S02|i zrxa`F9fdr{1_D3$He=oMKK0vW7t7HM`FF=M7u`5eT-rZG%&hzjL^!C>Xs<9OZi%f8 zrfUA{r?$t7;(r!yuq&KWhR!LR;fm#=P?V<+&zm3r)pCws(b5|WeD;6!C)^_8(A((> zHIJUZNV456vHxnyt1_KQE_L*1tHaQ4hVV`@g~|SB2TS&p}6}>QU)`wk>bd`sZf;c{2aJX8+8Ye^#^q*`?XN9wP&M?jL#5?0%PL(=)Yw zdFd7q&{g>Cl;731tR)tLSgsK^weS83_5W)_{Xd!P|0bDiH58#?NYxjJfrV9)$3S}a z6AltnZmE7t8f_2Yr|arPm zi93U1C_j&Y5Gg$AP>S%jOgjFm@JQQ)MGYp7@P850(!)Nzm1D^wD+pC8=4q1GR2gCG z7x}JJ=pLn7vX_y}{wv3Z2r}(6JNlD>c#!KduPNp_efoR9XYrqr{&7;Am~i-Ge}c54 z=;y!z)ALilgLI^|)mq?V3D38$Ei;mt9eZ!-K~-4Wcf;K7lm)ib2Sj2CrD4sO@D*^Z z_dtKf+jb?a?eg0L^QWIj(jD#OL_QT)P5MU$i)*?=tn>8oJ-f>GKOmRvJy`@&JKrb3Z&M`@`_wHA9M?-8Dm7H9(_I$;!!F-!D;i6?{(+@!*V#-pX%(*4f*%^frNscXoY zgHaiO@HNnl&Ghj9^7u9EWwH!T*djM>25R@mPBM|M{6%Ws@!Q2&-SQU{Ly<1dl_Fk# z!Gv!+&_Pu&i)KwnSUoR!Se_?~5)vPW!si?Z+#JIn9;-j#g_Hh85^IX0ZCPg%7>;H> zO)Gvr1hzL!+Af~OHXUpm`k4%eaKEwn`oS&Uul${5CRTw@W zoU2qRwVzlcRB5s@JoMjlH6cXit#umo)#5Wb%Wa_rNcVGH4-;b0Ec+UTG#@>cUo=-i z@AB+R-+q@WGa%@CB4fu^jzuZ+GSv@KuU$l7zSL{08XzN;Djr24_9+lm(*GY1rPaJ zlq5ay{Z0GW@RjwwGu{B+j7qkFt-zZF&=B2YO-}5@6JL?j+(!TnzqmZYzBUO)Q0Fyg zdzQ5u2LY3NC5%QJwPFj%+m6-{;1VVip?R?Yg};dzQj4<0PDp6j8t_0^XkiJC8qqGl zCyc5v)n70OQ(zUIOu|+F?JKEcTy}t%d#NY&BVC7dOTL-#h&Mcj-?1>BMy9)qeJDDb zVv8{Yd4*A1-5tad>-5m61dNKqQvib}iphs+(j@C(`0i86ccbf)8<2Ewvf)FPVV2T( z-2meatNcLAXco2+(@7xR@Rx_XJjyIXF=h*V6RlCB1#U-%;{)OYIX2czuj@%zQ$TXc zY@}B^Mv@6IM)(I`qav`b^U`bE!G^S!uV%oaxCCLM&GN7CwGmF0~wc-17O<4hP8V!Nov zdM+SzhpRLU-Jvk|xFj{4zX&z1h+t3pT^C(qIsYXx;@4}{TTvl*Xf@{xtu8FJI5|_r zk+mYM4b$X9*eK}SIhIr(LIe#bI(V!9*-v%zK1|%pTz^HJ@WbL9dhGSv!GtSL^}`lOHDrk0I^{b z!5!gxXN9-Ad~<_W10Cn<2}#*OvD7@^ciex(KFL7SJ=P`pWJRNyI9rf+{VpM4N@2ff zb1!D#r)7eZq(0+0pNH!8v&G?nLi{bplB2v9Fnb#1k_~pPjJg#E&RtuadFc;wG8EL0 z*&+TkINR0}36h)9ye`t`^arPtJ1fZpvLevd)6#ZZ?nzk z5LSs|Po4?MH&t7QS`^m0Gb(TjyX#E)!=>-ry~4`=tfOz10>cC%(?9VdAOC?RdoMC6 zri9Tn9cAau$nI$JE{9>XNap0$M5obe53Wm_ZB_cRY25C~tf?m7 zqtq2pr)Nprd1p0Y=u ze#{Fs>bO_M6nOB#mZ@rAJ?uH>Po_-~Vn}OrAZIinrrr%kL4C`*$gp0Ga$4#Z6wz)j z&i#ipnqDdm$@0}EfIQ_DB?ZpnWtlPDIm{-4pWTu6v!dEccU~3C=lRfKapb zZHK5_dDi0>W6_qm^bI-$EGY!?Y1zpz^6h-|V)FuT{tyl$RqqY; z1kLF`5T)hh=Dss1U5>?{4WXD<5^`ch}?w0>lSJW{66$ zytK?quAT6k9MafpI)ZFh9-SL$$y8~NE|tZ2!RzP6Ywzz@nyS$P*xBxKB%y~>slbmh zcHA#V@cZ=0s_TLUV@KCeSs#K$w1F`qSd^P)AZlIX-?k2VAdy_dnZ{*fuY5Mr+cb}W zrI1#0_P$QARTk$*;o&bs49xB37*2AZ_MIeKh$n>dzLji|1m(cX|JaYW6$5(mLz>mZ zTL)}5a`NsD{7fAU)9H1GfQe4?@u_W&qcUC|ZtFBf~JXt<>mYbnO_wqJb)#DbLrH-0sPtorkTnlDVU{BUMnR4-AyE zxIi-6AOc--V2XB+VFv;EU`I&Vq;kyczkkkeFT^BWuk_$E2)d09^Ql{|u`Zd9cCzd$=z3j2UOp$v z;ed>eX2PoDgw8FDPJFJ=5&hG^T;t0>bkE@|IYGZ77yocLQNWB-J*lPz!uJHAI(>m(Nm10Y5!idfXtf z98b6jJyV@(?1zNq{@f|gnQ=!oUwRck#)%u1NxiCMyKmCTfUfZbTdF((C7Z=6{~^Zy z+)xQsv#R5zNeX=)v?Do^4u@)Z6c!_WwzPoJr??3=CXI`m@J%-1HJUUs8_m*KA6XV z)@V+*x546OlA{%?1fQ;)T`i?x(;&S@Ew^HJ0;Pp!U+mfEu!CX%%o$)g(eiA-d2JkoIvE4}58#Fv?;I0k4TMlRcP@XvDk zMnQG#zBrRZi4pB_N#58f$w#OLELpvt!f%fixi?iuhR*8#d=mYnD9iRS7pD4Stsa0brNOdY-`nTJP6`cG~(aN4MKQkcRCFB$xSm!Pc&Md=#@4pkiym(SvE}qLuh4;yTpD)r>lp znNd}41c<7MJ|R>b*x~o^e=v`U4HGzidDv>rs_BrP9*)ka2!n6`cHxmj!SYL=?V%Pe$`xPsQc>fNY7 zkHLHeGK(c%qWoYJRZm3{vydAMM_=^&v-e;LU=M+`IUN19b{&s!BfAfHUjnNR1}1Lr zE!a7ZEHV)P0q*TR*y~~Px%@>+_WRYkx=d=P=-q*_BrRH^`6b3;IYXj`wCFPu*#=}XN7B@GCou;@ zl-|$zv9si=-G>yoqgV&J$ZZY=atZv^Gd{rPKbhcKH%n?L&f>=ahITr7x+CA_7nd6p zO_^Zj++Ts%kH`^~Rih9L(r@%)O8y$?K|lt-0sFpR|f zu6ogzxW5F~7`JJFtG2)JxmB+|Z@57*IA)t+IBF?*3($?|J*0FlKt5v_V4 zgfpD2PwQEy{iaCjPX`2^H+igPn9JW?J3a&g^g?)*rBZsAws0_&I>~S{kY6f#jYr&q z5peaQaQDra@GH>LK=U`b4$=*3*vLnFTLbW*66DZ1Mg_foQX~ySGl&j;WjNyUP&V%L z@yLA$zG}FSfoyc;hsU1wN454{+vT#P}CHJf1Px0aP;Vy zXHviSe1LEUS<9`u-MhCf(rr6xM-VU~Q&ldLGAo=+|HE)hTF{^1&oHy@@hrE^%jFM? zm4kW%j5$jK`fIOtj&V#y+_wpcS~nSrI7oIB~=#zEd`F1y_TPk z2~=Q;f+}rkhx);_KA5dnbLH|#hahH6Bw^Ah&6G0j|KAq5eBLzM+T1>PaRD+mhdS9J zCREIa9{oBRjUEc=0eWKaw{i$s_ePis;MJ1+s1hqwja?$RCBf;5fQ>y>`+Td2tu-R) z?oMZ;mo#Mj(Y`a=(g8K)#6iWUS$@3p$x5~3n=zawf>?gZ;}6pzPa+G^JNHd%!>(AP zZK`=Y*Y^duuVS_=$(uL@CS)ZKG!d5faetAbjQ5f)Se5dTxd!<*lTqvPM+jA=2kZI# z&=rhQ`L!ab983_V)Y$LBHOC6SZyJkw02Sy)2Dps-Y-#T$^}&5J-#YwyJ9K|}0nqx+ z100Wvxja^NS1OSgXnM^LgkHmZ8qzHrkUKkb=G9s|m+O&^Ou4OcjDP>x<~9qi=+Bvq z7mqf&q@I5`HiwmQ8o%Nfj&N`cbsVlQ0Yyp=!RD{IqgzR8kc3&%&W8o58bQojUx}y- zj@pk$@3%8MPAc;@I@up0_mlKq&$*8c!T3qHqQ0x^Tz0_P(?ObQcua~~tzO$!F`6j_ zz?WZNF~2|}dsJmqT>pys%z)n&0cGoO@IwJU^Yy0FwZRkg-b6>g(To~@QAF&A3O&oY)KQLE@h7@I7qhqD^ljT^MNJ;B|gYfQ<# zm4*TsOcYHYL8A*LG;Ky;m7HX#rn0(~z%VYO8<9~02d?J}S58SCZR2+0+gAEm7?BZm zBq5SI4+Z<}wAc4t7H&C;Ein^QL|To3MZwxT2?kDZc+>Z2UJ95!yAm#?xji6^9C0b{ z3eN5L{b2iGudF}J1=jK0IXIYd(6jqM`ob|xR1}&~$njY@+u676)cE0(4^D!T7J`HP zY?+YglUEzXHk;`(ThasPGu-~xUFp$&!BO;QjnXL(02%k>X_VwFlYw}rYB>&ktPN!6+)J=8qMy1JT`J{8f)!+u1cgkt_frY>8I2XJHP?8qA79==^ zuRPF($R3NPUdSoKyaTjK4k%qq9BQ`LBE&gb*B$%}l=OUmb1e)mpW%1+46Rk~Z+|ew@5kv-dxuUPAUtMu4}@e>en-C`^`yZvdSAasDFh zIBkbtIX4FW`dDckh-}-^9yo{=rMA6FIZzmrob&_7xHnXRXT)f+ofhg6Ghz{`$TBpp z_%q%v1Iuv2s36MB3R4q-u;l0mXNwRuACF2!3s#;QJFW4=vMZH{p8_MDoqbd|&9Gz1 zA53I^9`BBIl+YoI<_V6?yYqF?qQih6|i-S2`vA0s?ko=n3W%P-Sg zct(^ik~zG+tu`SG4CD@7f(8!GMiGOcMTO$B`{lM;&NO>A%xBx&UV0VcMH@!uUb+KM zg(1Ayd5u1svgUF2mw~Wun|OpR$3*Q7LX)v3Q)`f=Kb>!*Jp^gnL|tt)qvSA@uH6-I zp2p6gs^~)+#Sd7bbEfCRRa)7LtJKCbp1vVo6%a%oZBbV()#>~xqTJdZecLVChqxo( z_*hTTZvW+(jI~qeh^?nK6uNT8>O;su=s*}%K=aLXvZnQQiKmihV%JPrI{Le47e$f2 zjNBXYT#rX)r_W=m5AkYheG|g~*ir`9A(CeINW(&sy2H5^!+80Yto>&Yr%` z9f9K%_Sdpvqmf{haeg1z4H?{3^d@!KV^RsWfE?fO(dGoTbq@t6sn$PEv|Sg&zx<&T z?SY5BI*V$@TP3?7@@=LSgPBOfbyh;|*Yn9`d++XI_s1bpo#)!Pz!0>!8eM?_*Jo;R z*|v$E93OXl!6XQ_{=6>{KL{NjWPgFQgXXcG*jawE?9W!IEQI^=b#9`VeZgYnBgv)`$4YW(v@5#J>PkE-i=x6Y z+_=T@a2kuO0gGqi&H8$%c4IvL-OU&~E{9Ml;YHI@)Uwe5_5OO$m-*G!Y9>#FM9y1< zt_F@TfV3GyWBLIWO{FZtRjV(WjVJ*V>hknEr2XsbF+R5lk~u%;4uc?xO zwNS{%TgVvkv&^{#UTdF+aYN(@8iHrU4>aVSxv^St9|puGJI#|rbF++7@Em9iz?0UN z%0m@H1XL;JI81GcK;k&k$*t7#e&?dgnt-l3VF2|+n@gh%ochzduI;9J4jc!VmAFeq zA~K#qXFI;PaIRYvQejxOTt&8}p3!hYk&@!=oYxPPEvPvA$ocB2w~xMpD$dMnHgqF^ z5ECGdY7DvkY|wVGXfO%qKuXk?eA!NO%9n#^1ztbUX>G$obSpO$Cu6OuX9X=4u{nSo z9P4)C2FdQUb=5Aqn!G`9Gnji4Ob}n6ncIzq35F@Jazt10~WM z55d(;BqW}?iL1_qn8DX)8pDKQyjyzT)F`>f=6SMzQvWzUREppsX0v>~=}b$vejb*$ zI5S1?G>7ZftK9IJnG1xbSl|`WN)T&Bvz5z%jh&7~AQI^4M6uhYe2$fMXMrkZfo7$U zawe;|r8Q&Z{brtuP7cvKs$W3=O9qXxalc)K_?E`L#F$S2BPUaQU2w9qcT+mhQL z;D>p|!C$0#U58M*x``t9T;_?{A&)A~3NxW$==HS{*!gX=_v^XkgXRz$@)gf_%p2Nq zZ6jqqN-1L0ehWLU0=G3vAoAN`k4HdKmz8aqK8xZAZO|(Pg-XlCpVtFL#~Q8DTlS2{ z#GXgEI+jpD1>Sk4fpAk_F@s+eSa<$-teDT&ehoqT04=L^z0ao%JfITa*RJ)w;Nzjk zLR&tI(4u4Cu9JoW{jJ+p%QQ5j$s?t#MaJ&VALOE+i0E=zLoy?D-^bt*8#I5ZMQyrg zijl(G;)(zfp-ZJmmoP<9(s3!je5r*efzW^WHw6e!&5)2Bo8PnF*FzTY>zyM!r#5%^ z#J4=8(>La^)EI$nhb^Wsft9dAU%)^Xqz=bM<+r};8UNK3g=;Hs$DSwG6wXl&EJEQE zulcpC0kKYQy_8x0D@;xhOJCqOg9*Ld%5%X=)v#-6chkD>tWy+={JO;{%hM0BXMaR3D>c48*q2|2EE$DY#jQ-yMg9bfd0?UO*qEsO`AqtwzX24D94*>S~e5YqO z1f(Wjf1CkMI8(q=tk4ZDlpV<(UTOv|y4pkr%6pQ5w5SHpMukA>T;#ASRf{lJUG? zWdnVLbmsIy8WciwY97S#wuD1Ts1r4m2|Ku7hqxL~EHGO#qJdqb+qu4~T8+69^&vsc zcAY{g>c5kiVakd~K48HO6gK-H-FN{!z_r);*|6VvV; zMYg2<3PUv$=N4p`l@{F{M~wub;2N6}aH>na8rxmvH~YKlzeu2kh`=%qwC+%JfT6C9 z*eB~}Wm9KvYyT1cH2p4<0@;%MjuN90*70B)p@;#gM$ROmH^gmGjD=sm$O6w);wnld zv#fO_`D9F1=}DnO9flDb#_+7Cvq3K+H1@^F!S0Y41&YH2uk%mrnv)h+Bh0-Pfwjk; zr*+W}O4;Q$N#x_(iUK}S6Sz9#tp_cXHm<6llNVehh9}pa-0fRb9+z_Do{}?gZ*`hj zzNi&X{zYowcon!TCifR<@AgyEn|f!KWHJ+vILQXf&PmV3bdlHFcB2m@s95esY5kQ7 zErJ|osdo2lH$O+X><$*UGDXaGN6t-nU10mPem}MsB2d`9VLN@^BV$dsh`MS*D~bNT zzto_vc-s2c4HzaCBl(+B+dNxUW_27+dI_! zVOtc(WxbA~tKWC~+suw*!+gKXOXu5{27?Z_T&vSb1wDu3sEtn8pZTn#;n?E}B~d)D zn=K>0C|m+i$L3g)=2K)pEwti(vBDSTR_ztHQxmR4+wvZqFiLOjW*ci)_J9Cd5$e43)>u}7*zJBJJpwyi~NF% zEI}k(upajjU+Eg)A$5O|@=KU6&$J>m{Pxd2j*3|9rZblUtWhLAp)n0?U@t%`|7mGj zUGgHDaah&#S)N9p!TdCzwDd^Yc|iqE0pIA`*F@kXb&JGg-`Y4+dECBs@nQ2kl2wtI z$qt{m%s6xn4x#(`k$L3KBI~2q9lSlxrdV_qXGt;RyHex4mH@$e8>gb2k3oi2^V070 z|7Fe&wmbaa&RN0#I%jJPx`f17uIU;lW`cJ_clPN*J}!a{kLu6Z{vx^f3P~dm@2-G% z#9P_HaY)}^9L4RVdws?%WT!t-N5*WOa7|oT_uEH`C*2j5GYzUv>`FS+Nv7M_8$_EF z>sg$?;hywbWVL_-P-HH4;`0}|xrvt-z}x7|!`*`#{4Xr#P}m7{GOg4bwYiIZY4aQZ z6zf%rfP{rX0k@{KAT$<}OuI{imyL?nXPH2nATRLw)~Q_}&0bBOK0BD# zfNx4;BpRryX||28MH8APo>3)jCv&|N!tb<&Ngw;oXbLX2tWe!<04+yB>+)%<$rCY< z!z5(~YFN!{Z(5Z77>7XwL#3tt0}QM9%F9VKRwP5XkQ&~TJeFIrM1e}uAtxuNZeKxg(#?ML zQbqkQQY~7U8wsPoSsK}i1f}@s=kC0a!-s?Y+yno&U$aiyB+$)X{zY0qZuvg|r$AW0 zcKgHH`wsW}TKfl7o1+00-%t6<3Lk!;QP*yu-+hRH0Da+I;Sn!FU;sTpBfW_H$9oU& z`f91kERmwOJCNW3lG_5Ii0V8s@cU||m7?8TOq_{}X>ywYPcY>7z0;BIXKY~k;{&@T z?|XHLO?X{BgaCi*f>?ciVf?l=^-A)+g=6aQx;jJ(8~Vd7umLf|fA;U!VXy6Kx-+#X zfOLUMBfhcj0%0Fc;2)pm{{S6-8@CkHF@!b(AOIy1>;M7**h9GM?EL+z+*~*eL%zy? zgmK}wU!t=kOg-!>(I{T<5g`MU0ZvAFPWyldE;GNaRAG4D+E@O(E|CE90C#Z9Z_~G{ zpbwDliQZSbW-tACT;reuoBp^Zgnq#g{#y;#Rwx)qJw3$20v@{n9{uzm+7I2Y;%Es( zhdzV=%8(1+s15Lj#5;B#p56DocB*FTUQBbgIY{}$ZROVh=gY>jBT8QWGSHuOP?-Xu zK#eMloq;44&OEceaaB53z2u^zA6xE`4VX$E{{WTWPJjb{%X$&}f8zA7s@I+71rmkb zbb#!lKj!?Wr%^}O+Qa9s{s>n>-5#}7P(T2nQkPx8-9RQ0^!e}pE!QNZ1DQ`y{7@Lb zEo@2}A71^(LH5<7Tr#%q{YJr#H^$w1WaIDiIp{1DTeNKwVpo|_iYkJq0Apq#439C4 zVD+kyx0T{kq(Qr`jRC+rPs)$4+qYf&h_s_q$F7yO&#Bjc_+#ryZJ5o*bcDT${~ z9y)Mxq=ROykX-9Ha5gy)AgIW+C!XiNK zJ*#NmC1*p*@r!^r(Xh7|nO}F`h@@{GE(_K#j`+qh>pncTU~x30S(w}mp%apix)G3= zl6q^svgysZbh%Vf$e4r>gk`QEDj2r{u)aRvD)b3wJf+;^m!F%7x zBISAGw?tU&XPq4WqC+SvYanG)8*_-j&oK+FBddcT#Xfrtvj%;qNme;v(xW;(Uw8jP(hcIoZi9PbF$(TPpB-WLSAVIlbF`KD6)X z2hHQux)`#FRmZYSK)6;oW~0b-%Bx^0j}_UQ!}jXN97nJ@k0p>TNqBs*bxTAtv8`)z z?|5r#*k^7SWs;k_+r=+tL&~PSB94BkzLsk+lvDV}NR`)`s%cW1JGg|L#!=n#IAX^J zIKm!bhTIV29yupC+?$;rT+we6Oeps8%Xbx`cMS}pMZDA(P-V1eUfpGhmQ6NgNhJ## z#~U$a1qo-u`upzdqG=*X4jZyWVfAunzsRp$lzv$et?9lZ>Y-|5u}n6$oNSE;T=(w zxmO`Mv+jrGB;*ai6_b5`gzawNd)xbaR92eaRi4)3K6&GjP zH7P#gB(TJqjBfo0B}OqPRBrR3GJ)38>B%=IgdMX8YX(>HwNt?EU#y=a3WmFDkC zv}q)7h}B{|*jY>DGmWr7*luc?@jnfXO>M5Hx3bekt(D!bp>t<_3SQjaPpCq%MABHK zD+F=aypM4tp$Ks5-PCe2!2^4?@>CHx-M26Rq>+RC-<9!GghK1(J| ztl_*Iz4I=sCNE_kryC(Y{YH_I=>qTMT#=%xnFdVJ11#y{z((jM0;0+gyBeGhH~3ZH z$lhXM{x)aMPh$JV@LJ@Xv@=c>vCzMo&)GB4SlZ*cl!s3BP8kSUrw~(dDZ|_@VO$-n z8FZ9lW4J{@T(m!hhC8(fm3+9ziDYYdETp(^%z+($B?BWP}AzhD^R0MZ&T*Vv66>cskw~bbHGAqLzZ|{YWg&CCw_~ks=!5igH ztD{@!x~~5bvO_YIlX?J%a1Ge?PyaJ$2vz0B*Oc zmU+JjnR{VrOow=KZxdSFV~fOivn?>>WP}auv^B{Wo6qHA`+ge2V-n`^HO~3VIaHs= zIwA>1H;Z=dcVa@3H7<>t;C+xLrDWOMT#~}Jd?c<%#CYovU5YckZWs*E=RMkoym1um zs=P!omyUwDqRLdAIh=0EXlEXIULtcMRMkDUqRA4*vJlG0-jpsq_W{p4t|K8m*CUm- z2wc)0AmKE)xSD(DmNo92FtEOEY(-*P1VpiSd#IY_1oprg?YY$4#|~-|ezx9#U;w)= zQ2_xF-1MN1{(2v3^bf!9-^#fOU00#X1q-g`GKNz{DQBfbM8_XM4{G%hHi`kh!U3)K zsjQ9gK+4x;^I==~=Q(3ci)zlb&I5X1w!{VYvnv8ykFVn4vP2oJrC|wlU2c+>nuud; zDFq&JxYl}*q>DsMRSkt)x8X(S!i>FPlMCG>O)Fi|8nVGER zsdKeuaN85HQW5W?5-pJn?}_5Q&-f6pQqi~+~3J~w=+T%~ZCT(f$rE)o->bk!gzk$RIkPF|vzqg@m0 zzVh-M{{Yuz&H?3!0fKf=1P9?A{{ZYzcJ=<(pz5}D@htGrytyyUyw85%oUe~BTc&$A z@&5o4-k88yTyS#O%3CYg_SAi+DK|R$JRs$w0L}fPacDC*QW*pMWN>s=0KsOS5lCbR z>pn{k^9KRt3vTx0Y&RI*T#RGyYjKsUd`v^k&M74S0P7q}GRQz3gev8NeHyZ+xK?t| zjL4bQGHKmOZGR2Qg)ZomDkJmYNCb$vQO}ksv5{Ap#y)Tx3c^@%KMCqwJr(86)OI&F znseS)@)Y}Bmoc~h0N2?~kFTJ6 zQ2c~_N9A2rP4uLj@+Pwfkz)|}?-u0L{gNL`qH04s;_CL& z8+-dGuc4U1CoGnxTX_=U*gzKEIZ{HA`%^;F&gl$F^8$h!zPVmqXD`;vn?cfCW~&J6IuO_i?Kt)TyM< zra6m*T-xCU@4~!|Y-8)T;*GkP-_|Tu{b<}wB4;h94q>KLbjVsx+LtpnR}HN_6Cl;Y z30P@X-g*llCrMROISw<+9sB`hk!45>kt0YSE0-ue(irFG0g;dx5Kp>ljgGIvx}C(D zZI$)B`h&x$TrHbhO$EY7XlF@QXyvy~=43F+dzlJM!5PGT-@I_3_igLcB~I_T0LLLV zCZ3fL4vhz3_Mi~#AGhD`u5&p|nB}~b(`jqz#1u)`Fp`-`{Q9v>AIKTu*|m2fMMaxs z-K5cDHbG^RRdS-Rq(g#g31yQs_)5v*DGcjtM{-*hWE_LW+%D@jW(zLgw{M0@+pvUl zVIdg?-fmVcv|N<*sV~-QiY*Lw%tATg94-ndflZlMW5c&D4-t6<#0!36*0^#udd_|t z7oDjjijSGW#YN_fMVK-J5=^e)soo@Ob`DJDn=?l4dX!|jSdrG!^D>Y_dzs^Mz=#>J zB<5n=;X-?^!<#5UT#S9%Ca16P<)UdfFwYT=<5abX_wY|_i)QgfB-c@itr3hd+g@AU zqXCIxky!~>4O-?YdR~P%lrGDdbOGxyTrKnaLKfCTifNDo;9 zdIv+VgvRf`UtZhXk8`iXTOx3B-^Z7X)$tR5+4&ZB?6p`)qi9~3`ffVovrgOIjUU=K zifb^LYGs8ZAgfi8ENgi|=K;D)zbphy03aeAdjQ_MhQIaIWb$0w zNK#jD!A3!2(SneAk1xo@ZFbA1@db^w-kT&dTgh-rOWhR7h29wvl1P?F*(6e|9Tk9F zw;U;eZThVxXNBvsfZvKebedz-r$uFPyYaGuZoC*YjpSS zVF1wVchj-;4gI?9zgpuc*rGuI053_ku@M0d;ywFoW51YHNbcO9p8Y?J-eZ5A`SPrE z`Z8sQcNSHcZH<8-u5g`sIeEXv>0HC!*P)alM((-*2d`S6l>yi$b9d9fO_%Tag>nY; zy+EC=`=CR8zw3fqexv^Y)j{{yNJhI*fNgdIkFTg03IZOVEqCqn^`Vm;Y&(FCv>Orh z{{Sza%qpu-A>_o3xc)N_+m4v}YR(-lG+T~nseb23dyWA4MIu7~|<+1eG2luPu7nSTLH~n|rI}rd6`rww(eSjnFUA;r+T~X5# z3B*7|N`RFl%Bn!7M@tc25{ylOxx-M662U5%k~KbuE0QkezpB2 z<2<8>2ADHjppF)5yTQ3p87J<+xPB=CxB)~ic1=V8zG4w`YzVG|ssYGzl-)s->geC< zeSfw0e7;}Xt~jUhn8WiQ?FPWQ?NU6^p*mtmlpx z?(HpZ5!w0DXrq=g8ZG_TjE#xd<0Git3agtlV>m$f5V%fMy#TGe@kCW{-~qXO*AQ=s zXt)DxF{@I0%50OVn-bG$jx)6iQ&w zfd1824xAF;jv3$`OEys^*AhKQh`Tza612FHARMkt4~|1NoiUJ67V`qt>XHUlQkAjSC#5M$Qk6449bOHYpPG&1vVK8+{{RYc-9?%% z#_f3)o6Ex{HcjA!i%f9>?RMmC8V!(Hq4EU!XMt$_+e5)a-v^JMjf|(f9(+Grb8|nr zo5*aOp8;V{bKJQN5_F`U?Kt()r?l~zTndF7ZP1h8JUWm;8SWjHc3%$@NBVzW5{();T01*5W{I^qVs2Sp zNmQ(fWfOxD?pb7-WsyXYtS#PPZytOucqPX8#tkhFKG|1P`#)h_OoNqTnB?p2d1gqY zfoB@ZU2R^+TMyS1!NZoeJWZ(#E)J@VqT33B6`$pUjfhPqXd=O~1WW-I>>47HDUiPi z6saUaB$yCDNF*o#6hlB7u0t{u>wuheLKMoIzP1U6SQmb~F@U8F0EmcyYq*GhpAX~u zb{kDJlQz9Nz>w{vSZSjggS%;WK$|VU{eV?fCS^9H%`Dq zL!tHbuGCVFQLrkxx{Lszs&8i5PGt@|?XW+@a)&?{v6CUh0H9)ldMdDdnaphPUK_jb z)l^H~ZJ3@m+iakR^5w}ULpF&>N+Z-{(Ollx>F7+ShY$Mf(SJ zs@5yH@?HbT7_X7Djif!te9cX{Gxd}@s$5XPB33tIP6c5erB_Yi-8M4jInJS5yeYTP zpzRw4Fv@-oK6)MbTt!Q;kC%^dfxi~%qvqst&B8|k0{|HnieL~O=)u3TuPs>H#JsU|bwXr(hJW2jDh4wh|VaB2qLjdo=Ewca{*56Fga97%nmooj1M9P z{Yc7xB`?;K{{YA@@l`U`^Rb@Gscf{l?RPgKOR90fL_zXJG zgE=jL_twBSuKNADmevQkTZ7)R_YrrP$@h;iUSCeR&xSFBou{|6x0)-NIU^p=2$TUD z9OaZ??Y1`jfm6NYrTWr;`33$ec`1IhpZ-CAioW8Sg)k;!7!Dz@D2K!$_UJYu8t>RE zlkDU`KwTSK0T4wq6jd+)Z(=$UkTv#*o4@1@T7vD-+a4Ka&JRzrty(w`WWyQwMxLHv zdVN(*OI+6Fq(<)Nry#A=94sieaW^L&5ZQG>Gbm&Ttc!-oDsf1rIHm?Mx(X%$&<#{= z9l*`Rr6nA+WP)!KMP@IdmTcxR(o2s}E>{i3Myn=rfQc4rsgf{g+Ys(CN8-}AnTWB` z6DO9KU&?3$T|fZ?Bdw|VM%S-@{lo)fUAG;1y~e8(1!EgV>AzKvxb53QCMr@qAf}vq zJI2I0S5MjzW}+&Ac3mAc3{lYNb^;ZVTN{V7isC1dQ!BExYOLMRQUGFCEJGc(U5}8f zrqUK$SZnBa_ymRfUS&3bCgR8kk#H+(2Jq)zN zb=#%w25J%Mx;wHNG>56c`61E*VK|Vb5f9*^kO+sApJ5REf`7ys{mR$Z0bTHS=ZOoO z#@Ko?7X8I_-coT7Je8Y^hE8H03Mz^Y2%4#N2Y!VJQvhpV9+j|f=c+f>?`bMW-!qnp z9FxqX6OdN~leRke`3i*EOcpE$DmzMxJcXh`%IXbD zaM|-G1u2AvG7g&=L{%sprYMOHU;_Y@dw_*QpNPHx0C44OpI~uY9|*mXG?Z)k#;GgN ziuVM%A~20zszDGG?AI(INT!SmGm=7f{)|3AL$S?6#0{184$mecYNMH6N z7p$Bt)!RpRJPUVCoVQTPF5Sa*UX^54MM9Z1QdERGXDF2A0|0y3|6PW}~R99AK*aHRnljbXL#V5F*471%V-A3&OWs{#aS;FlXbvJEP%lt`Rd6UK z1EV5Bh+PXLrd=((*47wzy*PUB4`g$Ja&3X3u0J;ajW*Kpd#i zyCw@xN|i3QvB;1LkCisuv>3v}Oc6e35z_qGt*S`!`@nJ~Db5 zLwLJ{ICBr0?J2BLpKdGO_JUUA#xaZq009vY4)xK)-WDa+ zbx^dfD{A0Tnq*bsVWuKw)kKPz#Z5)a9O1{1nZyJW6*bf#AX6Kpz#mKDLK4Zkl1(rv zzO7CfQ;3gIj1i8&06X>o0sDtw9jY5VBAK1t#Lm6PAmlkb<(nTk9kJJ;&q~I}XKePDS8j-+*hEo8X_gYO zRR?V6rrU4u#Z9wilxUzR+)6_i(?lSKzF;L1iA)3EU| zurlDhL}cVc=|sh#iCqbzn7Li)MFVV${vbS~Xcg!WORn8$==1>;V*K|Dhw`JfNL5^@ zVtgXFBysZ4A9tyA^h_&fCrF@W z2;E6Hhyvy)7^g8vZlaXM5hwueyX0G1ZK*w2&-HSpoR4tXP?c3BZ_aY5aycnnkF%^pYy_(qfoEWO)gUQiK_ zthuXtDms0AU`W5FY)iA}p^7{8-M)j&YD~i=KAs ze#rw$K7o*L9TgKQqFZpyqebJ_aIsq|B0{Y7QwyLcnh2m(Jd)va^zZKu?n=SKMcnVE zvCY7&YxgYNs3|tMEho;wi|~COQ<LHY$uMO0Hzo?CYcwhH3f+CeOKx6;cz zYR(mqDl)DzP=;c14nQDeWaBsnnBn~<^6cH(Uo`g?-Q%ncZxX~p9$6I!&r-+U-(sVg zath~Reys@u&KBR1xgQ)$9TyDpZQ6wn;L(dCzF14&LLiD~&~N4I^R0d{m8*Vuif3!4 zR{Fan;%r-VhLKUDMSQ@7h;;Dn;h=%KoGfbZqnb>aCcA;bVcq9IR4Wn5dZ5;@Q{{Rdo9-r+r%~%X2;lE+!yeDL2QOH+} z9m#ea*-zD)dz|o0)Yeo&%sXOCO^uij@Bb;my=yf5P4cK6*<5w z$+QgX72 zCbO%)-?!V?*YVsT-MXj0ET60QV}c-H1A7z6cQLL21s9B*w^3A2nN+JKmPI*P93MtM zjbm>#tuIi8t?%^f8`v0OqPnz#c*yDVWsQbMfdeC`Al8)LAwC4zCyr3lId_aQ*A{QY zkwB~aj?9x}$xOMA;af2UT}-Gk2{Dey@C}zi%F<6Q=r}p}CXX2k*0iidZ1vR7UyAi$ ztu6d^d^=(I`+i4qs}4evD->o6g=nmSYeu$ggiV2z+_qjxC-Dv2`A27MWHzlOB#OkX zlxG8U#>=9c=FBcTY6?3mX?A5j)R^bTy4^YP)DesZ1AL8$@C0w>Uex<5w$SZm;yxRV z(@u@o^p=`gr4~yg1Y4^|a?%@a@s(zU*~|sRk+-vkNHyoBDOn2O6s0LjQl*cA-V>Rh zmW-HWo4h3PW(`>FoX1>lBS^i`ks7Ax-tb1niguz&GmHl9)@V1x+DgPC{o6x9L*9PF zJkBqw@TK6&Jj2cIrf-HW7Q(oIBIoaB14BC5$- zkxrrr>Kabtg_do+9Bgc4WP3&)z_WO^(db6Ci-koNjMy@0f-IV~ZpE<@NsC6P6(k!s zY(h6~l0-!!5QHfMqHu2r$EqmQ^*H2v0Of715R_}@Mk?i*SsXyFJHOSsypjh2&>;`x zFO+A>3ip8KJQ2YU5aP+LQhirhmN>2=;k$d34{IC{PLo^BtK7uNa-!xL?dMdXDC^* z_S8q7byRH>+)i?ic{7HPO_PscXqsp@D1%7GWdzJ&Oy*CeBvL6z1OOn3NhfR3~S zR87Wc*4Jwmh_rT$V|OWnDwsg$SV(@A2y>jp*+D=ZcQA!y}nBjhs2*R4Sw?V=C+#Z+WS#>;FLVBv&Svnv^M;{-QEjOrNczV zMglOZjte)tlT(%6HiQ5O1JY3_lyn8wfWQJK^{zd*!KD1s zEM%R(NduWgTXYJ>9-^#ZDa;@x>k=5CV;G_N1L@mi(2UcW#wfl9>zO{3QZGRYas#7? zfe=k1d14wKkSR^v&rHJdnYY;JBYZe!BYYgV38 z_maahJgF9BDA**%&d3QW%o#xUSPzBqbFE|KIO{ZyM2os?*w01j#I3>7s;T4vBA}bd z1CWXN;wCZ0K|k6Xq4^E@a=h=*v9F)8cDceCo<6LoE!9mux#WTnKBhqrbghQQcOhysn(dEL)>;byOuD; zlX;7Ur|h{XVm?3%YTgXq7)&NrnG}w0^$;l$P{{QV6+qxC5CFt6#6YL3#(NDO?}w(p zwK7d5l&v(77zaJkR1ySPT^e5ONL-{~$PpQWkO>%QBjUa_(|bzO^es=>Y+%={; zfTa;24#Q?BhzUeP8sHdQlh+aKD9H65yGB7~Bm|P~LngP9;boN)=@!U>Vxp@mVkU}3 zG0r6bHnPIO$;FMktQ>W0!?>1-wjJG?2#4@V6tp`HaA5qoq z?zMw^qe}0k=+>98HQnU5x`NMTZp&|LB$Gz>7S>B7lU%HS^>;8Vk;^^AakaNBUQ5c)TR3c9}n}iP{c%&T_HJwMGQi_F1$&>O1k*ujMsK6HX$0kRjan{4g>=fg)3(T1x!*2I~zqX2Y%m}ZOqd*-7SG+l3l}l zeZ$~8ldN>!s|dr}J>=xgS|Y3Pate#{w@6d=qbiu`Qk;eQA!1w8G5DtUR`Epc(2i_` z!$!=`zp}T4kx`mTzIwUZH9=)jNT?v#hjQscq(k{Y1^}x~Hs03POVf1;*v~GfW+iER zu_zZ3*~4)Jh*czXNPD9i7Ix<6T(dCWE5#b7x2bVY67cPVwT*`d>eqI5_N%H*YYXXi z+SSdK$eCxJ*=}dPeL@SH#uokXXp1OFp+sA)X+fnWkL=lZxqXx*yUYG);~GVQ!&vsq zouhG0(cLPE2w_|WR7!G~iKZs%F?G7hI3i_;OBPAZvc12M%I;P~zQXO(GQUxi5hHa@ z&>Iz0#W6PeNOJ&*bR{;xDm?CN4|<_8g9xLNS~GL69PikZj? zD3WfIDuz`BM5Q@8bL|p|vjeqN^PnP25XvZ-zzTHH0}(Yk z3}UI&AP4FIvcA&c)H|rHbqzY^TbZW1ipuiV)4LI?ndFGP1#Y7$BO;dpr1!FLbByN> z@xHmkG2P#4{5Qs0HNKr=Yop%loIS)EjPotqLv3bmrMJ`t){i%|Tie`SMy_JCRb&x| zjK)pboxAOL=dI)Jta&YJ+@gxcky1YGg>Ko3${0*#0js5YQw@k15>Z5q0wdedN4&*X zdKPTir{%6P+}3;LOB!VyuF>GOGoUaxi<@xGS4~hVokSy7iy0p+UXuyMF%T{lH$6UMS^e{bX>TLI@odN?k5d0T7bR{G++7coVRPFI?e0(Slu~G+syLvm7Nf%MUp;uQp#Dm z3$u*%T}H~yc&|;kjo($&E+2^aP};?3r_T(eTUu&XR@Uv@8yTj1zWV1+xHk6lLv48q zLYHaX{FHqqi!Sy_&HG?CZ0R?w)k)K%w2_Zceg`d%sEHjSqDB!aq}pabpboWFwfqdF z9WlNwx09&D%q}9y07*kWQR-hCuPntdH%TI@1}b7CIgLV7xMGD<_Dgl7ydYX+=W>SpeFZBs+?IH)=b(O9aIi+H(K?G>}YOUWDGYP{(we;k>F`|{nN%S+^MeZ+5~Sp25@7K>SF%we0fein`p{L2xyhVth0 z>GPH+B}LvChEPcaSEz?zKPn4u8MnIDdll^>^Gdd~wT>tU2XQehxbKqg_(5xFeFMcK z${p?Dm^5#OF-A*1DqUG-KHpM80@t0prQ-onO-0D@m9)j-i`1W4*+rnb=TBg6pEc>n zq(en0`gS-}*JfS3V=S1aQ3Y`<;1NxEcefj)5GWU@%DGh;M90b~0QC=)Q4tXCUH71y zarX9%cCwibnwb72ie{rO%BQ!H&6?Kw91DDTus)(GT+*^@SECvA~hep*#UP44! zJ$8l!V0fQ3GB?JLoCg~2y(@-T-`<@Y|d3g1WI*8cduC5U+KEGmkrMi zUTONIdX2b}!&bDpv%Ax0jnsE{iFau7+g(OW290eU`{f4*1zh>?*}MR=M$QqDad zc#ff9@!neM2^4G|OB;K8=R;)dphw=^JZl7e(gSfUYXq4kkufdvgYO2g(?_r_#(bGu3it~O5Q7uL)m4!b_^$>Glb!Yxb^H?Sw{X zt@R7oEo9W=h{&lW!o|rPrR}+y<8m|zr72!CuhDHON>Y`;zEgCYxM(o~q?BAFe1X9y zjvO_3^5|yX;Ta%qpcNKxh9UGME8-wg1%1NY=TPPV0#hgxr=ScWvWACa>!8pGdUpH! z>}#@kvacPg;mL(XN?>XRHuvN)C^BeIUqqU>MKb)lNE+3A#R7#hvpT?OJax|KzGt5F}vud*l5G| zXhZXXgVw)AW^XY~2#I==9f)iPU^*xWcI~5mzP;+jNK$e^#@%}EJ|1x$|VNL4}7f?yLEr67*PM0O<~mu&$Vg(?S z#Q`0Fb#Geg`*)z%ppSig{&ghtD@F+0-pCt&7XzW`w!`hotL-aJxwO032^ZO;@0mv_ zk<8MtATcC+#j;BRPBz7I(jW+!KnH3Uw)fn7fCzoSJKne6xgN}LL{G2*F^o;eK{Z3v912fz)x>+-g}G|L_k~K4S|wC$T$JE$-yH# z9lFJtx=ey(M4+NdC)MfLqF@ow7&KuL0QzsafCM*RZzKV7Yy)0coZwK)X@NEAXQ&7z|FrWWb<0H*o3$Xgllg z9eM}PLsUJiZmcqJKsXo#ft;L;zOD0-S%=Uiidkm249Kl)6(l)`PHXU*E6VjE~J$=s^dlg7k~i|$7l+W)RvqERpTM*7hmrW7 zBxKpCZct8PB+{^QYStsmdfQ=*U@t#=GGe@Bq*SEAUdg#CNlBs&luS}8q9iX!_W6s# zUoSeyty1DVY~EeLch(=pxz``$Tg~;WU>Svpm}82qs{wmU+>(%1yBpydVo6)ahiLx* z+GU=`tmZY4pr8>tfM0h}&u+x`?+Y|>XT9!bB1Gnolokh&F=XdO11!LiSd%9UHlcT= z>o(>XwAl4HR_|3X+v)FlY!=?`8*8_?GAuVD-b;>YO|nYJ+_qxO@kHc>pLMpo z;}~PZOSR<%`^$7wcWy{1&@z@ywq)&lfg>VG(j4~5V&+|%J}6ZM+qeXjJN3v>A*neY zc;xpyTe-NG31Z?)O3J;YE%$i}?X~RHB5&-2^;ULL=(p0mWRsIp9!bPZtg_-0go8%o zcEuJEuVq{_XqqEfTAmdg?7rRHEp5C7IN8;ce80t$@s~99pJ>Y`k)tEhlRcKgGUcC& zk(#(&Fj%hR7(};xc_!jjBZbOl0juN1o&@6#TgLI<5!rWOTKtf^?haEMG_!d-813b+ z35l%uyN1Cli%v#TFd;_bktCcEoT_peQ7gCoCvOt$$x0>E=3u3#i`o^VNT(g!KYb)n zGN(BAoQGaut&tdJKJ8vhYuWaf9FsEXSAU|WivI5JPLVGX#A((VuCr};zl-9u3_9fl8$ypOomn@>7vxtYuxyzau)2fq#<&hp@g$d+IRU;{kN2| z&NX9pUv^5FmTGF`z7T>kuG`yg8!d2LGgB~a?hATtD{b_GszQ~TNj60eF9z_mE8DM| zHdarwE&GCd7I1@-vT>~C8^m1*+gUEiLKTxK_$SSeBODU&uZ7WKr(vBc0p^)l_oqp6 zsCo+R@ag7OKE;XUtD^}@wu*7S<$BD_3}*9gY-@)EP(+}1RFle@~pXw^9`n-bA-&lrJzXj5*x$sD4m6NjaS>hI=}< z)MwN6i+dEfmgYOyE;W1Du6R^}Pwj_1BIGf0Q$)^lgb z3mcM%wz7vJW866jgdoUh7iWPzpKjvSF%tzJ$Aqvhw6X0)40jI*^%RdO{I*u9q)=~F zLoX5x%NvF5%xNcKVN0HSALFSEUyidi*N;)1%GNGDaP{P?NDF#d^Yg%_yc?IVzN}9> zw_aQp+D?z|iAJgc6((YE_rpIu<4$AoA(7=YlY7O_p4YqJ*gu=wv@GnE z0UaYQYhF%GpHPTnVD2oOtGEG9zA6268VCe4$4}{Lm(pJy(BojlaFCQ8bEtB)u6?ViGD#dPfTXjjKdy8)N>EUIS9wrRk z!@IC_z)3md0F07Qj$d?VY+Vntom%O%i#YgqRvLE?S>D=TSzkeY4bs}SwGYBjP#p zO|V(>bnRTB7qJiUbQbWC;{ zkK%6{FN=t5b!|3p6IMeLT86!^=awvFf_F;M?yk3Q6u2&+fIB5+Rdl=8##7BuI&LHQ zZs)5TmHbMR%W6X1#nUuXG;!Q4FWjh|mJa=-jy{qF<#`=>+^IW|ae1VU%VOYL zjb7eO0yyvVWO?)j)h(X><@8%gbp+5>-h0U=6WhJhGTX*^ZT+ec6$7daShf63^Ry%^ zCO5iloHvv4EJh5**iGgu$aZVFyE1y*#S%{+SeFc|bmrPiH@+dAJaVd63@nsSnu^M{ zQL&q-DGf^Z#b1;X^D)yd+hcT-fX%pvI$E%7Eb~R%R*bF>fE!yH*%quUY@0@LSn}V3 zKd>hNkqqThCJLHJ7dpx*SIYQ!z%@WY$us zTy~4;g)zjt*6dkcg|wN^uXYW#M=p_W@>I~JY{^9mFH~+`p)4*gwWUarTJ1z}Vfi4O zv|(d~%QJUe!ZNd=QO$w#hy;Svw2cF@i;1MXm-j9t)E#89p5su`%3sf@U0&L)t(qm{ zNiFQN=@P*+#R5F+kie2mw(lLiS!np5ayrQO1bYbVb1!Wpa_6gpfZt9P?BxE<}X>C`lG(Cyi-!a^xzQduc8tU??yn>yzyob!6aUQX;hWsRHLFfkUz zyJ}+FK`T<*kBx;ot2Z;S7cb^+31==GF0_R0%P}!D?8hoceeCErMHxuJz8_gD6>)E# zc`uPzP7XZLJXW*r9BBUMTF{xhEK8c=%DCZJxiNu8Mg7%aP0iXbWK79Pc-U8u;v737 zeQ9~bsQAEKIph~6*j*3s-GqCV8q`^X8S92da@@47n7LVl7$PDSxi0B=NK?&92@DbO z2tHOt(Mn^Y)WiW1w!OFjtw2)0)*2fdSz792bra7Ww{*r(i9C@8WaQ^j%Mfl=+q+ff z8vr&A7}L8oTiz?;8#U1EEqHqQbj!VUFYQ-Jn&Rh8v%Fw0W4bnGW}f`p2_<86W|@`- z?%$MNHM~)IRNEzGJh2G+&$jP;zmo8lT%VYTw$%@HUHClh(X<8~qvgVtc@dtD zev|a1(N)3*@=;XeAHCD!dyy_HY6{0;#_lCs816eZ$7d;ge+P(GEvtB5@lbM$(-HS$STB^8_GS(K$cyjXwCC*qvQw>Z) z{sNmZn8~Wm$=mS_B3M6(lenS}5dKD823Kdj;No9Q#HVU6G_0&sMW4qJ%W(4s>F+h9 znPKO+pCKQ-Si8u%-rX)-BS?UujdCRelygS?Lguh`ygk`Iqhv1(TsNgn6xWeSr?#tW zZ+mW*`mCHWV{;@?-Xr%@l(zjDBcN!bxrp18l23Zy=dNMqJmttcZ;?|gL|ON}j>^J| z$IYyUPGh31sO)Chn`R6l*ib}&<-!sG%bU1K6hqZcWstwY1{34 z*4Z<-NjZs2E?s6zKoaD)WJW4QM7@x%+87cLPHQQ(rZdbM>Jnpnx#W0cjUT#%&CXe) z02w>88oH5@h0i8xhZbpFlt=mk)Se&Jp@UVo;cYWcw!O2uo(I3x^xZOBQ4&uqvyC=u z+iR~$D=#WM(X(O3Gx0IxULK9K?Fa@K?o!ORW%H!8)unOUE@fcvsGdT53k;WN z-fhn;h{)TLC`UFVQY_6IBN)11;Rz$I1u$c8B6$Hhp6`f@rS3Y$SkgM*x2@}P-?Z^v zo|UC;N5;o0E0od(JDCaFf?3IwQ19n1NttP9LZJ$yphSqGOugWD1oMX>vZfo!FxZ`~ z=Y?Bl%MQ`IUR-ikv}7H}<=pWS*CnkN8Fb1pR`+~cdBV=6AZ_+??+V3TEZa+@L*0%^ z_-OJ|A?My!-F$z*jt__+bJlNxup;gATd)brMdSOvbtxE3Uu7>P9W{0~wb(HROUKzz zvZaqRe_{lIbj*ow``tp~&e}m7v&0DQW8{&W-R_xW9I9QFR|A-x&g5Z%I<(e&6Ql7y zt!!>IeKS&u+Dn_;*3>NENawvvl#@=KWw={(yu0saxC^z&UiDO{=8dtzw}~EkkL0FX zI zioB|K#D$+4sTBveBP)4$cB!JfgAJS zy}BeO;1pFU3n{9T;cwdV3>qsL2#^(2)Q@!=7z$AC0%U;O5I1cA0PF+jupNMF?f~?w zr*>KMc16WEW!#bD8F5<^kKkrwlvM{F!!Zo?c9Km!rLwEEa40-%svza7g`2CdF$Gje z>c;t9xtc3z>&)^ZP=;|a^X+S8QT~> zSUYC6&c92by(usq}?e3MLTP^081U3QZ zu3+A_p!FN9#Mh{Fh=}X4ciaQkyB6g#g(`wU5HXY=uu4!kfp#B0!cf?J_uqOE?V;k4 zO{+tJ2t%ga;Hf|aNJSPX`P&iRgaAakF14>t!CaJE6hP)E0ZXI#T^-Az*@xyJKdBzy zx9e9D-9%nhK)@pv%N5)PV0Y#@Byy3y`0&kPbj=F)bxx_48E@qbZ=@boK$U9r>pt41UJ}s_El2lp~|Pj*hNzmJ`)dZ9DaVg^$(xII{DWHR=o#QK!Q3H_8|=G&A42vMG! zRXPa|wE%R8fe{mYzyMBShwb(#`u_kOegz@xDF6qg+W;Q@gaAZDNA3V0`1M`6kWdy> zz#1=H7es14w6hsp`Vb}+t;v=CQk4TV1L%naT4X;gp*6u{=L`OO1 z867%+2?ufT7$1#cKSsD01atCxPms$iN|9nRc5JFQ&MVb%zH!ita50WOBfSUOJ-UCj z=pMd<_E*71<_>@;4uC{W>N^izdTck`0BgDw#G-8m`o0j*2y93EzR|Cdk}#aX+&V*G z0t5LX06P!PI}QBx>)NUbvV1yt;CXue-hWk->BNix?%m)*qy=HnpPTNTf!{rGjMqb; z_=BWG2YS}^^Zx+XSI?k2hqrA8gTBB(J};j8{{U*cac$T`LLR+419kur^bP#L1M_SK zz6Ne0bBRhI03actHohS40r!`BAHJ?uOpUR&-%uXEoct>fE}qQlt%Axy*tX18MLidB zj$!dD(>ru-5)Po>>W5!Hga9|+?)iRy+^UAmNp}V`pvs!$SU!}7Kd7B#A_Di z>D%m9ZxJ?V$~+ilDIR?nVy&y9a6N>^L24N{b)DPDmd3wR->4et(hQC(*Rky89oBUz3>RsxG}FBrzy?N?@jO4&EaJzX$SS1Ycxt^vRkF+8$~ zjADo=B7UL(Z)GR}fP>UJ*qEXq0q}@yYZLe*{KMQe^!{Z&JNkD20O&<${{U=#N9`W< zm6fhe#paQZi?%)h;YZK_A4Po$;d>}-IBP+&fkMRwk*BD}+|F&Hc_eIq3Rzj?bK=g& z#<|Ur>_q`ESn8jlG6u^WB@>uAcDY^%ItD8^m#&dO5&F|~m!_n*7pTHvEJM>Q#0VQA4HRIRM5X8`N!iFn2xQbK9ET~0a+o$#5a1;-Oas_T zU=aZU>>*a>$-r2e$(VO`*%;c+wI)oG&0bDIK*z?uIuDcumqk|%5KVPR;be$&lV<~* zr7-#ch12Rn=Gox5hCXoI@ff2Dip+A%L1I*vC5g*qN!$SXz`KHaurSV2KWA`PQr zV;dyVgCqdLU`4ZJN>q|e3}Fx<3IzcX?Np3r7{u{cgRF-ekF6N{<-*TiFLgD9VBUGl zsUD)fRY^3_E2R~7RS)Nw$_T0kFdtwwCB58mdr;+mNu%V9d#p#kt?wMD=nmj@@WoKJ zk{e~b5yn^ABIHs6laSoVWN&vkAY_1icB{TJeFY*UOb(GsB{9^{xDXH!A1!i-D1dZ` z{3I}dkL7iMj{ZR12Zj?Mxl&Mc0E?3WOmX!172iR`b)W$Ph>x#v5w5nM<=i$OwgcFI zFx7xi0q(~sCqD5fCnIx`doM0 zaG<8>iS?);Q8!6S0zLJytmwQk{g09uGKasc>wfl(VC-KojJYCN%(QCo$f(%P8=&ze zii+kzRS^|Z0;%Pk#RC8c)mam5+g7Ez$_C$yX>CVEHg3`?1}zkmi)76$iCZ^rkxT3e zBnH_L5GrNYK?6ac$cx7oP}{)r#PPe9Wo}T)*dcPKnXqz3KN2o+ZdyL@ae2Wc<@!i{yr<5rp?TBY`BAA$^JI6#!O2vXbU4?h=41+{NL$ww! zYV0F0-W-j&9^|HY>dtGB)m6j8-HAfSlHzdj=}e1+f%$mXqiHu&NkH9*v zUEgHdH~b=&KXe}&F5xEmj*U0e%~ zIa8dk`?rvokyxhJLRTD_2V4IZGW5oqL5*;Cs@R!Jh53}F!B zWNTZIoK(%WW^&3Yu^XCt<#9Z;v?InUvYb&9B$dY+``xYEG(l-t$4ZsTK1qF{HwrFb z6N%0n8CkY1n~x#>uh`ba9j6KH3p@8z1anx%BI&@CS8y$wCXzz3y(I+{67`r0P!SL) z0CDe3ZDC}_O(HM*Lf*V%nmh-L+1yb~#?`?{|I>9n9Xk+$sA9O$mzV5~_44l9bkPa|6 z{uiGv%)6oQn?~NfAXf)4_Z%}BrYe+5V*(Fb5q~XCkrI_;OeaNRY&sTALI?nqKsD>; zk1Qp*50ndIJ$mZR#MXVncvTT-g09@YRz2a^Ke{CtBC2B`=`_<&Vr)jP)pYSjXf6pE{d3oLLsp@eN zw2%0w$2Y30DItY%tGDt?xOnNqt41AV+^)K(QD-ZxcA|AxT|*gD9L6z>V+oJ39fhrh z)xE6J$s{iz!R`Pmtrl_b62Y>=!{f25D;uj@TZXx49zqZOT!VucAP#euDp(JicNso7 ztUTlIJa|EXal0IIYB#Zh?I`yr5uCMJBN-8LXU67HbjXvW}0o# zMIuTRG|JKpQIc-qVP@r$FIy;~K&Aq@NU9<|_9>jnoV!d7t&X-oJakWrd}~ZVOM>xt zVJP>q;Enksu-8)|^z{$Fy<`D2k_fd#rA4b`lR>j|h*Xh51WE)+6w)9RgiSIOr6CFc zQk0+o000$A>U(Lh(InzVY{=5OxM8+2;t$85s|&k(NhO+Vc;ydp{PP=!5@eNCC2+Y? zanv543f0EedxIMCJ14m0EL_yRkT(VNRNKL;B$NLDejepeSuMDy(e6beq7OX4GQyV5 zPNEokL?l0r_x}I@A#)|2_#CwFxcq}M^w#VO@?Tk9G8N`iGee}gB&XgpAr(yGPdM$4 zbhp$|0qznC{{V}ebd-GZPDcu3XR;CwR(SQ}t4<+jE}b|~%C6yclxkzBs;U^rIm{ws z7{Veu8tg6ZIN&={WtS9wo6w(^m+#BB?Bqv|=2F0VwwY z-Cx{lcGIsYTg4sPp;0OI58O5JC<5h(8zMhc)+$_$dA zjmI|Q<5wE-Ov~C=T4nsTZP~yM-ljBbt%&Qe00zuHfuPr}g0=17Hzu*i9H(+)+=er$ zqjg8aw2d@0Y2T;^V*S$Y0dOkl`971qkD3rni8mm<&!|pMdMouRIV#h3;luVjMvY|yZ%wPdBVg+U< zMP!U&0}!GEu-JC1TPwI?g60Y1c?H3bbYP@%ob8`Kf%2?WSN8U)Ew$V;NSA%lSt4as zMutHAha)A};gkXf6|?J0;7(cM&PU2zaroWE!{=LZQNZ}~Q6`HiJ>V;#*o}^5*6S5i zX5bX*=@h`gJ07tb!5Vn&jPC{)Da zAVbI>LIR~qZKHy5RxDA&>|=e9aLV%6AE%p7KH!w5I5p^8-QYZ_zBFvUdQcw^&L|dz%Oj8tw z>J98+6~uP;anA}jc8m!|KJik#t_cUL0zknT^cz(Rd+SSEsO~KzaS}0%#Wb0ix4eZF zKmdp4AOgoAoSX`WPYfJYCy`xdT=935*9467w^n(M^uBAEC8q=4cT>SAmq#n2xNONm zAwZ-}Rgw?QAi80 zR9x&tOkLK~R&}v!zs9)wdsRl=rSV}dOTnE=YHb1I>LI*eiX zgnMhCo5UEpYWRuC6WIRLn!e*r7WswMB?!gj>vu6iRU+3;NpueDY)(QMuj4e35TH!} z00ru5-PHFplq@EVBUHk#Cw2!R$S0xL_4jak?O8~*nPa@UnWF|7;#7(<0y=kb$K9y| z-Q`yf$CQ$CGn(zOK0A)ZwoRjr;>-M}Y1-_e(NF|LTs&SE zZn6m#QvkY7rtt(ErrpEM30GLgAr)MFq9mEh9%7#sfTuTCK?~bO0|`TQ!C9MmQiNHP zNy899KzwD>Dch==fGN5swZXY69J4re9T{Y9c3g}V z%WevcjNl5!+26|q#&rtekt3M(2X-z?07+)b1@S&ZY{u?9@k`^})ui2AfP0S7xmSin zCLtO?y_aNpw#kV5L`$}XGjM9)n@$frKaVVOa%lSzcHL0iy>6T6N`3)QAIk>Q-tq^{7|?Rkh!i5BV!q7 z%lRzSXBH7i`P%3e+%k+iHjX;X0(DHX3T(i0o4A;2=0)R+Cm6MF0b|;B^`ROq(p6~7 zdL@igL2{T1Cs^q+K@zH}niCmi0LM9ptV|{yh2mY>TXRWi49Pi0RWmv~Y99cM1q9#^ zbdkS^^0>6r^yuf8*sboC;zjQHt|X1)Mhd*hg)(2e2a(y&FmM-?k9xS%uuUiJnQK|$ zj!5}rM zHRI+@{{R@~J)6bUg}Nb3sfvV)B~o2dxNe%jU=*QknBcL0P5L#wowB8#vN#W z{e6{0Uby1I$kFABzij(@?qHdWbX!~zOyvmOLk5haZ)-_IHc&&=L=2h#0NGWQrQ*UQ ziezaZnL@g$3jXggQmwY&vFdPqLBJJO*6CsIQbaEl;P;BBmAQ^LQ}G=R-Z(ufJo4{} zwish$%cqNtH+0@|G47efAo>aPRAg(nE!0gnvTHsfLb^>1U{uW-l~Xtpc|xj1KbRCZ zh1L+dt){nrXS!qE#kahp5QMc*dWfLBgkQF$B=T&j901_W+Q=Y_C3_WeCZefzqH-vF z@wYgY#_Li=IcPjPWjByTKwSqeV#y?C%aq+kS*c`9=#5k;=ty)5nTQ}AA{q+FauA7- ziKb8@WGP5O6f{y0fCVWEQ0!8apa4>U000002CA&Lw#jWZy_8bME(&+gGpn2-QWXM> z4D#;8=g1EluXh4lJ+-V-pqYb8^E$B{yKQG4RDA@~inLx24cn18&} zHEr+@h&~R)*b>3ACR*MyH%+T=nTysDu*i#5o%?IIAes^jJWUZyNVx!2F*^?a9@Q&X zwmY$MOllC<^`!xLMK*Lt&ExJE#bm)<+?A{)j`ch-gD~G&i=w&O2L(W|Sn)E+b_@ zxKO_K3uj_6fI4-~(TeiXEfyQ3n51$voXE(k3v%@&6TdFQ8y^x5L_T6@Ooh#EU9rxK zTTZR)e{0+@63e|+HAR~^>rqDMh_}*y1x$~oUmdYkd*q0f0dTtgD7OSt8Tb2s@ev=+ zA|gNA8m!=~$QT&5@oeK*vS!^rgjuj`lQwM$+pbkJve!$7%qRLXF0%{L7eO=j*DMNF)x?ho8Oz<)S=!lp(j=;Nxg zx70zaO+wBcM#A?`xKPkvTHIPptTGID5j;)^@%LQUl>I46*{kOjDN0h6y#D}$t|yMe zd?Lk(osunXESv3FhU|2T>bNV@Uq(S&P3U>xUuG0>+Z!#DhK<0ji1n+biV7;_WtNpm zNtpJ{Uy>z3QQ=bqnbE{dQgs+bUXlP8@`@mF0Um$=*oJ^AKX`ngu;LdKToKWTlKgYQ zBD!S~fqFw1T8XLHJAt+aF}6A}wmRw!)>tgN*2n~eYp^*}RUuIyECo?a4g;f<#Wz_* zfCV^xh7E>{73wW3N{SsnOh~Ya9gUbpKIoCs2$`LT1oJzR>_&1}oNu?oE42T6xrv=#Dx`a#1MiLh?*%Y&Fmz^Ni<3%LRhS3`72JqGC@ z33gx+5{AqoA|f@bN%_mJ8cCbhk!ENLHgd_lgJcSlYPJ=2atBdNl7b3$5}2kC0jfFe z$t?(@LbrU~xzlV3okWvB&6^!H4h~dqa1$JYQk+DhCMcUg8#cFF4Y@4+*hp4HV8iw1 zRORGXW>OG7aM)qV$_nmIE0kXtqCs@`_swT{ZwmLO$zi!8z7fh>+HTopMFXDH^Q%UV zi7GHs8sOR!F!u}#8diimmr?v`8~vY)3)XKqh#h7F&PyaV2Dcu6&gdZ0D`xU`PPOSwTNZOk#l&I2Wkm1OTqq-C-LHx~(M~H6w)j(|n1} z0HWJI_MivDzP_O_h>uTDd4sXj+d1F>NMe%SCPtKwLPWAcvH(&pa-6E;EZHC^ z$gGvVs`tsm?{9VsTf;q`qk8~~$VoJ87SbErh!K)&xh>*16PQSixzy%PMJv)t$~%W{ zRDwZ}I0vposYey7W~K9yDG?84=@Oi&7=UAm3MrIKQ9n-0x+KAN&D=0IM0!u=4;t-M z&S3;ybQjtRB4&)#DUuX~p|I#6oWZasNOTmpXwi0ymk-iPIah9ui-2I<0H;J(F?NFH z0~|oaM_Vu$L_js59`)E`pqREU)!^Gkvy&M#kxR%$WYz@8*|4hX*#LrLq~Q@Z)D;Rs zb`ddyq&0EvQQO+g$ciRN7`U7y3nXlcWFwbsD!CgDp|TG3jC~g8QPnIUpHP}TF6!>u z2<6ia#rxY`MItq;auP!BI(n>ibOqA}5 zWzlraP!$>wTqYnp1XM?`^?8I7RietAgl~vjyv3Hfg`YD?b!22#mK2{xz{{wZBBKab zF54PeWKbzUKwP^hwmF5lNNIy^49Xw6V3jw}wI%*)Exg0A@6HD2T<(Z^+Feg8Z)Q zQt`KF3#0JLL7-mQ>HJ!ConJ%Mbz5c5t2T#jie0X8b#reBxVvPA+8KjLvBfh8b)>1C{gb|sxK7hm_n`to-1CL48F-_lKIP1U` z&f$3ljdD%QxFX$q(j}WW4h{gLgQn!>T}1V-#gwTWqpcTRUto=2>JY~uzqdmpiD0=6 z%n?_Ux!FWYJHA8@h0ifKBdFiE_H85!*;ftf_webq;>k_aI7gQD^H7IX)Gc}Cl2?0_ zB`svTyzZ_K>tk+Eu!Rxlr;fvuV_rhzPr=?%xEsE?alpu4urXI`nUaN^ad1j3WI7n1mw~i=Y6U`enRY3=Dor-3Y z1d8Qn>MWqF00X{)fPqL*3Cqm9dxYfPLzlg;3pQ?X!p|gCYWbKS*sd-L=d4g}utlb9|Tgw&FOR=JH!> z8CJ{*nq-b1?Tlwm@}H2>D5_SO!zmz?QCmf|Y|A3uWh&_)avfnY2{0gXxm6%g!a(xQ zZF+{aPdVggBGN0kMRQJDO5V6mS0c^D^>rP(fM75aX{{t;fH!fn7ytue8ZZb2S$CGa z|q+pB<49s>8g{}44IN_5(}=HDGFsCgjVKu zZb((6jd{b4Rc3w4Mx>ngl9VAjWar-vir%>AjW~C+do3aLOEZ0@YPU1lm$!sm_XZJW zB%V}YVtAqEMj_dphLKh_<}955018~=nDM?BzwbF~MpGijvc2BNlIplqmVQ_@&kGKk zE!<9zoO4H<$^pVH(%_MlRK`ckI;R8W9mSazznnXll*jfNu2f12Hj-lq;i_pgPrAfb zB^RR*^u#HJLa61EhbDwX#wZu2>G96~iNL1 zaHO5XFyZu?4!wnnCHAD3MFz{J3J{5bOe4sUPmWl#B0FZ@8v46hL(36DxGbDXO+~T9 ziwjRIq!4_8(Kw(k06>mXA27cOfNJW(CAPi0H@Ym+YE5k%_H$X!CB(DYp;(E$65K~` zZ8FSxJCMy3$ehL6NcmUC9iwp+TxI_N#Q0l{pwsv|ZF=h3`%Tw0s5E;mBUqo7N0UZ| zJ4?%*TG8y{S^c5mwYjjIyk%io?B;%|+Pg7a^@tKz6IV8_S+*Xs8)8P8 zk`2*&aJx;DM~ksYhgm^fJjFpkAaqa@*iQ4grz9?`J%N|UQVGgjG4}!@0UHSd$o|s1 zSyc=0$G(SZsZn;-V-aJhnS}sYf>VxJaZ@W`a3 zRDz{hL|#X?XqsRMfdwBR6if~!a;Z(sdwA`KfId&1l5w|e{9k<`;rDE!(-*Gj) z)`11xrkf?Uo3GfhXTH}pi->LKx0*dSMQJr(($Szdmbz*~mb|%JrTcL^h;g!3su!M2 zYa%6`GH+twRaw&&9Yq0(qjz$^nu)ApNEiWh+KGw++saVo1FP`JJ;6Ofde>1T;Bj%dy<8KZ|wxOnYklK@2noa&#cLD-1Z#UTipK%^)Xr2r{F zJql3tDMQeu50Od$03Cn;D$Qq%YbTX#Lfa7zV_Q2$c~^Eg)_p;*Cu}X{WxuvY{?h#K<)wjSBn9kd2TlchT;WW^%c3)#3=aZjgzWO)vr1D7PE}qSUF)#HeSa zL1slHi$OEAoOKIzTL+n?lUNF2NXhk;PLb#nXloB|o-55>j-}+!ISCZBwTTH9F%3QL ztV?UoEb&a7N~ZO3G^yjC+fj(XsSM;7;aYnPf~=n}Us5I3jFFk(;z8gQs>s*gmNSoY8jK zJ&v!b>N;JI=y|w)H?`6v)Th(onXk2}^&3lht#p5Ex|;I#D3TkCZ6@vF?w)%wH)(x$ zh+;B-@I{t5(neW*paVIHByuB#V&+pQK&Y(#>$(Gw9E`%qn8O}sOK;qlyaZj(5U~|i zlY@aw<&ul0WKQ}XQ2_@GoQh&%0_|2WSwu*2IRr{D>y!9I+mAA5o3&d=T~@rLf=!@Y zI7`|eM94pK3AT!mBV@`$ipv}d-O_2Ilch{jl?2x}LFT^Ax0>2kowsYUDN5Skf{KSo z2pTDh!ICY7K6K)`WE2IFIf$SbqA99E zoPuB;gOs8g5U$JeF8=_e8?|4NS7{4t!}|8E#~p~ztjTS!_Ia&b$Sf~3hPZgnyThWqMF80ZFX~KsV&?lIU)0B%A4eE+0V*@gRU+0TSz!lk5<(iOXGba)+N-T zk|0_;4Pg*Oy5^F>o+q`vc57a9J&e#uAHC*rKMDQ^aeQ)8jobZnodO5;RDJ5F)A(M*>h$W74mp*Ypcpd8~ui2{%;85hc(}OXm5Am!VK1LOalz zF%p}nMlOsUyVAc-dS7T-KWKVhm&clJuO6?a@rIvi#9DTz9tvLA>afRmX(}dM!x)N0 zM7P`7!WcP0jID4@4}>(H&9s{i1k&vWn`Oe*@#zs+0z1f>+X*Aw$f+5g?s<8qy0~%8 zaWs!HC!aOr8A?*O+UT^UDN0p1Vw=uXdIU-?T=&;t{At7Iz5TzOdsihg2!V%M=>rIM z{{TW==swT*zRKhrnlhcW@u(mH>9H_~k8hZW?0#ZCyRW%Q1x&-B{{TBM`h5Jp;6K~n z{=T_oSe_cVDK9SG&$eS;~l$r34m z3MBz4iUaA`G#!KGzQ6(Y=mWN>nFOjTK`w)7hwbR!xH=#0b{$t_iXB1Ry3uqR*J03q z9e)#UV=CZ8HKhnp?gO9%i_&ji;(p>kXYJLJ%bsDJ9A|uafuB#$t!<}IAlfL41Q+*& zY%r^DAs~=5zczQ?xXw~3TbsAcy~I0ySP#fPf0O%l+MFF{VbJ;x#0S2$+PjpR2~*KPdb9zs(01Q$!SVp~`RmfH zrIaj4#g}?TW z^Ku#qOySTNg#k!VD1d+tgP=|Jf3ok~eFOHpVNA;=*rg~6Yq}{zTF`+Ca}#9|0O>Y^ zu=fG<51nJ@xMY}eo=_SyxEq3j#>9CKiOp@AW|3_6*A5xpLidRn<^z^vcx_a$1P>Al zsst#4&mRn z!|bk8XoZp@MpZ4C#$3veSwwu35S=A3{KsVx4G8q;2kfqKlIwLI)j`n}RU@cg+B#^d z=cpndk{(;mEG|RQJl`dfJCYakt z1dkX__Dhzx5yr*T0MRqTtW*LySd)xr;Ki>(jtnEz2Lz4Py^ux_k8wyJ$mI z+6-_vRW(3NU) z@cL`8S8xnUp%0@N#wd^rpaO|Utf_Q>_RxGo_k6tuuybFxI6T=n2*h%ns^Bhh(_(!| z>ze8Me+Y)O<&q>4M$dBq+`ln0O2?7goUvjUf=B?cBb4H^`vvm1jBp%ESByN8!TCoi zMmFR#+~Wvrf05zw>sRiiELaOD*3|RY*5$(eHVP6UR|~t1K#PGK6o{OMAeyp1U&Qws z=PO?P!yKE!7c*Q2_G=VLVY@c~UXATJJUbDEZ6z#gKFMP4;$tGt;9!@Hc7&$ki{{<1wlY5dWZsa(^UNfuEGLhfQb44=zV>AKyGj$7B~Tf zfF&sm1<)MfpbdcQu!gtT2e59g#}Qq}Z*2lRVkL@5d!rmoC5x2At2V*q9E5-wjxtJ| zl1>eK9pT%}Usk=ihVb4S^uJs9H7!LN!u(yssNUY`(MND0)2<$P;%<9XN17;_*pn2D zrf;s#7{+(zLc`etM-9lswZt6Qu{kFlZpU4OckPxQGO=x3duwC$<|G-U=0fH76`ajU zE2=>;PC@g9Tpg(eLlCj$#~xJ2U~XYca((5WBRLY~&U$bbt4S8D-js61p?z9SKx7so zjf^m-x{-L}N&f&Wk&=ldBszo;#Zs|MbR`feOsK3S=l~9`g$>Xioj@iyYg_3M0TJ)p zgDBBe*b3tF-%n1W#M>H-73jZ^*5-b-^6%W%BH>N|lWA{I$9 ziVgrEuje}`J;Yu_vg5SIZIp9wJh)cMynD)6J%AwP20;%aeikIGr`-a@SRFEqG+{+{ zDFGE+suUAYy&^R!bG|J2_T9R2ZzOS+47%evU7PJJe{1BIw^i!Oa}6*~)qQC=pLu6m zNya5KD&3z{nIzGa!{fHKin_*&S<%x(!vzc?j@7rEx}c(<>=Zu9@d;N{!UA1^zxI(z zAW`leLK^i7ti=#9QX-%|CSR;HP%wepl*<5o{S`!j8}$(#cJ;7sB)qYaQqp8-QfVYy z#TjIj2Q4gY=t`24NTJk%0bmXQ195|~UKQe4X1Uii$;P95r(0S&o9pNzxwLugOgeU> zZ)JHD650#xFHW9FTw$iOgg79w$vbu*ip~tgnFfCY+)z(76|A6+F6ySM;)Yhzs;!46|L9*{1almJ7ddV|@ViHBaGBmm#t*umTau`9&- zt@EvD9CFP8o`sjO>83&Nn^;kij7qkFh_KFpD^jjxm51N$(HKf-Zr*; z-b%Hyc`?>uJ;diP;k>PptmhdX-fxW1Qx`~~Hu@&XijKCLOiCp;GTYkYTwZV89@rs) zDDtnhR8wB}j>^>nsB;v;Q-JsUuY^Ry>9O(&OF!P)$;6u(>hD=06Op$f2 zjSt1rA)^MpL_|L}a?4)V#taCRzh%I16d5&`IqBdbB9rw-{5O?KFa*ikLkFskO z)1$c4B$o2h0R&U(I{u?HmfCD_Tb9$~mTRIC)+?K9Hn+D@%>#F(SyE|{=4%f4p4+&& zd^U`RHJzJR5oB&w-tSf=!qq>0rO8WHMj?b-VO^Sn(Du6X1$O;qMCrfsRPqx{!c$jA z9pYOA!6u$YJed{aygeg0P>-29&)NO{!fa+sewh($J#nIP5g~>E7lZJaTxdH(NIicd z{Z`QpUdcOhKs{306=5empP{-JIm@2{b^kCGMUo=bRnip6ak4rv0h z+5{LqIY)^mxz4hklWEtJ$#)&9O4m1}ciPnPw6V#mYS+##W^5xix0ZNXc3dDZ`~Qw0!HE zRVC7CBKQvi3X2v1qf@9gj9ho+UJ1cFPAq2%E=yyd`%Re|*GC_iKTxR6#8PznN9lb>qN(XRe5#uCu zfZyjvQ{BqCFc5Sl^8_`r4}PE>SxJ@y< zB0=i-bQ-Fi<<0EzO%>&p+`ZJ1G;j-f)x_@7Tp3m-A&m0M>{)`4eqkJ*?k7UxF3#=r z+pQwN%5B?K)3rF|i-_+{{fwGDjkcMl4L0E1Npo)%m4%d6*3ri&bYl`nB0oHZ=i)EL z0|-xIsQxhD*lQpwgi*nE#u%Pn(7vN%@(X!e8!uh?a?rW$`A5-e#=T^McWGc|pr%ME zNSUy{D#)A5NVi(t@n*w}X0LXWcq<@IV&!oCg@Up68yE;??2Kb)&fAufnZ7Q1 z*>G9QnXI&`7dvaZ*Y|AH8;0W<5JXy-R}E|-ro@k)s&k5kBZ3I@`UsH}NMmo;TPW|; zeh~QuU08V(oI7N1H>^Oe1QRiYL`qJA3CGv{84M%bJN?6|7q{BIkV29M5ZWp!_Gnlh zOLtKbCN>5odFGLmnU|VF)L;$Qh4@3WZYPR+dy6Z8H4SQOj^%aDQW%8STGf)vs6qwk z5$Y4iV`Br|M5%E0_R&WikuZ55VR!yBsVQaKlhIZ-NsP?V)+Q~nUqrXP;F#d|B*pSp z^1(K&6FYn_2|uinwz~!ot!Y_>VHrGCSysv&R9X=nSmYl(xaX2^?toz>JMII$)fmw-IJq4PV6sJR8tjOO28eJe+Mr_w^dcT& zXDLLx*@|G_p@SQ1#G0kZyGx0ZMUEMeKXn#VJW|_aH+Qjgnnf&q;;h@}1aI1}VjZ98 zmwY)klVd%+m%6@}c4LoJ)WXj8dWMy&TM3{SMk%ed`SjQ(w2IuhF zFpeF(R?@kyB}(=}+&X8u*rc0T5|DxB)F&+4x@(FiBA}WHm<}P*Vx*aj1}OUUn5G{< z?jk=i0Iot!&~QfvNC2)AR7>&>g%uD?q1ZGaCOJq^9RQDE5C9RR99gJ9uttVH=>!qC z>Y?|ZBND>yjsm5QM<^aRsNejbct2RZyt=)MP#0GdY7)fDscKg7+rfUCjJk{# z@GZnq+cu)QhNU*86j(`2^A!;&Qj+vv6f9D8tz6eXgRe(Cxw1IVaB-sFo?(1Pv%!vF zCaqcP5uMvHWvLch$#x@AIlXn_~pjj*g#0bs3~>6hSZoGg(c6v<5er zp}>MYI?xn*=ql>hiFFxmrY$l95J_0~aIbkJQrm@<*dTKwd#jS$;AbT5u4|oxaDJVu z=|E{WEHxoMn80dR?AF><{kEdh>GtunL%DE@Z32 zBQV0ZMl@de4 z(Rgz;I4GDFoReTCU6#6ZROAE%IzS8sO)`|j+%zClm^bn$k9}1(c;kv{0TU7kB&Zll zQuQ05F%U1Vg*|*b-o1WZ>Xp8%(+>7g2YV{JGX;(_%<@PYLRD3XV9IfxT#bM=k=A=X zOBoW=Pi;Wi*w1Jpj%(Yyu4pW@{VL)MY~0A~$=)dMGThG*nF&4f5l0cRlWOGYlte^a z0Faszd7;)mSxf~1-*SfZIsp%|zRe>PDku=-=`a_#Z?8a72pd80=nv{UA77q=szh1z z$4CGG6;XEl5)mnW6N3FA)1mnQfOhmLL)1HmIL(Y-E37({IRFeGUXUq{n1~2`fCNB5 z0Do^<5en1Z1?N!9yo4RsB#6*w1nf5}j02TB=B=#wQ``}g@Pyn5$3sMDqCkW zFo|3$WCR@Tf*PoYO~=enMd~3I6M=vOxrHT4AU}6-(EX#j;+e5d3jh=Hl?@KJ`2-h?OR)7Zlpu%($JC+n5A;Ld?dz6H%y5W-ei1=# z+7SUTDwoCETOAk!^L>?6NijN}XTk*%DdvXt@QFxHp5f{y6LoApVe-&dN+^g(wD$-s*Z#ZKx_5@?Q8bCvQ>dZ93Q+8DDNJtT^3VW?2igNwVvWt9 z5CH(t>$rCPuk!mubzNeJ7tYv}qF^D!1V98pdVm94^wl~&@bUFayp+t03l;k;8 zB7mTQh$S%oFY-hL1PTEsIKakzGt++pcgA|-=@sv;p3(=IVR?jQORAg@hpP-LlaC;| z>*Q*WhKF8V$xuY1VKMx$&};=j(S*HQ0+0$p>N&^q00%%L*nYPRIKn(5Ll^|cNE9(Z zdVrf9boKtMJ9Pl)Gy|=6-DD(u0|sVU+;N*Is)aBg$ml2nrs?W2$OHJJm;=6wUqKB3 zcB>P6J}c{rKvOs!ChHxlVjiE$;whX!bRC64n_BIl0Ra#Y8kmI}k?1!+pT4kqX0axv zsk%eVw$a;{kr-uz^Twk%1R*(MK5jrb$W}h5;@2qj=2C5 zF#W0VWE>0G{{R&6Y|;ceE|GOTvXhSX`cyXBbQmNCGwKss!-J9f%$xvf)$zx~3hlkJ zG%bOXpcqIuyC=^Z5ply22xI^42jn1O})q9ZVd8MgZ6%xrH?Zz#A|XP}xVYhfh~W zpoW7$HM8;cmXl$uC9aum9k@$ndxVUTuPeKN;dzRNaTzVkfXqobIW@$7NgPSXTus@f z*009;)y}ovYqt>S*H?(IcMXDC+B?B@a3YQ63pA!nc_j=M-b7T8pbEW6fRse00V#?) z5D*X$AFx1c^i6Er4g3bz+&b((pMI6tE@jAnE=jr6IfrFb`zpX6XPl69Dj#x%Ki#hN z{VPtoG z=NP8h1U_jKt3jad2RLjE+@J%YprinAG4jR%5CZ~5+0{R&Yi1ECHUJ&X=mHuJ-GM;H zMnV1%&IeDN`M2cW=h58OJ{ zel$AY$ZPpfsk+zQ%ExlL&JF{$R5{1y00JYT@9ZgbUH#sHUoq-16huV80igNxfPB9- ze$qu%hoqX;ghWhoCO{9o=P^hEK7axsCLX{8U&WGD1DPcXVi>=vAFx0K1U^Cn0t2wv z4*hCA@!tgJ#}!N!9H@@DP@|L(P5=O8b?M{dpIZ4+l&DohvBB7mp!FX|T2hpyDP5#w z!}x^^c58H%O?jxC1jwoZ>DEn$eRk>r18e8$U1$`-0$?bJ0Bl49dJXGiuRz~zk81qT z5;|0pM;ypwkrG5C608FNM?y2Yup?qHK^q;a;YUxfdLG8SYDuW7g*gyNNJIqX5D`^B zgnYGnhpS=$JJ)@N>x(RkWKnq6GKv{aw3bO1r9bky`+-a6^_?>&B=`eeJv|^IUrM5g zq0=!=LkUb%0g55=5bgu=-BqNKjhQo3%PH)y+W`~yf)IR{WK7=yR`~i;IETV200(MISLRMyK-}a8HQVw?i(1cGnPn|5_`nN zX1P0+LWx!vDUO581d|Xp$Jb+^H(~4}s_Nb<%;_YXbrd<<01y;WKQGKgb|6pz5gnAq z5%nDx;rVX6c__oI3Ymp;S#Z6ikVUgh)UV0f-$X5DtQy;nsjO6~Jo10X3bF z6M9qx0I2jRJw_eq%9H@3&`{c)AYtq2=`iRx!=&k@Bmw%+1bKSCy6_BZXe< zNaG;xHgmBcU=jrg;bWM~s)EWjav++;C>Tm002?x4paPtLASDlwh>y;@Ch*D#9F5<% zD;GdjM9QcMJMsWcqL~v2AE&;=H=z*T{cGT<=44S(M-CA|x&;#vxr|oi4uBCbl`@Y` zwd!+plmIop!&vbvBX{KHQ)t-tP+Ee~>d`35Cm4hCmD@v|HGHEwD$Pz*^iSnJB3)Npopjutjci_5itHFf&yV5nS(>$xa)fw#VZo@$k_KK+Sm^;OvT<$ z?`Su-MYVr0WLRfqP7IEfe+@YhL#W)#gLcMp)$3EH3Y6qYLst2}cg@htZ9LRiH-4oF#JE{Ne-m6r~P z+{(&S6*#itEq=p@V3KP{Z!E4fi|egBSJSl=g>UrjN4d4QYfHAZp6bR)S_$E~S#0j^ zt!9R3<$`$>o?aqgKM{bPU_b#k*iiWh_8*?B=lT1O%zoPX0n9?EK<(Gk1|9d&L`PqE z2#A{FQ||AfIiU?01uebpv)8&CjbnS(*w+twg-)V zNJAXJLKIA64vJES#7FD^`PE9*`*@X1%!mtxOkxpr2pSPo!Uh5mLwhQF0uOx&z%{D= z`vD=Ei?;*R^x91VlYJ;0;oSS*#AL%}0Symr2YN)p`(hyNMb44@(Gm(^Q8*Ze-&l!& zzyq)W01sbXht8^ky?lPpkJt2L>adzfrHP(Xn_%3#F#(+X*7r!}2u9$X9$~dr2){+a zj(~xYTnn&8Py(nW67>PPcm9MxdvCD%)d4JGnn~%2u90wkYtvvlAMJqGYaW`$mT;JbaU234lyW||5&r-fFhZc%<`F7n zR~A};V<*$``Cy;I1oRS@)O`l)Ti~^+aSL}YmVF;2RMl#tN{A*UTd2sWbi@R}Qt!7& z{#U>uuH)+M6ttRDM80J9OK$5aCN_#Z@|VcZf#n2XV;wQ@OSB&DK04I|i15I8k6Byt z4XF{$HTA%Zuz`EkidiIA zqQ$wDPugS*xFQ8q;AF^Sh<52Ihe840TL2O4B0BBXEbZ|TeKO?jQeeRc1YK6;Niw3L z(a`_{%j*#X9H0PE(22L|15twN=`eYuT(AhL;xg}*Dui;DD?>w+gdatajQcTs@mY$Z&k6BMTI0z2Tdk2Fof#!~ZoWQ!o_33*s${kdspDY-B{ zdf14!A>5SaAMTtn$JVW^1HthGaq`W8Or_kz}4?zWB(;r#!XOY^1h^JN?LBbdCQ-w^-;i-`DRiK8%I4N~&z zTU+(FyPrtXCyL@LRGCB65ouhrHDlUVA#LljE!F0m$rsL7 zLg16N7K?i+BOne;G7>~xB78!Vji^=DSwaecnUvqzPue*?5!vJ6n&Qi0XXm+_uG%38 zC1m8~PbLYqkVT{CDvHcZB}KZ8TM@eDD}$(X#UGE%xUcyWkgT~!kZG92EgPtsM@X*9VJgiEsTNT%F^-58Qx3WWLaM9k^tZ9S{{Vfc`ybnJQ&)r>($;23 zwU>H=5l^ld^PQ}aMGEd%H!)1-+5N65Hs)q43zX8)J{*^OeUys#Ol`%FT_L`TcejDB zAFH(TtaSVb!o%JmyE@OYT_uI4)x)Q687o(^D29BPiK2`rlW#e zVw)uavg;<2EyU`iXA3HtNtq)gnGT?Ij5gpa)LG`dDQ`ri0>z!>812F{9WRIu+`2zm zRYb+|3f(k3vl%0%Vu*E=!J!Z~XLyaeT6A!mC%~d|OjW%bxR+7esTCX*GeoWJfDRW` z6ABFsWZERi$u}?xD+nCoq0b)J93z#@_}OU06-_2rgi>DAa|fL5MGmO>rY~1m80H~_ zq8}{)>tGcu5M5ckHn(>I?nq^f8-X7qTq$IcbIx3p?%h+~{s<2sEK66fctTwVTI`lx zZ%fgn(yb@q?jpK_O7Gh0-p1zMEmp~8Vl6cI%(G0lGX#R%D#;{^3azq5EAH;iIeTi^ zwQWmw_qDEw`{E8UwXD)Hk|&8^qzswlZ)?H83pVJ*GPhl}m~9{Iq#!yXNqGfSsT}5u z4;1w-d7dub&S9m}kF+B$NEj3?D3kdlc_5|8iB7YYkt8z&!K%rq&4YOb2;_`gHB}VB zHPQi+tX*`(;M{YLB?8@6@Rpi`o0FNkn8vq$`p!;8k`kaESL#11 zEtGTS3W|#7P^$*NWp8u(Lh;hsZf!}q&ZQz+iS8OHC57%91m!W|ZSCS&Lifgb%;G4L zbTRWSD^=2k_W?t5s!M09%dGHf4jYc=R+iUKit)6o+bupFURIhr#}_x+jm(xKlELk* z62eK%#+NL&I=-}avn9-u#W|5bNH}Vsk4l|7Q6M=s9mt>%5yvC(}@m&4|lU{)pZWKiI7AHkbWpS3Kgyc7N?PTL`7ti zGKMe4vHY@V1PTS}03B$c08r`l&}+~uYP(Ya&nFp)7)IL-PVRcywxpX##w4;y&5~j< zl1{VwJ%Q7>$oub}FIJ-F;Wpqg)EZ`c7?uzIZT{5D{BXkuPihvNS9Z&&O07+E_ zT;iOh1B+SX8+L5Kkqa9(m>{YpNpc*5-M}h;Fo#9TCNP48>LBQPM`o-#w^-k+Udmf= zK69qCQUGSHoSXSoh!JmQ0xnSxExK(`C=lxilz^Ffj3e;~-P;>&PfcdA)u#;7M28bpv^LmW-Yv3osV_^wA?17{8?We%Kl9CWho41R@S##p;hZ|(#c(o&w0vhgi;_!BHOUWPeXb8Jj z#7qnzL|L@*5JWa1&_OT(K>7?HyD`Qy#j&{dYB&HcnM;9!5)PcGo3DAJ?PO~>bz2mM z0>w(P7j2P6V+WWnkukjAC1Vy=;RK%Ojs)URf=G=JNhoH(0NOPqQz}WcY*K&#AdyG~ zL;yP{(gU#puY^DJ^zp6DhslexJ{{rsZfrDeH0_hU;ui{GI+4&c9d7d0*5OMtOAqNb zTl56-3GCw8S|F?S)BcK{1-%`&akjC=`mMI9tng1}T4tG{S)|7DJrdhqz0=#8+UYqV zwvlw}VQkjz8aqdH(n8X#w=BJ-Vs2@?vrG<7v*Ijf%cp3&j*oF5_tlN#yGR8kYDdzgM&TE!*4aI-G8g5k6zE{09msRsH;&ST)Dr&on6 zTS+Bfo!O9#cG(9fK_;#q^rnH;AeiN>t{nXV6^PKvZ*9ktF)zW&OG2SBYpkdukskYC z`)ZQm8vLSzHH3{CF0y|;}p6_v6{ z1+JsnMsV0*sj4!?iL+S1v68aw=&O1%;bR{(2u4RWjupuHnob)X%56we zio|ZQ3851K17sld)n{HP?QdPtIFqz4Ce^rihQ|o$6W=U$yg0V@7Nbfwwzl?{7Umr? zC@j^D)Dy_v++mo%G^M68G2iqXY3+2oSnh5O+{FvM!FgowdD)#9JjBRHcFH~Mbm%J9 zWLxguvEJJzyqy{*(wlVZHcH|$23f2lk|FI()sPg^Ra9f$f@?KZREQ=b#zX+33K&SN zSMd-r&xft{WLW9@ZSx$Nic<+d>7^SgvC3cp_=+6>Zjk{Fu_*lMU#)NYANw@Y`&0Q3 z@E)_TUTRjiS}zlEw+vdeZ41Y9r)k>cmv)jUx`I-o1E|Yn78mY<+MCE^MxK9W^4lwdT`xYZ%@(dogqj(6qtsq#fal zx-0D=SX{Po-b05`1%f9=;j7QG?` z5Df?j7<+d7pH9KpHaj1_=N3+W-*X*}ne(ZGPlq zlTm17jB}I>@XPfkV(ff|%ZPW-{5v^zQ4NTCcdT3A87AdvK57zjM#3w0Jj89#E=Ks= zcvkao!ln%)zJlEt$u+LzfU-T_t!{}Je0!oto0X&h-~vG3Zc=SZWQrZcbW(`u1WH{1 z7MYdh!xt3KWTyOSFz;gu(y$ zaZ*t;Xiu)PoyiWMhzRHapeE@LT>yHGVVd9x6-$5}lqlG2NZ&XaBW}KbO>{eb6tptk z!)H8_TiVDNNBk4r6-Dmy7_TodEIF{;fwRuF)B-7xt#k!3*E@oKPhr^B{_;=5$qx%+^^w? zLg=h96y|Pak+P(G)VYxX$na4YQMNY8-nXt8&|{xazlz{P95KZQcnDHmr_%K46!;M3 z?q9r9mJAN+b5xtC!iufVCG02&3ScEE6H}=$4uX&Xpd-{fH~JEQ2j9VwXjI!Aq$roE zX!dB72c)7ayFs~x`q4x>3}F!s7<&i^1zZO$N$n|_ZIv|AG5!$^Xy-16qyxBsl-<71 zQ19ENoN548U_t?Uq~Z=T;W?H@yzW zed?_DaUPVZ9RC1{Si)fvhJ&bn5D?f1kCtNg5bPov5D@KD+mgfJ)sd6$l&Z z4=@NuLSg`RDMU}!8rb@jP1tITH)$)CX+8CV;ea?HirdIn1Y>gCxaxNG+aaiER~l4t zT&1WM*BY*k46`Xy-9~|OwjFw>Krs)l@%~-q8cFR zp`wn&p`wnpupMh(DmLL*5(Z}>h&?MTZszG8%^VZcU?cf@?c8)9Dy}9R30o*b2mwrq ziXt1>Y)B)a`3As4<{q1?2Xjh_j@mS80^xlu1t9>(In_DSMHI+TABg5Mfv;VNfj~Re zP9L?F^5AUC$Rx=tk&f+;ymsaC$pmgU@T_lZI`*5wnk1%KF%esN8J)s1I^M?emK|`h z26iNX0+L4gt_znhrX8mZ5Y_CQo8^*h*`qX9UCOH*;sBayCQ}_z5FgZl=z-s`4zm)_ z;i@*(vZei<5|nEmiby;qu^w`=DO-uvAQD>PSPIOJ#HgrZ!^W(nnaBWg7=S&pdyW`# z$G{kUZ0(Vbs@MFhv}2&+#gjLNQRC!}x^awsxDW%NF^MknL3p4{!j z+p-qq%5CB@havCFg2%!zfcce^0D|BbhCyh->d3i{vmsrd*jhFf1j9FYJY)5CK0ss` zGDd1mijd{obm4WZ-Zqz{2DY}hki~a=5>oTZgATTVRhN`(49Y+Z!GTkp{Ce$gx4m0i zyuBI}@`BJVoI)ZDX~%8ppTH9m{GyoCZUjY>1M(%RY^ot0u)b{DP%7b+nzoeShy=7*>;-< zmQnETu8T@O#b)i4X%ZOc(hsjAM-}tsTc8N3AaFX$BB-d@a%c@$9G5fLV^p5oymzwg z>=y{Ao+b39rsc=i*~Ca?5(m?H9kZ7C7D!){sL$e?O~u+kD=1brw0Q(;5boUM`bBce zx?Q`8WtUY&U#l3A-KgMHD#cxQ=(R>g!BR4MK}T{gdH_I7QyeRx!P(xFHW>OMo#CIl2O$3reQ?Q#`SHfztD#@&zbJo_2**9yVPbD!TV1H>z%1xXmVy>A^ z7FKha>}Bp@#k{=2gpF8Mk8g1|yR0*{x?xcx)f9f<>}Ojvk!dg`S#*f2)Ye%~DXISe z5+pbbRV9_~)zoDw#PPoMK~AQNIf9LSCM6I8ln{31sh=}cOa~II)nrVfoAQLBJE;i9 z9LCHOmb(ipG23U(IH;gzEv*d47b%qDQ2{WwNYHWmruby_$F=To~Cqus2rUl#FM6x6QKax~fWwW)rHq6C#@Bl%cyQqit7b}NJ{IN($s`eIX{qZ5d2=%?VS&f9EZC1E6;ae` zj@%hE*tA_|ps1=-rjjkXjFe5z+joX7yvu1`_WYH*amBTKo3;`O9RvAhQMjhz5!jW( zX9Vdw3!rrpSu+&roaHe@W*9j8DQm15&xCL8Sn11MgoWLE@s{F#>UQC2ZA6tv6H|DW zVN@Eq$`&kANdczd9kVV-v{-;RxT2M8h|8Mz&0IJe#NQG#jYif^3z1gw3UQjZ;?3qq zmCI8dcjRvz(SK;S6qWX4&ynMVluR88>77R?reV-EHr6;=NaNN-+O~x+}kAAGnj4etlCIrc^+F;g8mD+CAE>mG|GY* zIpUOuMQn)}f~^X$l7OKQ_&~r^K;NnX*cap@^AQ0NA6@$Wp~Z+XWUi#!CDu}*3`Er( zbd-Im>y^XI5YbF?iAtb!=r&^kgR6S$ZX0gq#j68!u5jh1!&H$3h zr~)Kavy{wL&{%>gs)DJgQ87)is9+i@)^<(s2ox406iAUoG#x0WZu<>~`T2kcVW8j7 zxZOQA%&k-Ikhl8iJnWwV0)h!zK zXyXswTDG4qp&ulJl!#=K$`TcUJELS20;(y5mO(QSx+`?U|_*lsCh3wT01yL+k~swn(oqe83R4eAedF9m zy<~0f%39urd=F>H$x)yB)uQjVaxxCxGCV6x)wCF9;tm;^VQC`$FEzW#5<3M8pli1h zOOjnN-mc4zRW5ph1$5Hvhucv^I=V%J;5SHs7^gRq043IgW&>zM1A6;CD}v>jdJ-uF z5;KOzCi?ym1058MPhUX=M@9UgHo!C^Rq@%F@0+L~DyVjg6JydP02L7ufQGvm+BeU* z6hAoe-!V-=0rJ2Kie?bmK%!Fu+bHya2XBC)Z_S|jR3Owa_VELejodIJ1h`y`X8>{# za&v_zIjCwJAk+SqyNO&2nbi_0BV)-D+gOZ-&I1)$0p$cJErvXsP>qQ7vM06iFMeb9;2cDow0|_>M1~=pn(9Q1_KlWpr#QW?_I<@_8sfz zUE_H1CA`TXI22QA(IcoL8rT$oU=0TLV*$DY^M`$Ixddj5QZ`8DIfMlw3CBaRC&UHV z7tp0BfQGl`A;!$anl>)A04`DFmUfGS}WV6PcDt7&oqir ze_HnPByh0hGING$93OZ$DuNU#YM|GTAs#XV3H$lx9rXGNNdTC8cM&M}`$XgG-oFH8 zqL{@f34GQ1M0$2QSmhDhWdduhtxD3UPz9FLw$fq0qfXx@*Qvp z*nr$b1jF&4t9l=dR1r42eWD@*uHmhXSN7szLK~{8l*q^?M*+#keePqAfdgY$H{p1p zyShe=Okzn{U04Il6}FojWd8sQDy#>PAa9JDa^bGX zkN}8PBn2vx?np$y1*!<7uKNKF9@3zIfrJa#4qoN;-hg_yyQ~d_Ran~C3xz|}JwU<& z02~8su&?g08 zKmk1ok`)7C*Ox1Uk-703@y;#KOmCw~gsL{E{J=sCj)`fg+%6rCG2Wn%u=lXI3d830 z37{Y+ImcoEQ7CK#paN2u1ORuT?os^X_jdV_5Kvr+yX|8Xy?}laCPek$)3|r}Y&YmN zQZ{HONW~tV3CulzFa=CP6f__|k-GjH;>#pCM(z<03{#Z~1KO}|i+tkNUL-xc9ZT|q?fPIx%9X_Kh zQ32T&GGW{`+oTJx-PyJ2_6KmTnMUR_)0n~lQly7(nCui1kIXlr0Ud{7-|b&pP8C>_ zmhRZ~!NY}2^#1@G0wN+i&;b3uzh{3+saI@b97oi>^|22@5diJ`pW69X zS}BKf2xtIw1KaEmyMDW@gck&0f(`}<1bGemed4s;M@vDKz+6656=TW{0mr?#JfrUM z#ZXkGE6~;Qj+CV-O7yhghw~3`*Y+v#nkf2_#%;mgM2ekM4$%ZpB@CE)E!0u z#CCZ^K)#{?I{_cG2kfk^O(8gJKhXhwKs`!heE$INf4|zbrw5&e4tbkzq}S0s8GzAr zqmV$;YyscL*Nh3JZbS^z5OmQet<_FBbX>hbR_cJ14=(OvSd(UCb~ou2c;7jdJ-YWXVR=K z^-UL5w~iQwv1R`N#4R5?YaE_09|(&t?givNurK8M&d`d2`{nF+B!)oa1gVhyVzP=mWTj*1f#k$VbSTf_ZR|QS4Q^@GUD@uqu!;ZrU{@ z4KC$BAOxze>RCr1WmQzh1bv+)6C&vJl5ca>;;uKu7xms(2{LmRZol_irNl)5m2{u7 zMt~TgU@^||bU`A34_UMt5Z!A|tmLK7csF?-)Q(&%=gWzYaEafyY(o@4ruJnFxGCkF zPW@pwnpGT%u2(96WdPk{vmG&v_qxL>s@le2iP&S`C1sNgP85K#g5V!@xp9teZw7q0 zc-ke>xL>o2SzWI6o4B>R*ka6vOK7E%$4`z(QNLP-;jX4wW$w#eL1{F6<^ob#JUp!C zja=O`WsP>4urU#q>EAgy6>Ku^%&d*VlQW`kD60|4TQYK)%A%x2gK_h;xsoKMe6{lX zK2>9Q;f&d0d_8AcZQBYj%Nmr7^6C&s;q>H*3gz>c1wZ3RZnJ_ZAgGC&Hbn-VfgJ_% ztrv;)1=O|6>!{h9F88~HwlZUg2-UXR4a?33_~tvDl6_Curw7Tv{h9E#hj57<=&)P; zLL>w%SDK0Tr?))O#_slsBzA8ks3no0%Ym}3MAlh~DHS&jox1=4*%fe@q)`vn$|(qw zUm*bjt~>b_uM+?wE0s`GP71Dcj$lYjuP6*cfy4@6DT~xShjndlYx32{aNhp_yXD(M z#RHNx7j8@iOsgF=R?*BlDN0mOSyLFo9|~pw*~FzZN%9-SGEU)Q;@851DQu#mhC%(> z;E1IvvMHFw62p0GDh!iUN<$Udi|s~Cc9=CctxXe$HC=te*;|nZFj+5U_idxcQqmEE zKm_4=i1Eh8tvgQbd$Z2TtmeJqZC9IC?wV^J8?cy9tm-Yw3M@88L`Wfg?QwSSTW&dB zm~xqNymJOG#W7`be%+Ba>W=*5B$LN!BJt7)fCvHqF^S#rVtUXqQ%VE z&n_antbKLC+y!Pr8PjGCdZZdAppTYkjTiFXq*IRi4yq*~^gSXv9YU5L;!bbmYUSC3|{1WaQX>c>Z{p;T3|z~U%5aAa5*1VOn}C=R-O=Z&PeRhO)3 z3~_hOIXj4U)1dL#rrAZ5Zy>8#7{{b&MBBNJdYUCMkWn*$BDj>|W00qwJX;^kEtyOA7%CuuM} z#aRz2BmfS^y^;H+(3aanyO&k5f(|6^28i>{AYDoBZ4K-ZT6e@5C6?J*SmG=sWl|J7 zj#|65`XCfeP&kQ5CIB&jHXvR15DgB*1MaWs3D%)g6O@2sl!9{)!cY?dM8n)W2KVb$ zYm!-gjuFKdMdX8YmXv6bSX;@t9<^M~J~%UB@DRz68z#BI%Y?g_TBNWE#C54HZKS-p zg4Pk4ZY4-!7&tE@1YTl3YJzgic2xzAz|~EAUDLR0NYypnUQ=zQ=-PeOrKntB9_rT4 z7oKKR$TB}75RoA=NabUVS=a-{$=ry<7=3o^Z`;j;Op}i&>BJ;epUU|QenXWb*^y@m zHZXiZ;Z(|)mts*ihgHRikgUv?2%W=YToLyiLDoBAcOI`;B;_zDsM*3s0<7I~0mx${ zu?T*Xl)wT}0jOQT7((C5kTmd4BvVadlcno;uWB*6 zNDdH1(Fo&5I$>M(rNR15o|mXe1^wjuj*yn#-8XiNrnSu24{HX?BS@Lc4r9xLIY}Uo zCU9rUBagU?jrcCpP~iO@&xCtPlU9Bi(`|09r{hgOMbnhMzY%Ky^Vp3#^sK4`al;}c za!8Ug#}i#kqM{^8B)|j*LaLhXV+p{gOaosclcYeuBbdYM=~1?9!PIHhk#H!xYC!~w zCMQy<7@cT=iei|?Fpp77(mi5O4fX=-^hm-va_iX$p_D{Q0(BK9lH9}&l*o{IW(5@? zOVT1c0(SKg*mQCt)+MZ(vMQ?GHc64grPVPGiBl;>L#`vDXoO5e#yIalQ4!DweF0UA z1zxR%QIFvg0QltoO?u`@(UF(D5SXznkIaCqYl6k{1`w}OSO5-kJU+;%)kGc;%+OEC zZPb$G6^x*)3J`bmFCa#k0)^2bj#1a@v2QK@R#W!#e1QUg^3$-l8O#Ojh=G_%}EAZ{1o!%zf2)FvXq5N=F*JkAf9VYrJ3D z9)-d3S=dh<_O--Xm~*4>u7z&5`u3Bv?{6fxvW0n!w+KKDpJ`pz z@4l9{6S!gmeKeC%%m_&|31XnJ0c3?{0BAlFwRTVk#_ z+j&Cm1SGEMTSDA&#uQg8LrhP}#Li{SipZ$Zhl$m|kSRskz#*%WljkhJ${@MX5ZTNiVd*dcY(VATNPvdG zM8G-$5vy;;yyTv03$gK{P->O4bjVuL4x_|P6EK=Y_So4bg))mMis~>~sJ=l{oDz0r zh?&kqXtpCga;p*87H!zUjr|Dz^;!~Lj2uiGqRhKaX;w?3$Q}f6u1NIAzJH&@(M8NTf#@BMXNHpm@;b=1teP#&K5Fc zO)xl@sKzLbZ8~=i-d$*y*Nq+$X(Kw#>ilfo9t=)SgY~Lb zSo0)2uAh{&ZFneq8Dti@@}0)Q#Ze@~3XO>o2`3NH)!~9Rjd~2z3 zE~~;kC34oXT%H@@&L`tX8a9)qY1%}kHCwOHz_$?G>X$m)cTrv0rIw!z@afhNUFsI| zTlaC>3>x1dXZ+l+CvS+AAngdKSI~H-IoV8$w{h=^t7A#1+}k)eGgX&du1p0hw+>Dy zbs&%!vX5=V#XV|QM`EFlK`~5c3JKFtz$3Geo6wL4wufP`*0vq3vScDeB59C>OoalG zG871zN>BoUN>bF>Ut)VBoR*?J5#oeAs7>;*x zZ~+3k_X}`e?l(bwGCf*tM^@G~nYB%KS-N$!n^)HLC5&C%ED^AdIHQ6H?d){;+D~P% zw~7%XlzCs1bGAjSx~aEJsU&1lIFP-H2OgjvkPQF;fB@(NTdID(%eh&>fa|Drj#3nW zV`xq#E`R`iH?Lj&{{Wi4HHu;j91wrxE1=t}M+|YZa~RY{Sb{QDSI?;mRG&gK*Ck(e z?pJE3n%zK5{UTnWArIJnb=Fg8N6?1El$q)bj!$|LcpZ^=xd>SKKLA7E@m zL^Kp$qvAgLsNq>yHaSQkxqvImdgL95BV%2wrCdJtBo|zEa~Q&+h5#r5)D(y(0O>A+ zL!l7Z2yE0*EUDH| z!etI&F^#_aAG2P79)JPZ1F%=fL`S%e$L$)Cn;?(3J#c#C)~myA(aj|0MsD?RP^eIw zf&e2K3I`|zXQuR}DNY@idJAyv@-DcC#0GMX3dtYjU%_qB ze4z{}q*QTrvC;|~MgS-$(j7nnqKJU#HCOUQibrD5s!F8w!vsNAj#=xdQvnpp2`*9V zDu4hw1AqvLP64p)Hh+e}7a_wAB{WVoNAC&73<`>!KL`-&V%t!L0*LGkA_6<@_Kv^< zq;i@9GD*=LL&#eVAX81sPh;d45l`A$#t_DElYlsRXEMkJ%5g7AJD3A{5cO7@Fpo{L zaIS(oOK@W^77BMUlOP<;E1Z+=DwBXP2_z4Ld}F1x_Zjg_3{v3TYr4>e?l|vc_- zKF>SH7_*Fqhy<2*RuW<`PC~UeXS7O9k<%4U3!tG)cME`lyu`o_)F5FHHo!o;9dAR} zE1NvU8H7s^q^ZT4hAWkb*rq5sFc=I_>L8RAPz0I+h#RB?;6A$#qg3Y1zp%P(9?Yqo zUZG}m&*vqv@|5!t_)W417yt|*-_zt3Lnx=L)AAXvMBFE(h~Y#*R0^M$)%eiX%3Yh| z66oH8*gA%%X}hTwWq82ImL&`rFDX(OF$9pOsKQ2_W`?SD_VCCr-mg0twSl1bTPU0wbX6*!}vdUm{1$$vZ5=ca2=7 z97KqtbcG-=5T*kiKuCT8>Rd!LJJ<*Tx8AO$n>>W0W=1=ON}05q#SEEK=v^%o(^l#YNo8r*-wL<&bQe?h$^OI$OJLk^G~mLX$wEh=Rkg>psI(Esf;X%OlMUMjMF40cE=| zNfTy5(nOrUIOPC!$0!B2Cu`0m(R9sbODkJT`>1bp$)4$_)3j;t?5^a@0@}v*>%Cat z-S&XVBtk6n#%58PB&A9;yMwP@)U=ONQkBLj6%QSqFB zikeX75fIo2?yg21h2f5DWGvioJ9J%4?huZ)&o1Fb+_j2uFBM43B2-M0(M?xDGBgK( zsw57wh@6BeYVfzkhI?zTa1s{5RR?OcZfGXuXvxy;3gn9@s%{bz3a;7ci;7MTayTky zOb4iH*x`$&e!{z!zcMA*$~6hun3z~t^q;0;y@@P=(L2btEEN>cheZXp-BgnzM%a$` z)D=`;iR~wr&gKB0Kw!UXyPY=SC5GDS{%K65VJNn0mXXCI%3|*xc1$UNcVw1XOm>m* z>*<>AnFkPQdQO$2@m`pgnx3bn=oWUVXK1&!_cCjjH+t30+!0JJBC(Fj-zC!S;wehR zOfXzRw~T^H+bys?se37JDR$ZoFQPk6*-kx9rJW}L+@^5qH5Tce!zDMk-5{cp@5995{rT$~L4_lM)zGS=3XB5+!TdjgekL@HNW)%W?~66G}IN7adQU8m#k|VR0{6acFR1jA?3PshYdeIMgo@EwXCL2!CZ#B>=gv}4TlLj>6FwQ z>!pU#C9s2nl{ZeKJiuny6@?TEl7fkZfU#2`n?)$%kBMCFF3Nmk$Tv-<=I;k>X6;6^ zQZC?;c^aYH%Qa-(suSS+hB}T81q6{%qGn8lF3F=5D?an|?e%_I7Zv4pv5bP8wlWNT zzjMVhA(vT0ouD~jX$0K3kVW7EDGF+)byjXg1gR#G5=g}uoaAmtO4q=5Rikvo#>-kM z-mp`!Zc4!hWn@z>>Y!jUBC|jc@(xtMQ#MN0+3zhP)Z|4?Mi^tY z)Y{HvYk4G&2+K~{207AYluV4R5fQo`cT^ej9*?bB=^dbH94iCe-e@v$C9c21mb%8C z%c@(W>hB((YibOSai?BdNpCHc;G9U3&lHOGa2X_!Kr5fA$uevS8S0Wr5a|I00+59f zR7^ovtE0?Vy+Q^tgx!Fp0RSikZok9MOIwWbhCj5gD8tCNgSH}-jS>~OI3rPqXaWq8 zIRvXXA_<5JVs5nwt?a?n8g1l!e2H#(8B0;3!*9quUF2eAH?#t6)l^n)Ksh!l5EC&# z59(rvR>XUb&i3`mjquI4jji{w%1>O#<2z=0ar0M1>WY_n4ui(=T_A5L1qP-m9|nZr zV~GR=KtL!x)zia$mtY~)J z8N}Q%tlOkfUg}Zm@oNBHB(dElmeFa(#Up7Xk!H7f6d2VILgm^qv6Xza&g*3HtZgej zw39ct6fxVN_CYqvj8m1&4C4jUWe`+AqK8`MC?+DBW=OzM>L`RVWi?zv-?t=037#b% z5i06Diwl($UE_v|ox7)su2D=B_LoFiRKTSv2${-4lmG{G<&%=1-B}Ht*x`vxi+h2z zy2&VCG*lyZDXK<@pgSQG1XChOrXnRNK%fF$2C|=#$ytohZw#{v2s>O68ODJJ2 z0!?;p-sb5HhJH(5oylm3zkEAm$X}K{xhFdyvQf=)OH?N$ovy0JYZ%RwMN>sB^>l)4 z%_5>jHiT3G=ql8n@jsjl+ zf6{64R@VMi-zAQhSKn63DC zRC_Cn;Tc(yE4^?|lD(z3doy`gHRFsZjiU1*&OP(5DcnvQm z6%`RM1@gi96e=;rQO z%v;wq!eJtU@zFxytsS#^^UGx942Xf1B83B6j!xkTE=pOr;PySuYR9i?-NwG7UEDEF zXYKixvQ{PCX{3qMj(E{vCzW;$RL}4*@C63P0JsfIFfhOx)&YnuHX0ftCAkB&`oc>3<9_+`k zonp_1(~Wyz);lfjHXTy;PruV%$)jyQR)>lru(Fow`t}P5IBGi`DUA2C&wX_ukjXm5 z3s_uRP5Nfnc!P=Kl6mxf3fo`MrGnn-*6u5S@y}^3ftj8G1Iljh;XLLyma|XgU z6aN639%++mwjp@vsU1TGr_xMs1oMw@3m0Ra^Ks#$9p$HdtsiG!8}FMD{X+iEJh@R1R+ z>nkKaz~yIg&SM&&@Z?=*jF)UsJA{=WU8tFOx#;Fo5Ry!0A|#un?mAL2(l4XmwOGAK zxn}LL)j`8`OYtVMN*ObhKuTc_^#)n*!=Elg!m*Ua%Ew=G@26g)DAql+TpPI9$xHh` zUr%LD;^2IE$ER@{mRVUw^O(sxZRIa6*#_zrqO4@n+q`D5UI=4xW#)FxqaSbC_Jb>O z!nam&At7xj#?6Lg=E`w8;z7%Mu2CC}2_z$?7`0&CSix#%2&$qkUa81<+pt~*)~xtK zUc`Grx$S3+xbusyczVl)^J<(;f2d79pJ`-}Xi=fo+Ur-pyt%x#y1kAoGi7fo%{PDS za%x#P`0nRGvexx3II@FNQ0_S+ zUhpgD*d|ri2hHX+QIT* z?4PlD-W#23hBO0n#dlB`t}W-|4SMc1C9*Ox7#KJ!l1>z0 zWQEOkY@3x&D4HLIxlQY?;&TVD+t`1-T(nUVkWvv72r6MH>!-I@NC5Zs4G*WTx4qXT znkEw>V(7!=qCo&3ums09eFsl|!?66-%PB+!MK`e(OhEe$peXBN00HUhA|D|28r7z_ zIlw0v2PE|*ZLIOW7^-;D%pochy`g*h*A5xgx-)~Kaudjaf@MKbpmmnK2N=XO^ zXm(&HSdV`~h>pNRzV;gJRhwo((tkk_&%xS>JtHg$ccmmy~C(Lq1;2} z1M67DybU9cRwoH#NNW4#r)Pg|+N6#zc8; z?6XJjH@$(%*dZ`~q;4Ka9KC?xLw6sv0DUw+A??4OziX;^fr~Q8y&`cWbCr5ZJJ=m| z>4q4#VyECh5v6l{8TwB!ScUASVzHQ4XVM zOR*0AzkaHrLDG&4(5fb2Kb)zKZjl0L5nEaj*2Fiyz&gHphKH6`R5ND0nTiF<29vuk>5e?3|^9y2m{s9VG#fg z*L1UAIkQ&XNt8uZ)awF>h!g<9unhp5!PFuJ9S7gutgf#fL1+k2CAJFfjgfie#s_HL)`rJy=}Zd*1xlQd?-P-OtT{BVj)*F%nTkLHWYJDs_sY zWuz5s03`(4wjqtKpbSHKA5jtWj8c!MV*q|gRfv_7AOrflDC8JCq<3TABO8KLZ`9*_Z(A&y zWOpP;Btm84JIgE;5}`+HrnQNHVuULBuQ1BnHZoC z1Z26&pu=NhTIhwtxI{{RcI3VF+r@M*t6(A!qGl`}dm zo0;0Bjbh*zkXTzc6FWIuwjc;7)g_f8%Oqeg!Xg;;cFU-mYXJ+?B`HKqQP*OC_t*}! zJ+-|6{OdjVA#X5uV%`%jE}O#Kx$Z|OLfb8E7?4P}0IeXvlC2~zXR(VQ%#9*kuB!2j z{iVXC7OoamlU0*&ZN3|J)3gmn^fE%yz#&OWlF>ECDl_3Se^(zn=WKH1mFr(OzF6I% zJi2A44_V7Q-0Ju7+OonzmbHjH*CAh>c|^*KZtA1oNzNHa<{1f>Rkd#Ww(QH-VnG$g zY!d24H0}7->p{v~QhwH3sYar zYy&-TL}SbcX&9FEuWdGMkn#hQuAiGZcwKRfm$p`L+^U_iMU8}bc?421Oo|UK2@{bd z4&};Z#~U|=`0mz82h-_{n#3Rqi8xfs_3T8(Db8OhG7vS=R8makDMUcWPz};vnZY-j zUWvoj4?2gsy0?yGjbr_6R`T;r405>ycg&2BFbscK&Ko2e`PDB4>w2~1vRbK2BP5;F z(#w=?=!jlOkdQ=d@skk3j_5812&j~Ywl1s5Q#E4Ack7@g1qfD4D1&rV5$p2Q11e(} zG+`;+C_((A3B*HHm3YI2`F{TPR^^FaF`J?$M-ozw%NoR_C>usZg%MeDfDc%e9;5z9 zmTc< zj#v;mLq$z350qW(z#s<`fyx^xN@9k9#_9m+@0_{f%ZU{G4XIJS8PgMxjieCb${Uz7d!T?@Ir1GbPGLU_8&}$x$mEN;%HTx_(Aqt@ zQb`hmL;+OlE~0|6Mma?xInnaO-w}{FbpfX91aT9JwjxYiMOv}0B|th=kn;)>3K)s> zkgkrf9L7*UOm8fUl|GY?m{kBwQHr>JSTspPsI&Bv1j-}>o1ooCAwxo zDM};htyS-|c}|0M(CV6QnUo-$hAYKO)S2{E1fo+3N<(X)3Mhb-K*bRd5DLM!5NgIj zB#O_5CzRwWgUg=-fN_#dY^}jMS+{7cni!Y_$x^Jx9RPfS`6Z4(80&&CDq62>4UD8B z&|cVTjh%8uNHw`FOVZa_v_;ElU2(-w(RVyk_N5@BF3jqxPPI&Aq#3U2Iz+CRJaW-! z9pxrGyZGsnAi0T!;o_~y#c%kl8hpeW81ACtJ}C)+0z9ZJt{+l~L4E zYmt?odbOXnJoN#)Q-q#ce3?x~t&8pL+_rK8k6)fu&O-L?TlV}ihvKuz~Z zHUm`ryURB#-?13}RH!<)xeplYjrWoclSR{1oa9wg96xoN%pj3hmUeGxVLOaC6w9|l zZeg=w0g^hwT5J1la?a~cy@4FhZ6XNd8IEar2?*H)A9!rVay+Y^@dpUr@cRvF0(+NnluQl4?49T5vQS(_~>TabwuVk+$|kgJ|C22FfC+3)GIW z7Zp-&kPzxeNdU72)e%(fmMIP;28Bg9PK=saCyFcrlB6@(Gz5k?5ZX~D!l0&I{-CQE zL;y9uko!bt_Tk4fP#8ZnVaeu>Bw?a0l$=}MT9Qktj@~S@gWNG*RN%OI?$_559j@Uf z2|Gmdz(ku$Ca@&kcpJ2tAo5N7hhRlKi3sM18>qzs3XRx-lrVNLQ93|3vC)TH9ffi3 z8ZghKPYja#L^@$hYk3L=cei(jM1{vOD$vU$h|10GDh1^L0)5-^XX4FWt!3dj+miOj zSQl2TXOUrs!t+Vh9eKtXW=nH#IfX=O7)pp9G0X;2+UO=`fT@7$8D_~Qbj~7fgj3pO z5Dj(%2}H&3paBzofnAfbfg?_2$Oku;p<56{L(DPCW1^T3$mS9hg%JVx%mMd@(h#Lx z9-t|KKBA%cu>$@qiWM^$rT`EzGyAiL37iEoqM!-3CHRbyh)@C0 z02rp%*tP@_QOom2ku_oA(1=9(j-{f zQa<)sCs@IlhUZl&z09QL1d;{hD0iS#WV#I$M8aN_kRj74Okgogl49dVFm(Jo5bPQe z9-!C-bsrV6icO#q+OK=x;%)e;GN_wre!VF3=U z^#}%pL~}`V{{U3JEWGNmq-=ANz4Wm<Kv61%9dCWZU>d3p;s*($_)Fyxzp)&`CNLDhnOlLx$?LySKspC~gvJ2@5ecJqiLQa;Mrg*dDU?uMI6%J8nNFdKRe>@Jg&|6A+A)L*Pz`{FggtffWSLz! z6pPp9H)uOd<}jS5@rk^Hz&z6zs8sUAzyv9}6gj}5(bzyp zpO{k^L_m9dKt7eoMlm)*>{BP2qJ(&%4jo-*I>sQJ#sTalFQEVgL%0Tmb(3ktUHop% z&K^L7Z|^&GApFp(aga&n*l)FIFz6E8NvB@H3=3i+vPq&7~nuSv+6jT<<_!bB@bTV+%>IieMi(dDl{rh0HgwdnGjdu?gQt3 zFa&)BL_op6vqPP!Qb4 zB>{5ZsJ0#Au3W1>aPEba=Q%5#s(}XQ6x<2AdWGAdE{EaSS5O0ezF->=4S;V!y>6(p zvgmsvJt9$X{RI>Q4vYpPG(ZHU>;h3KL)3kJeQN1AZUTy{CSvu2w>uFX_cG=&iXou@ z5e}}~?XcFpYMFA}O(N}3AQ%%+$p8s{GMtSOI0%l1u$QYsBl9n91#A{KY+C4+E6uYE zoR02Dhy?GD*%}I3 z-*M3T2!^V&Rxwd(1?kX>RSHlM9_BFo0o#4Uq&NQnudb=O9TCyRF-JvanT@UX6E`ZG z5!av_d;7;;f;Eti=k;#Ev;P2Cj2x11p(XV3W?!TZwWQqe`$u0|uszVc!`{HgPlhU#RUicvPsn8=unB*a|kg3-g_mz)_jsQ4205`>HI-Zc``qm~!$LlA< zMxOF0R7mhSJ>1JDyuq@=$0Diq5-5Ry-O51%he-Dg4zwaaFzf^0?fYw}RRjK~qyR@k z0s;g3U5DqdzrU?j;@hN8(oh1J;wI1!a}Ry`2FL9l!Xw;ku5gC>Gy)w0ChxxeKmY(A zn_K=rO1*;Tmt`d6=Q%!`9FI?pYWj|kBP3=_t0)1)V0+xsU}4Dwgj}3*j}hU$jHM}F zqOXb6r722RrXK?en%o@WaP^R;ONu;rL{n2@Co!=treYX@tqFFg<2E7C0lgcr4pw_X zm^oOe5UP1=b`$HT@n!=QbRb|Ih<6S451*xCCj>v3dxpQUPmdqL6`xsK(r%uvk?G#L zv^_ifH|f8+wa0E}Y%cuAeE$HApHIJP`X8ep8b*_rz&dS%a`Nr{%MX$C^84$QyR{To z%_@ojn1BZOguVL-fI376q)Y%h-+g*jgwHq%*yI(cg}X3ejGl^BM|P#m*&s9cX%#w0 zKwuK6vo|LyWpLBXDHJgiP@+YXB89$1DU2lofQXy&bOJm4+V%PRZ_>F(NbHm_9014Y zFeX0`0ZeYiP&NU+kkP<9hQy#c9e`G|yt%TtitgH0if9-zNHTCn1_%UX5O6{3zg_B= z5NH}F6X_S)4!2=%sOfr)CL6m+(3F)km28YM$rIv8Wky+HkO?Amkwc6m#+kb0#4cK5 zu2Lx0*qMuNX12yrUC1eBUo04qq-tjqrs;0RbD*h_+A=0=vCbf81x3+}nXm1^oiP=; z9%)&;n`O6RBr?e=OO7qsoR>y0dmDCcTsU@P=t@M}BBF*6=>iFWYO=ZQTXOSqBRHM>zkHkd?B~deg9EK@?2C#EM#uWt=Sz>@r%zGBGj2T9(# z>>i`*Tc;Ci`fih;S?F9f-X*=)v>E4TE#^^A)$ z&&&Ow56#>5wdepJb#b1UrDp8MP{@$2moe5T6ikTWU!3vS+RJk2yB~SP zMM1$JoZy{~zIjh3UbpqlGYB_r*>PJVKH&>$8b(@5P^z?S@ylp27OJk`&fk@y#YC%^ z7IL7dVgbws0IY`K>kJ;QPb?-|iFCER%Cve zngD<%QiIV*2dUsSpxW)^R1>)trFPQQiJG~M=BMVQSFOlaY!y@C5c3jx{Hvs6XhB3u zA+Z9KZZC+HnFVNNdw%V<(r*-?A8d-F|>Gnsy<;KbZ01p zAqr9^P$39VDF{%}NJ4-CNBhPL$Ck<002}yc%Z?%G}bb>NP>oD5i>E0t_2Y) zY9#pu%2S*JL?HV>0eZ|GM>v!KL`nlDSTf~%c;Vb>b4j=tQd0J86R8(NuBR`(g(Tg$ zHh`hly6LE?^a1f4dk3XrFNq8a(inCYWd`L~(6&L4d1wt z7V?WI*qiUzs4kcQcF+dB19cJEhUL3eOSX6FpAr&gyBGc?mx&_&&$D>S5Xu0-OBFXf?HosrcdKxGB8 zOLe+%Bp`?)ir`<2Qv+Gg4{J5vK+YE?PMS~6C9KKxk<>9dl2YQj6YZ9V2- z5ip8-NHw!;yUmO-Xu78!>r+J>w$MuU>jMr&xNFj~BwX3qAH9hWE=gZ_07eIvIHORy z?LUJ4N&S~;H`i90&a-c(>bF{*u=ljsICjcSFy5~-C^OnFpQv3#jM-BRWID4484qdr znb>BEK^yYOx}t6*2vnbv7>r-AQFOoxqNxMdY+a+~91J4eWJJga^a`qLsBrU`T(^(p zVm8bry8$N)1#P@|_|D~=Bki*8T%=SJI;|QVR_PI{Wl$3_)>UCL$_B_lDQa!*95spV zx2j0oc;?HPeyD+!c>djsaOG2MM`|o~!lB1vBeNKLi0-3z#CHS6TXv>4zbuPcgiH)l zPoU?55dt}pG-(94##{yXpx3^{hR%oMim4tlkEshj_esWhE+FWk3?ewh64%BMZY>9j< z1aan^T`cY2yOlZx@+4)~S#e3COOVGXxGR;))K(Cg3~P+-yg_F|*_L!@FpG&m5h=7) zTsTod>vHYWl7^fbTw9yY}cFx{3I<dDJlgbDHSx^6dRQ)`sRL8<2*qe?Pqr!RK3sFrq=9iiVj`^#{n^1 zNc$n2sKKIU0rL!WRB)gNmf5nZ7@ENAw-?&Rr8bwQY1c7Zt^LHQW~nbc*KaZJZtlU# z^Rw=m0V9i$B7#`AS?r%h;jYcNBS+)jIpXaXQP%EwOGmVyiD$X9j>AmQVYZ3%z8T^5 zK^XQsSd|Ro2%76wzUH}|Pb3h*k@I;D-o^1V_eJ3Kyk)r!;EP=@RbY67=?9fRf7+EBn zGpp~ZBb-w!V>)Pvm9Z3E#xq{Ir;&WeyUS}uws5?A(-kI`oxDZUfsJmWfCqgd^~S{@ zP`xI0`TFU8FR8f*nnGj^EF4+lL>C_|vQJ8t8O(_?m?JAbRFw8;w2qjnq&yg{@utX! zF-W_!5jEeap3l&U6G1$>X?kx4+O7Vs@Zami2e8v2bdnfZlLfAolbEb*d5cNOos|`X z1{~H-IpaT+p1X6yot@j?aIa+w63dGC+Vb98Z9`XuXN|5j?G94^0I8np1@4Sc0dWjY zCcK&ykU=Hq!Z?0E3u9Ymz+k#+8YQ3}P4R@Fq=dVn_K8QJk$)HkS>lTwB#d36h^Cf+ zspu~Q$7zdp?2#2zO}UOfa=Iv(#}A05OaMfr0S?<8=r$l8mDbnrM?t#g)7;H>Jhv0M zdG2L-XOQ)IC35cGW8Pvw$-vujUf0p|Z9hWOG`$y0w~EtE(k$%s`wLjt5y5L^6mVO{ zrI?>~IMfzqEXOSD%t+1r9QvgT3a6COO7ek zV}kAk)XbBm#l@6Xi*9V+y|*4Fv#bu^5ZX?i`#D@p$xOZxCd%E4WkG3|rZQjVXbLY@ z1i-*oinLE>6qG1lzGCqr>f{9Nv2@yZ3}YA2vEJi%7cwpqZe|B~yTd(X;kqtAmWrb0 zDy^0xX{wrOn5&fK=r&(s%x?jStV@2ww#Zl!8(epcKatY5H#q=&@Kz(rZ!sWO8iEETg%)@26l&fU?Yy!ve^JkqgMgki3nT z9h32Q820VjRqqz*?Pb}u>hR6oxnm5g#MfFTk0q9eZW$$%J%*ooaeu1c+DQr@ZjVli zWp(GqH+XzVEZ>eXG3}i$f~;O9&=T{Rb@rKXK zl1`u9H*QEQbFPCpwj=KO2KLd;1Sw8rqRuNIfS60xVx&@#6gkdND2-Ma!wx}WiCg*Q zwEgf!-Asq=M;UOd7jOZvR2)sW+h9ZU#Ps<`?4uXcR{c8G_uOZg&bv-)b zSdGlhaFQo9PM!D?JbUg8QZu1pvtyY~`*!XO?CQ-sG2xB|<9!!S)JB7*!K7STvn|D) z=+X<>T3@(`pmo2siYumuUwsy11j-#;RAO?I1YqnF$19=Tr(r^)HuY$zMiWwiGLva9 zB=sUJt9duTyM$CtvTK;2*ij)vU{a6`+c$6|0WDk~jUz;epm^&N-cj3s^RpFkiEiQO zhyi*)OtF|%dG0Q~ygiLTQLhw!{m9;;~h)Ccg7ziAmq;z`$ z5d>JaVtIDyfQp+ibhkkgoaZo{!kC!jzV&&pXfZ~b)%?;)73ICee#v4~1sYo2u9s}? z8xI_kh>OJ-SIkj{AHIxhJ(BjVs9aulXTq9ppQm2%&ay9Ni=9IU=UCWa9(~xZKFDq zF^lFR-NDM~(Mmf8sH|?l16Y~G%tCj06`o)u%c+!OZMSUaZ)3_jfA~$lt^~-f$g(Fn zfwArTQOKxqT8@#gYaA`Y)|y@KX4+}$5mK94ih`jhwU(1*HPAc_3Ordd_aaviyfT%G{w007@$4_{wT zw0n=|`PH7o7*f;1cDO*>;Jf)J%7g2U<&n~p7Zjn29&5+$HYO5*gy7w{ek}qR-8(td zF|R6W9V2xUThW8LN?_57Vh>{ghoOgGVD}E-6{%`c*));c>FXi2v=16jFDl7-Bb75< zIt2zbkfI18Cox2zI4;abp!hn=i5Al5SK{emO?z3AIpxx9rZZ`p1)NI4%SX1Clnc4- z#FERXYAUF=m$S{>#+Go}M<33)jEl3VaQvjwIm2PF4FD7bKiL#b)Eo2=0r?GZ>#&aj z>RjXgc1G)YpLbaVq|o|oPt%~@$J0Z;_~q(72q)p1+obt~c#uFIb=V7)Q7IS@i3(&` z6j15_DoPG1M>sk8@}~-o4}VyG<0#Py(PT0W?r3bQr=UC={WhfeWI5 zR}AWG1cebPOaKNA=uA)mE{(5Jh!i#-F$($A%)sOU^!-Q5sKp9^j6mj4zVThyfw}9p zexAORud)r+bg58ok(N~Z=^+3F!_op_>>?h3AD+Jnfdu3Q1i+Y>pm8sA0YpQnN&*4` zARE_V@A9k33j+%cB+bfBUAT1V6R620QV=R#Ntg@^ogmQ!ccAkF>>7fvFwSwlI)7bI z)HMjKWA}r!u8#2_Q_B6;8Tq6Dh{CQ|u>=4zcFrv6(NKV4ICS)%%P@6yxRaqJ^+2=_)0L#Z90bO~C9LtfB*1t5RDiwQP zQ}m@PXs?>|r722Rp+5+ktZpE2BvDavCgY8GEj7%T009Kp!qq80J?y>xL<91BXm%l4 zNjnn~5K@oVR(UBl43{H!M>?QW89)}OdpXEqBB_{80H_EEfJ*g$CrLY)K&3HFuAvbD9eRIFk>t0sRE_Z+t*aR`$c0iEi2?ab1AtV32*wUhabFDh z&f813*0`PTZX=ne*R{yvw~hz9nI3IM<}m33TtZc&ot94cFn(2Z3%E6It!Z^wm{5Lm z5Qae`q-Q;q5)?qh0N-PQga=>)un->I!mbRB^19|bMA{h^BN(WtWd8sbbDO9%9Yyc5 zfqx`NL$Muq3ZmwtWZ#!+Fd-kRQY=tR0WbuT(FkIfdLW6w00A%pm;eLUxYiMM-wOB?9kaVfofx5n?|!pRlJpDnj~B74iI)+>hr6$hxQ2XHxs0WVO12y6tv9)nmp zQugY2!M;R8Duc_8>@H9cNNh-|q;mqeZSoFHbPYAMZ6iyPaiPz5I_d5j6+HJh58X>~ z-m<;7J-QjtDj3|(BfX85J7}iY%Iq9fNUAQk6gsf+j^uVCvX> zA|hZA4cBpU-~-QEkPA-Dq{%o}L}Kl!lq$=!MVkK3B2g1`I6xC135rt@R8-g$6i?s` z^_2Q1nR9N^Y6~sTC^Jlp-g3StTW&-}$aHwv5wggVv<$5qC>;L)Te9Q6EYkHvx8a1c z(=FtbY1T4xTf;Ssa%sm^6Wq**vnA!LS=|Ydo#CFsE31C#)$^_Y0E?8&)aBn{%TBdf zth>nzsb{2eRZ6$E0ygqXnNK_8F~wBGcdp~y1LPQKirYT1c{zgaD8rqEgUK5<>1w-O zrYJu-1Xoo70WU!NOLY{{N2l?I0RRrwvL7`t{fl|!q?up#BrWr4+6G0fsG91!D=>^Z zMhSH+;wjrl$U1o0lT)ZGDd!Z$^HLE3>OWbMxX;FHcYNB>4Y4F5YQn->R|S_iGB*R6 zn?XsK#`0kl=~0t8Bv`Ut$$)}%1mz%ty(6kX;!wdWS_*0HI{YLKPwsl`{C?cS59 zLnK!P#BFzLGf68)6Cq)6pQ&K=o(?bTQ<3|~-}Gix0u29nPgYN=bcIcM3VRSc=h zQh+EuB0VM%*ysR6HBv=(k%lco79~488_$&#Wku7sj$OnZC&;AjoP=43C@8WHn<$dy z^8}(nA1uHoD1g-YL2M<;zCN1C%P%c9xe1)(5KY9J8TiKU?Y3PDB+bj%be?-thOP)h zqN9x}B`6S8>G*1$v{Pvo(t8D^&BlwXT!HSBJ6QMMs*2$wh)U03V1g@hK#aht3k8#$ zs`A@Ce#?kB&xdthF4U~F&Nb}pX}XNjqQ|F>A%{u5hf=(R1m^L1OAOo$0th;EE z7NwlZ+Db;`m6Eog2=T(rjI)K8S~b60MoA=P&SvEm3PD)n3anreFc6)p^;-M|;vIz+ z;_j5QVegpaP%;ituipgtp zyp3ZuFwrz)?7ITriDwxF2*siWAroCsFU(ijikbuk->T_zbeT{htB9JSm-lueX)Nq6 zHD~5Fup~_^T=ypdVyqw^uU9Dp_0Ez4g`1$~mp!jf|COu@4w;n<&<5@9bcO8_95W zBY8`vm?sAW)KOkd%z0J-Bzc=KIGtIAz=rdUrbZH!iyq)+YbzaOISiwn7)m;gw4knN zh)C2W(jq6ifw>z;l{h^KjC2Uek<=;A=#Ueyq(pUMGKVm8eq~Mk9JJx%?UmkpYF6}1 zWZE}H6xH(@wpGGp2QJV5XxIP>s_mlLx>Osbqa1n)AW$#}PaT%FjJn>fdu69j0vH|*Ij6dfY^S=n zp6vjYLP>WrK^?p%G9!d5$satD4)2fZ97n)+4ROG{Bc*G+Ri^4QM|o>?#EGZrms4>C zrjd82X;%aEbl}?QHg`Ie{;PKLOl~idOGq!?8*3*s+6ar@P3A!Q)^rMW*Oe-Ujslr> zp2V_%kVO##fq?AF#6f~h!~}rc2#^#C02O-XF`OI*M!HwJ%Diob1uXPgwM1rB3Aa0c{z1MN5)4xKtLCcYcSyIJAQOb zs0ck-kDi(exDpCp@D=nYG9#>w{-oBDB#x3;ES8f)93i4>$x%C^j3bQ63=0-JrJ3bs zLo*eOmBVWKCl5iaEy_bZroV9xvuk@b{lqfEq1sMjxQ=^yC%afLH5R<*7js%$+rX1Y zro;aLS$L(8$8uQmeqRbiW0da*BQDbOEBO^|riy}Yts7kvFpstw#3G@Jm;y2Bg3B~p z%R1{Sq19D422!LJ-MirKc-V<3=Yo(-$D=6Co6`FfiJGiHKT?cW60T7oh>+q1GJRz* z6vhCkF1+RmmpLMf7pfSrQ4_KDv}066%KreFk&Xz=#UX?QqN~M|Rl?`#0{QDHpaKDP zlUai8QgbzpuN*!@YgzMHR^G^=$e9foa7}V2&>(UUSMxQkZ>Ruupx4PSmM8rZeT96e zHKyZ@3gYLn-qtmnTkUIz_@jpO_%$9J*5qbJx0{G~R^sN(Zgm08+|8QjLt{V4f8f6@=yUt)TGwWI3pou+nmq3ik|2XLl^tX#F8yA{J)+$G%FZoLJ)-g`4(g1LKvGDpn9Mv)069}BROn1p(S9O`Yydxs+CX1fUnpFVmejTP zcT6KGB+;0l?rHkSY0AV*c88uRh=)**a*u5W_1HdbY2W^jH)~T|!*!_qqkA~D;r3Oy zmiF6(c%JW7OCX)$f6-Fh+1eSx3>d#l_h9a3AQN7$)qm-m?DEp;??%(R660(AdK<|! z+iPh!k3+W8?r)Z3Z5l1?cDGk66q6MJ#+>iUNfD9&GZU71GmP;wCw|{56Z7eHrrOqC1^O{|v69<2a}$aj0u8ZzT58>atqO&<~rxDxa5EY=0;#ZC{5tp5sa2ZV9((Ax_RXUjBKmFR%Oc zh6mz(VpNW8U9|T}E=9a?*y;W3QAr-0lOoP2g$s4$iB|D&jTMj<$rZD7QYZo~kw`j2 zKpiQfLI8-E;$SEU2#A1eL0o$@^9^K7BO)-6q(N0Ao*8jO=R}|aWROUvDvnoFbed@p z3?g9;zyKx%eJypnM&-4Z-Y8X61t=VyWmr@H-^b5jbPh&`V~h?7X^;VzwcTeBSTZYxRJ&^0psvumN@EEPhdt zd2sCU`&?~V|7~~nYSPyyvJM=%8-QZF#iaO{V$^6FXritQt(S!RoIETJYpBH`RO)WZ zND5@)bvWO!)nL7layrm^&7nZp3x!`MVM#%2o!~Lh9Fdh0^(vN>B+lPGK%qYbaC>pz z{G?mtYyEY zl1aq}Cnf2p`x(Tg3?(4aRg?kFxmYyS>br8{qu|Jz66VD~_DA|zcpzkzJ`x5(4*x(# z(Vi;f&&l5R2;}RKyR@vZS5=8cX6c~eC&al(IOqt@SwhXHy>&pa65AL^Jj&FmHK-^t z)KAEs5fP!P1?bO4*4JopU*MM=Nqug2OB@?m9gqv@@{IiC{>;JuQ>7Q3XeuH%=%UI1MTHEv9I-YOMU|Y zQl)FrWv23<5e4?#XSF{B&$TKP>L+{VnFjf@1_3q2_v&LbSIIeM^tHb^P+&U;3 z)NEMnksoO7F@K$KeJgtIAM|+hJC=h_*}@n{sZ89 zPX@JNzc1B@Au_o08?Ohk3sD#LIxe;;O5)UVub_)ADhe-;z>$VB9Ur87PJkaDyNADz zJq-bOtf}7* z&-a~ger%13vMs*@Ap9PI#8qHgKaFL|JM{4H3hK!u5^(0`%Gt($9KEM`#_X9bu`ylT zck%&zM{{p+@Z{j3rpKP$ck(Z!mcxuIt=Zmn{nBhJuyqWe5zYS#Wdf|!*@YvKV4@uW zki@B=aLED%nRFtW3oYe1Cf+?-YRYmFjrv@;U6G_LH5B=t19WnI*;6#ihh9p^BQ47} z6ip!d^Dct6%YBCnpa5b+Z&yq((^tM5gyFgchgPP(+QsAjC4|VPB5prQ{Xfp8!Zq<= zK#NP{Or=Gg*7KreqnSp7esOQ2i?t?|DQ!P5q%InZk4PeiSn-&&x4K>n1UYteSTt%s z>b&!)pb#3K?)$!~+%nkockfNPHrFIU+yjqG+K1{ZaE;PABQ9_?pR69ik6&0yed(++ zZkjUyi2@$TvfZAqaj`4OJq1m1@pRO#S(#J7F@;Jcf8HGVvCPE!P(j8E_N#xP z&3j-2y00JgR~7)B_l5ok*tiSaMjB?h6H!w`=n|Ablp9)kpMT$N*)VT;eIDwl<|Bxt zP6%S~rFttGiPc0<_7VP0IFfwJK+an8?ZY&TL3|{cgG{2L!}ByeIjK}7TP_FTK)wk6 z)*X7qh{?yWrl-h-OY;9rweX{=)=MluLrNkAz)nnBbQK2XPV+7bo0op>^8xA9E=j?|C3U>VKW*dH7ccNTI{H^N(1t@WhJ zhTrypni5ZcmC`;I&9XzejlUiivKb|%u)kv3_&8T#0g^-3@?kH$YxMp*(;)kg4bNVv zJgqs6+gR7c{TY~A_@MQ$V5#y18Ea{~Xb!%NF_4*XygC{wagQ~ImfQ0Uze=nb7N8L! z$ree7)~J-y*WjGV3$1J-44<0&IC}y%NOD+DfPyQfn;cnr;SVeSL`7O9t^fe|Ngbhb z{V39)CVh%899i0$70s_|xZASSX5}72q}dm$QW10P_gQ}x2{2@eX|N!<#3+<{F?l^~ z9{TXur6FKY7IMQ(=>2WON}T3^v6QUKQa2jFikPaiV4sI$02u4_FPoS{?Rm~P7585$ zjR7=#ny!kd(Wfw*p9cvN-F>ZLN4_Plv*n{42h~+t)%x==MwN-J!ubW|)7Q$jY^T)? z0Sd8QUhU?Z2ZtndxbX!-sn8LM4&%6zT{a};TFH7(44j2fp$V_)UN{zVqv+U^u~@8E z2o39I;h%n%d%ZJ6?WUtHY=PfLsHKVC8gL*(jvwrrfyNt&^b=|qDFT3%n9iP+uHbEG zdibb63Bic(qaaT)Ju$OL5yUep6-&7eHrU|p(vO3X-dThS(B5V@@pmDc|2X}D{@!k0 z?Wj_Fd{2=K{b{T>fy7VQv;0s}4Oo!TGMeT&u^n0ruC#cFI7xWm>#Qzlp$gR=*AxlY-gy5eJRz;H;@Cf2y$efK z<8@eirub_9tl$Na97gu{z-le`)pX2BvzOE(7W2~w0(T$bP1?HZhPbwNz-e(V<8=g&G_whh5osV=4i(1Bv$QvOi4J;Y7lz(;uuO+= zM?>iwMuYDm7Zy51pH>h095Qsv?3vZar4FP^WHNWAdloz*m=)-{Bp;zn+2F2qCz zeUMYT7G+-Y@j(8sJ>NPTgqXGUY2^pjZ%V#(sjT1B1zGDVt!0$o!W^EJq9p-8cBAoz z*X9bOgS;Ze(@F3P9fu)%REjP0_73t(IJrzb#Vgq(j}+Mh*8ZPTuPYwbBlB=#!hJw) z-~73&Ju zD;C9)O-!^ORd;P&N{JI(t4beLXp!WV#x8eCl$4xDXK8t~890AErb{%Aq2Y~qZO;9b zndt!mEw4j`MoDKtwK*Agh80-r5HO#$Uxo?XGW za@|=RT2pgR#Gl{QBE@Gk2T9{1;!k~A=llgK6xM0gYJNZlYa+A09||qt4PA2*Jx^(` za9|O&I!|u)nw*<8mO3R3 zsCZr&J?Ag@dF#1LvtNb7tdX37be``pwyIgmNXprYOV&W63d3;z9{^d8byu(Sk_{+4 zQtE)6S4V4n%u0KT&)$#~c~BQ=l02(^3NAYPI$bPQaW-|}z*1HQfBn)je>9A@*;~7z z_2R(`=x?n11i#oQ}{snEE`P|t<1mQec-^&vr_<~OLJIkP|T~P?0Wby z?C^IpMm0YX%jPhYIOD)>H=y(>Mf^13aC|f)mjay5KeRp@J>k%rM*83xmwt*K3oLqn zWY1yKVn9A+;Qp@d*;;mr5z(n^lFN7o2b*{PION&iJ8e}~c_nmeoZX4;WUGvmT5UxQ zf2TgUeD*VIVu3{e_pN+az9$X>OaXy*`eGi&t}^!&Q@G3SJGs%d)+U?&1A^y4pQm!h4*oN2e^CzrD7WD72FLH#6K;)EeEDDTqpV={~$1FxC*^ zPUFUi+rT&jLdvo-3;Czj^jz=9Pa_%EKb7vzOyobjY4LGT*|w^SMfv(KjjX+`EK;;X zxJj=kJ2>Q8JsU3i(4HJ4K608Jk!(3;*YqQd#osO4FtwXtoG26QoBc_ZTytb~BzW=W zko}W?`3ZCAZeV?oGr}iF{wQgdn)2+7N)%JHc_+dogIF^4Jro$&eLFf{mAW^tM*pwV z_wUPv*LI6aYA)ke9}iYlgv*~|d(;#%hY=QIbX-~sq><{O#9Rlo2B$2mV+VT{Q}ASk zKbd89KB8lF#B^`MkLZZ%zs04!r#>2JdgJ0|m*O&M&cwWa5X%L2ah^8LN5lEGt&R_h6>C)H7 znpWZXw(B@|LTp5k;aT>WrRi53+5QKyMDU-=Bs@i$sw z?B|}jTe_A)mhnOiCv5mNI?>d4X*zs-hX_=H_1_*p1tb7kUiW{ORxPATZSHx)N2yYi zwTp?z0JKGi*f`p=C~822MNQ=T42)|gHT->BB}ZWhRLC1U7A0jtHdVU%KfT|~a`#u` zWaRF)ZgjZ+?8BSHT4$1{UUhCV?Z$={xrNc~pbaR^Q%xw1Yt^|e|MaH1``J*9`B|~* zTZ|2*qcL8jUA`h>1g}B`Aii<&DI*96^Y5@B!FTog zA;V(nF)y8(iL+;!AbMpaG!~zNXDU=aoxq696Y+2yZIT`=ZU>i~llc6OA*Xpl`F@ZW z3lzPg;zN$A!_|VbyTjLfBF$dT{y@9Fm3zIpQfFzU^H%AF7v1$I4{+v(N-JwsTE(D` z`kovPhDz;(0N?i?w1g$x^Sb4smbIXQ#YnoK$X!Yl=!5pU#UC zVt`ZBM-k9j@q&ftG@;}GCKW9$nMI9HG~`Vg4xG>u4FPOzbOXNYWvAmyzpy&o6i0)~ zv36L>TdOw=Uz;&|Wj4!K-w-J)Hw zFFM&GlLE7k-6dt72@plSjQpvf)VN41PU0Zcl8nduNzc*bU~M>Pfbr_IXmR(rEX2(_ zJtyPjyG1;sGS~xba-VF3>iw(57;7aM$UC15%Ui)%W;{v_bD89=#r{=;$b4{qm;?v4 ztQ^S^O&WPZ1tJu)ExIuRSBR&lHeodf4!CkC0Qhm8K&SzHVxrLGT{%vK5zT!wtk!!C zV)qfeR1HQzq8S|m#8w-3D0FHh=nO9uz7SC3%q9+NSvFgshvxw)SoLwq&eG%ip@A!h zZEG{^=WjOg8Qt0K0I?ymU7zU;!Vl6vJjS{{#qJfb(Qx_CZ?aTzAR&Sos*b*6(YZDd z?RP3P40#lZCdPFHggaGj#AQ#3&$hCZW0KeXPn$1f&*VTiO*QFJoZRDiy&%tgaG1yp zo+?$FoZn?w!R76;tGqv_-Mu>0lmiL*jc;D*0++1NBAQmp7C7PaV`2XfAU^F2&5tjF z>EWQbl6>t=gK%zOsr_{nAhC6);vdYF?GY6opM1eePxWprsRSDo&Ll?-@JKg$x=}pb zHS~~lVQSi$TihVmvsbtom?U)E^Srir%BKb^;rObYP|BlWn5V(Ge*&jqW8J}nv7713 z#J;-*WT`>y1FxIG{KXE~M7*EzMdTD(c|dpq>@iF>Bw!^LjlEq-=?{3AojkWS8U9kV zH{Q+xrLJr}>{4@gFX!Ft^`(`su8|zVh-Y7LRlI`b2a+-#-|4si347taHUTMT@3N_G zk4;}}(T&EAFNkwUQZL|msax%RMejF(5~W|s5T}b>(jfbslN0!QHIvKd4JN~osWUw_ zF+PJTTaCjb$q9}U0K%4ffzEDOgQqAOPzD#+#7?tZi}U$B?pDRi#gp8R7;vG07X zbJ_fhaP`l*dGu`-xz7~`IXrg5K~?b290SoqTv+2ok_q8A+=IzJo%liY|72q;Z$yP6 zahHoh%zwa-tgdU0b)=-FqDvm&2a{bPGL9m$n87ZY)qEX9z#YM9k3x9?P~y7WO?U?> zNo=TsN}STa4flw1Dc?ULWMbm^!Q*c4e*Wbvn~xc2I>lP; ze$f>>M#fw6^cA(Y2Af-qAtlc-TX>jI4QK&tK6mwc}(SmW|B$OZ!=oF(PH-U zu_(GR^_+X$r6=Tx)a)Q=&vNYI=~!K!pk*@F=pbNxls~gW+?>jF{V{F@vAA(8xNPDm zDCn{4^=o+OPQ7=(L)9<8>Uo}xNVboUAWGJz$MQLd{ohURrTnOH0bhH7y?IUnGsI7{ zVNut4PA?6On#GM=8C#4Z98d!nSAx}fWKeZs{>`0wl9%GmLWO+k!>H|Dh-c4;Y&G3x z4Ug6LVX+Z0Y(`2JdYt;hkG7!-3TO#Imj#ZD%v@Qw&b4?wrxNMK&e4uASZR8x1V7qxly0aIEEo2TTqO*x z)v}h2o-@dM_{{@)LwqNcX%BN2PN(}^70FX0*qWk&XB`EBk)8;1^Gfn7@7BmS{iL;I zl3o&rd@6HfF8L*^S$FnW+&ACI^SC@~D&a^lAFJiJsB^$E!BNT^N1@-`eJgOP-7M2r zaKQ9agGgZ^;m5$rVQ%Tlk0pcnYuh19nWiIdy*)Qsz0#_{w{tvxULKB}H1zQ~M#K)} zBa$=#701D_(qXLss`IKzn0}Y=YL3W$N~?ic&+C_TwI&)FHN`tF5LHs6Wzmc$hM4>2 zqhgi(ju4THF<%CrabIia%ks&nRA`nP`W`#!a zv4T>7((eqh>%3{hZ%|`DHIlM=SF?sXZ7c-U8*Ng`>{K1rWl@*tR#w;$BNwBX*8*yk>*j8-68j3N0`vDhmnEF?x3x=ltEDTE;0z zMU`!`%RdP|b|_5|-7mK5u)N4<-{#y=oeQ4}4GIHZ~9sV55u(O8o_bTsHx$>d?Fqp8MmmU5KfnwHu?vza5 zT0^NUIbLoq&;=ghs-6K9_i8&LmE9ce3XY|TxOKTOJ~6xpFB z>-BE&y4UE7hva`imyNF~bdt>LYOXD-w>_tikoJt{nAH0K5{{e@+`6oUx~bQ>7*_5Ooxybyr%4B z^eCccAd4B++&}kL%+WQF1Y5F;rfV_|#aP&t$NX~(Of2DJ7Y zT|2ZizX=IRtj`l}R}&qIyYyl}Xf;(AV3_RX&p>$6BMLKaqoD}_6pgo1qq*`Xqkl{) ztzDQ2<6o3`s}!#4l(A`}L*gw>b!j?^H-;6qC7TucGdz@ylY83;s+xMn$6V?QnEv*9 zi+bHB;$2nqg*=)kA}^LSEHkL6BXy6!xgk*iI0ldb;2mbC>{|~^3v2x2vV=Jo{9-v{2aOE9N8(k&Q9(V zRtc9_fm-!#&sRv^V~%zxjl+YZpwxJ&vZ@(k2xFHOYNPaKC9qhU;U2Y`(pMOJS)YpH z6IL?mjJboWcM%$!GW2dt4jmaXM1cs;))BfK)rr>DYzJu@HC1;W-)G*txn4!Rt(S#! zBdYy{K8=<<+~aT-J6?$D$JL*+6i3)EyOE$UT9OXV$CCyhOsG*k0`+x!yD+d>2c@&BsmC6DaK-ksA)ubmpb*C6!*K4_RHtv4x$B}Lfk^ulk>lTurZbM4X z=ezDpi50g3--DLDQfjNddQm=JM>OmZgk0IPyhNjd<#Pq9;S{lOvp}1Bg$Xr+4IcLP zH4p601kB;bz*K}jf&eRzq-0qJ?t+wqYuH~<~*nq3^lk= zzzG2OSNYH~J&5X;WsfM_xu!muIaBGhUR{fcu$M9%XZ%u16Bl^1)Q?1>a9bnEdmN-c ziVh7A^i>#7SO@Kk2DwF(Y**sq?jR7HaK^Y#@Vm~XV5_EJD~;7&K!BZ3j^I!WPw4o^ zzX4l4X2&_fp^fi~?VX(+t5*3diz|!Y8qZji*=I<5d_lz^^wYpD?;N}yC%A?7{#&~H zTZgHMjG#)Nb{H7IHS3kY{%e!4q(4eOn1=*Lqn=6r7;6%fpE4|c{60XF#Kp<$Zvm+} zGQxmuvT8{EGqErwrsiw16--_Igigy#LjR$eh|PphrpC%r@``%1XQrA?0bK38paY35 z;DsgF7|v-TCNSK}P*M!;m<5;!XNLyXo-mA)2j=E7K-NY#kQoyfEmcY!DxxQbG{Hqw z{7Vnm$-n3^^e(>c3W>dLWWTcPzMZx{8JXkddEdPyW~r6HcIRZ1Pt3L#W*x+quZ3yw zeSYfnKaOYlRdLHG-Lt>mygtM$mc7(TDHHmd54P$SjvJa&t}!7rQ8xg4%Su4Qe%BY8 z?#Aw3|Jjd;K`YMRDCuBv{0SJHMVHz!xeH&2JxSo#Gl{KzT}M_|&;5Ea44SyJRU~rl3b$rzY zcWt^sVc<@FEf78ke?5t+Drq`#9^)XGmjTHXe?yn6J?Al7p?EyuT7UF=9JVL(@#{=jxiQ8 zg4LZbMO3cV%ZVM6nRS$R6zLasKgjj1FJzMRX6&ZJNi4PlG(nmI*3_~3Jq_jwnnlN1Q5w`}tO1Ei zCC24160}yM^SF)heY~2?Gb3ZW^c+lolrUCit+)7YCSa^Fob<}*&6 zbBb$nwgd)p<>y_PzVS3I9!F&8xs|M`df2-WG`^)?HTyhF*Vy-#1G7nNhe}|yL!nG} z4N#Y=Xo8A?NRo7RC-t_#z z^u|dqIBumUG^y4!sQlErCYd0G$|e|KgP};GuDHON=Qm2-_)`fQ$51cMm!`XzDep)8 z;Thf~nc;gRO?@={%841}2k8)sykY68{Gl)qS_{VBL(Q9#d<7!yc77L4Uny!<;yj)% z7E#4prOz?hEb9t{_fky-=&z!PRIJK*JA7KiM5pFR4)MMqUU9adv_hXND=m$Y#9)I1 zNV+43K0`t*&vCS8qLxhRS-u&{mq;K2FO5O&-0-Yz@;G}SuWL*NtQd}KqA}(BUJ|Bgk zM{`+?W$)bPaB^kq@VC;5=@zl_k7OMK{Bn06lH)LUTFO<=?cKsr#R@4_Dg7fL_B1vs zbO3H4a?UyX5!|aFlD=c^)(?! z5~rX0jBK2lJqmh>vp!pdln2<@q*6?YiL4A@o`!c_{g4`l99JiG)i%<-_9X1A%PH_3 zfY=AQ=NEpP;NpWnJF5%B96*xr3bsoc5@xxF)JhQT-0{{F}