mirror of
https://github.com/Dr-Blank/Vaani.git
synced 2026-07-08 18:31:38 +00:00
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
This commit is contained in:
parent
bee1d233bf
commit
792448b0ef
6 changed files with 723 additions and 192 deletions
|
|
@ -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<void> 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<void> 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<double?> 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<int>(
|
||||
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<List<TaskRecord>> downloadHistory(
|
||||
DownloadHistoryRef ref, {
|
||||
|
|
@ -41,11 +142,13 @@ FutureOr<List<TaskRecord>> downloadHistory(
|
|||
return await FileDownloader().database.allRecords(group: group);
|
||||
}
|
||||
|
||||
@Riverpod(keepAlive: false)
|
||||
FutureOr<bool> downloadStatus(
|
||||
DownloadStatusRef ref,
|
||||
LibraryItemExpanded item,
|
||||
) async {
|
||||
final manager = ref.read(simpleDownloadManagerProvider);
|
||||
return manager.isItemDownloaded(item);
|
||||
@riverpod
|
||||
class IsItemDownloaded extends _$IsItemDownloaded {
|
||||
@override
|
||||
FutureOr<bool> build(
|
||||
LibraryItemExpanded item,
|
||||
) {
|
||||
final manager = ref.watch(downloadManagerProvider);
|
||||
return manager.isItemDownloaded(item);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue