feat: Sync offline/online playback when able (#431)

Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
PartyDonut 2025-08-03 13:35:56 +02:00 committed by GitHub
parent 15ac3566e2
commit 092836328f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
42 changed files with 1002 additions and 497 deletions

View file

@ -16,36 +16,36 @@ class SyncButton extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final nested = ref.watch(syncedNestedChildrenProvider(syncedItem));
return nested.when(
loading: () => const SizedBox.shrink(),
error: (err, stack) => const SizedBox.shrink(),
data: (children) {
final download = ref.watch(syncDownloadStatusProvider(syncedItem, children));
final status = download?.status ?? TaskStatus.notFound;
final progress = download?.progress ?? 0.0;
return switch (nested) {
AsyncValue<List<SyncedItem>>(:final value) => Builder(
builder: (context) {
final download = ref.watch(syncDownloadStatusProvider(syncedItem, value ?? []));
final status = download?.status ?? TaskStatus.notFound;
final progress = download?.progress ?? 0.0;
return Stack(
alignment: Alignment.center,
children: [
Icon(
status == TaskStatus.notFound
? (progress > 0 ? IconsaxPlusLinear.arrow_down_1 : IconsaxPlusLinear.more_circle)
: status.icon,
color: status.color(context),
size: status == TaskStatus.running && progress > 0 ? 16 : null,
),
SizedBox.fromSize(
size: const Size.fromRadius(10),
child: CircularProgressIndicator(
strokeCap: StrokeCap.round,
strokeWidth: 1.5,
color: status.color(context),
value: status == TaskStatus.running ? progress.clamp(0.0, 1.0) : 0,
),
),
],
);
},
);
return Stack(
alignment: Alignment.center,
children: [
Icon(
status == TaskStatus.notFound
? (progress > 0 ? IconsaxPlusLinear.arrow_down_1 : IconsaxPlusLinear.more_circle)
: status.icon,
color: status.color(context),
size: status == TaskStatus.running && progress > 0 ? 16 : null,
),
SizedBox.fromSize(
size: const Size.fromRadius(10),
child: CircularProgressIndicator(
strokeCap: StrokeCap.round,
strokeWidth: 1.5,
color: status.color(context),
value: status == TaskStatus.running ? progress.clamp(0.0, 1.0) : 0,
),
),
],
);
},
),
};
}
}

View file

@ -230,7 +230,8 @@ class _SyncItemDetailsState extends ConsumerState<SyncItemDetails> {
else if (baseItem?.parentBaseModel != null)
ElevatedButton(
onPressed: () async {
final parentItem = await ref.read(syncProvider.notifier).getSyncedItem(baseItem!.parentBaseModel);
final parentItem =
await ref.read(syncProvider.notifier).getSyncedItem(baseItem!.parentBaseModel.id);
setState(() {
if (parentItem != null) {
syncedItem = parentItem;

View file

@ -56,8 +56,10 @@ class _SyncedScreenState extends ConsumerState<SyncedScreen> {
SliverToBoxAdapter(
child: Padding(
padding: padding,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
child: Wrap(
alignment: WrapAlignment.center,
crossAxisAlignment: WrapCrossAlignment.center,
runAlignment: WrapAlignment.center,
spacing: 12,
children: [
ElevatedButton(
@ -65,7 +67,7 @@ class _SyncedScreenState extends ConsumerState<SyncedScreen> {
child: const Text("View Database"),
),
ElevatedButton(
onPressed: () => ref.read(syncProvider.notifier).db.clearDatabase(),
onPressed: () => ref.read(syncProvider.notifier).removeAllSyncedData(),
child: const Text("Clear drift database"),
),
ElevatedButton(