Skip to content

Commit 8271c2a

Browse files
committed
Simplify API
1 parent 6c7bae4 commit 8271c2a

File tree

3 files changed

+50
-50
lines changed

3 files changed

+50
-50
lines changed

demos/supabase-todolist/lib/widgets/guard_by_sync.dart

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,7 @@ class GuardBySync extends StatelessWidget {
2525
builder: (context, snapshot) {
2626
final status = snapshot.requireData;
2727
final (didSync, progress) = switch (priority) {
28-
null => (
29-
status.hasSynced ?? false,
30-
status.downloadProgress?.untilCompletion
31-
),
28+
null => (status.hasSynced ?? false, status.downloadProgress),
3229
var priority? => (
3330
status.statusForPriority(priority).hasSynced ?? false,
3431
status.downloadProgress?.untilPriority(priority)
@@ -42,9 +39,10 @@ class GuardBySync extends StatelessWidget {
4239
child: Column(
4340
children: [
4441
const Text('Busy with sync...'),
45-
LinearProgressIndicator(value: progress?.fraction),
42+
LinearProgressIndicator(value: progress?.downloadedFraction),
4643
if (progress case final progress?)
47-
Text('${progress.completed} out of ${progress.total}')
44+
Text(
45+
'${progress.downloadedOperations} out of ${progress.totalOperations}')
4846
],
4947
),
5048
);

packages/powersync_core/lib/src/sync/sync_status.dart

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -176,13 +176,6 @@ final class SyncStatus {
176176
extension type const BucketPriority._(int priorityNumber) {
177177
static const _highest = 0;
178178

179-
/// The a bucket priority lower than the lowest priority that will ever be
180-
/// allowed by the sync service.
181-
///
182-
/// This can be used as a priority that tracks complete syncs instead of
183-
/// partial completions.
184-
static const _sentinel = BucketPriority._(2147483647);
185-
186179
factory BucketPriority(int i) {
187180
assert(i >= _highest);
188181
return BucketPriority._(i);
@@ -236,15 +229,14 @@ typedef BucketProgress = ({
236229
});
237230

238231
@internal
239-
final class InternalSyncDownloadProgress {
232+
final class InternalSyncDownloadProgress extends ProgressWithOperations {
240233
final Map<String, BucketProgress> buckets;
241234

242-
final int _totalDownloaded;
243-
final int _totalTarget;
244-
245235
InternalSyncDownloadProgress(this.buckets)
246-
: _totalDownloaded = buckets.values.map((e) => e.sinceLast).sum,
247-
_totalTarget = buckets.values.map((e) => e.targetCount - e.atLast).sum;
236+
: super._(
237+
buckets.values.map((e) => e.targetCount - e.atLast).sum,
238+
buckets.values.map((e) => e.sinceLast).sum,
239+
);
248240

249241
factory InternalSyncDownloadProgress.forNewCheckpoint(
250242
Map<String, LocalOperationCounters> localProgress, Checkpoint target) {
@@ -269,15 +261,18 @@ final class InternalSyncDownloadProgress {
269261

270262
/// Sums the total target and completed operations for all buckets up until
271263
/// the given [priority] (inclusive).
272-
(int, int) targetAndCompletedCounts(BucketPriority priority) {
273-
return buckets.values.where((e) => e.priority >= priority).fold(
264+
ProgressWithOperations untilPriority(BucketPriority priority) {
265+
final (total, downloaded) =
266+
buckets.values.where((e) => e.priority >= priority).fold(
274267
(0, 0),
275268
(prev, entry) {
276269
final downloaded = entry.sinceLast;
277270
final total = entry.targetCount - entry.atLast;
278271
return (prev.$1 + total, prev.$2 + downloaded);
279272
},
280273
);
274+
275+
return ProgressWithOperations._(total, downloaded);
281276
}
282277

283278
InternalSyncDownloadProgress incrementDownloaded(SyncDataBatch batch) {
@@ -304,18 +299,17 @@ final class InternalSyncDownloadProgress {
304299
@override
305300
bool operator ==(Object other) {
306301
return other is InternalSyncDownloadProgress &&
307-
// _totalDownloaded and _totalTarget are derived values, but comparing
308-
// them first helps find a difference faster.
309-
_totalDownloaded == other._totalDownloaded &&
310-
_totalTarget == other._totalTarget &&
302+
// totalOperations and downloadedOperations are derived values, but
303+
// comparing them first helps find a difference faster.
304+
totalOperations == other.totalOperations &&
305+
downloadedOperations == other.downloadedOperations &&
311306
_mapEquality.equals(buckets, other.buckets);
312307
}
313308

314309
@override
315310
String toString() {
316-
final asView = asSyncDownloadProgress;
317-
final all = asView.untilCompletion;
318-
return 'for total: ${all.completed} / ${all.total}';
311+
final all = asSyncDownloadProgress;
312+
return 'for total: ${all.downloadedOperations} / ${all.totalOperations}';
319313
}
320314

321315
static const _mapEquality = MapEquality<Object?, Object?>();
@@ -329,14 +323,32 @@ final class InternalSyncDownloadProgress {
329323
///
330324
/// To obtain these values, use [SyncDownloadProgress] available through
331325
/// [SyncStatus.downloadProgress].
332-
typedef ProgressWithOperations = ({
333-
int total,
334-
int completed,
335-
double fraction,
336-
});
326+
final class ProgressWithOperations {
327+
/// How many operations need to be downloaded in total until the current
328+
/// download is complete.
329+
final int totalOperations;
330+
331+
/// How many operations have already been downloaded since the last complete
332+
/// download.
333+
final int downloadedOperations;
334+
335+
ProgressWithOperations._(this.totalOperations, this.downloadedOperations);
336+
337+
/// Relative progress (as a number between `0.0` and `1.0`).
338+
double get downloadedFraction {
339+
return totalOperations == 0 ? 0.0 : downloadedOperations / totalOperations;
340+
}
341+
}
337342

338343
/// Provides realtime progress on how PowerSync is downloading rows.
339344
///
345+
/// This type reports progress by implementing [ProgressWithOperations], meaning
346+
/// that [downloadedOperations], [totalOperations] and [downloadedFraction] are
347+
/// available on instances of [SyncDownloadProgress].
348+
/// Additionally, it's possible to obtain the progress towards a specific
349+
/// priority only (instead of tracking progress for the entire download) by
350+
/// using [untilPriority].
351+
///
340352
/// The reported progress always reflects the status towards the end of a
341353
/// sync iteration (after which a consistent snapshot of all buckets is
342354
/// available locally).
@@ -351,25 +363,15 @@ typedef ProgressWithOperations = ({
351363
/// counters are unlikely to be updated one-by-one.
352364
///
353365
/// [compacting]: https://docs.powersync.com/usage/lifecycle-maintenance/compacting-buckets
354-
extension type SyncDownloadProgress._(InternalSyncDownloadProgress _internal) {
355-
/// Returns download progress towards a complete checkpoint being received.
356-
///
357-
/// The returned [ProgressWithOperations] tracks the target amount of
358-
/// operations that need to be downloaded in total and how many of them have
359-
/// already been received.
360-
ProgressWithOperations get untilCompletion =>
361-
untilPriority(BucketPriority._sentinel);
362-
366+
extension type SyncDownloadProgress._(InternalSyncDownloadProgress _internal)
367+
implements ProgressWithOperations {
363368
/// Returns download progress towards all data up until the specified
364369
/// [priority] being received.
365370
///
366371
/// The returned [ProgressWithOperations] tracks the target amount of
367372
/// operations that need to be downloaded in total and how many of them have
368373
/// already been received.
369374
ProgressWithOperations untilPriority(BucketPriority priority) {
370-
final (total, downloaded) = _internal.targetAndCompletedCounts(priority);
371-
final progress = total == 0 ? 0.0 : downloaded / total;
372-
373-
return (total: total, completed: downloaded, fraction: progress);
375+
return _internal.untilPriority(priority);
374376
}
375377
}

packages/powersync_core/test/in_memory_sync_test.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -593,8 +593,8 @@ TypeMatcher<SyncDownloadProgress> isSyncDownloadProgress({
593593
required Object progress,
594594
Map<BucketPriority, Object> priorities = const {},
595595
}) {
596-
var matcher = isA<SyncDownloadProgress>()
597-
.having((e) => e.untilCompletion, 'untilCompletion', progress);
596+
var matcher =
597+
isA<SyncDownloadProgress>().having((e) => e, 'untilCompletion', progress);
598598
priorities.forEach((priority, expected) {
599599
matcher = matcher.having(
600600
(e) => e.untilPriority(priority), 'untilPriority($priority)', expected);
@@ -605,6 +605,6 @@ TypeMatcher<SyncDownloadProgress> isSyncDownloadProgress({
605605

606606
TypeMatcher<ProgressWithOperations> progress(int completed, int total) {
607607
return isA<ProgressWithOperations>()
608-
.having((e) => e.completed, 'completed', completed)
609-
.having((e) => e.total, 'total', total);
608+
.having((e) => e.downloadedOperations, 'completed', completed)
609+
.having((e) => e.totalOperations, 'total', total);
610610
}

0 commit comments

Comments
 (0)