feature: Re-implemented syncing

This commit is contained in:
PartyDonut 2025-07-27 10:54:29 +02:00
parent c5c7f71b84
commit 86ff355e21
51 changed files with 3067 additions and 1147 deletions

View file

@ -1,43 +1,34 @@
import 'package:isar/isar.dart';
import 'package:background_downloader/background_downloader.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:fladder/models/item_base_model.dart';
import 'package:fladder/models/syncing/download_stream.dart';
import 'package:fladder/models/syncing/i_synced_item.dart';
import 'package:fladder/models/syncing/sync_item.dart';
import 'package:fladder/providers/sync_provider.dart';
part 'sync_provider_helpers.g.dart';
@riverpod
class SyncChildren extends _$SyncChildren {
@override
List<SyncedItem> build(SyncedItem root) {
final isar = ref.watch(syncProvider.notifier).isar;
final syncPath = ref.read(syncProvider.notifier).syncPath ?? "";
if (isar == null) return [];
final all = <SyncedItem>[];
List<SyncedItem> toProcess = [root];
while (toProcess.isNotEmpty) {
final parentIds = toProcess.map((e) => e.id).toList();
final children = <ISyncedItem>[];
for (final id in parentIds) {
final results = isar.iSyncedItems.where().parentIdEqualTo(id).sortBySortName().findAll();
children.addAll(results);
}
if (children.isEmpty) break;
final wrapped = children.map((e) => SyncedItem.fromIsar(e, syncPath)).toList();
all.addAll(wrapped);
toProcess = wrapped;
}
return all;
Stream<SyncedItem?> syncedItem(Ref ref, ItemBaseModel? item) {
final id = item?.id;
if (id == null || id.isEmpty) {
return Stream.value(null);
}
return ref.watch(syncProvider.notifier).db.getItem(id).watchSingleOrNull();
}
@riverpod
class SyncedChildren extends _$SyncedChildren {
@override
FutureOr<List<SyncedItem>> build(SyncedItem item) => ref.read(syncProvider.notifier).getChildren(item);
}
@riverpod
class SyncedNestedChildren extends _$SyncedNestedChildren {
@override
FutureOr<List<SyncedItem>> build(SyncedItem item) => ref.read(syncProvider.notifier).getNestedChildren(item);
}
@riverpod
@ -55,49 +46,33 @@ class SyncDownloadStatus extends _$SyncDownloadStatus {
int downloadCount = 0;
double fullProgress = mainStream.hasDownload ? mainStream.progress : 0.0;
int fullySyncedChildren = 0;
for (var i = 0; i < nestedChildren.length; i++) {
final childItem = nestedChildren[i];
final downloadStream = ref.read(downloadTasksProvider(childItem.id));
if (childItem.videoFile.existsSync()) {
fullySyncedChildren++;
}
if (downloadStream.hasDownload) {
downloadCount++;
fullProgress += downloadStream.progress;
mainStream = mainStream.copyWith(status: downloadStream.status);
mainStream = mainStream.copyWith(
status: mainStream.status != TaskStatus.running ? downloadStream.status : mainStream.status,
);
}
}
int syncAbleChildren = nestedChildren.where((element) => element.hasVideoFile).length;
var fullySynced = nestedChildren.isNotEmpty ? fullySyncedChildren == syncAbleChildren : arg.videoFile.existsSync();
return mainStream.copyWith(
status: fullySynced ? TaskStatus.complete : mainStream.status,
progress: fullProgress / downloadCount.clamp(1, double.infinity).toInt(),
);
}
}
@riverpod
class SyncStatuses extends _$SyncStatuses {
@override
FutureOr<SyncStatus> build(SyncedItem arg, List<SyncedItem>? children) async {
final nestedChildren = children;
ref.watch(downloadTasksProvider(arg.id));
if (nestedChildren != null) {
for (var element in nestedChildren) {
ref.watch(downloadTasksProvider(element.id));
}
for (var i = 0; i < nestedChildren.length; i++) {
final item = nestedChildren[i];
if (item.hasVideoFile && !await item.videoFile.exists()) {
return SyncStatus.partially;
}
}
}
if (arg.hasVideoFile && !await arg.videoFile.exists()) {
return SyncStatus.partially;
}
return SyncStatus.complete;
}
}
@riverpod
class SyncSize extends _$SyncSize {
@override
@ -112,7 +87,9 @@ class SyncSize extends _$SyncSize {
ref.watch(downloadTasksProvider(element.id));
}
for (var element in nestedChildren) {
size += element.fileSize ?? 0;
if (element.videoFile.existsSync()) {
size += element.fileSize ?? 0;
}
}
}