Skip to content

Commit fe5969a

Browse files
committed
Adopt in example
1 parent 9319400 commit fe5969a

File tree

7 files changed

+109
-18
lines changed

7 files changed

+109
-18
lines changed

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

Lines changed: 69 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:flutter/material.dart';
2+
import 'package:powersync/powersync.dart';
23

34
import '../powersync.dart';
45
import './status_app_bar.dart';
@@ -38,30 +39,82 @@ class TodoListPage extends StatelessWidget {
3839
}
3940
}
4041

41-
class TodoListWidget extends StatelessWidget {
42+
class TodoListWidget extends StatefulWidget {
4243
final TodoList list;
4344

4445
const TodoListWidget({super.key, required this.list});
4546

47+
@override
48+
State<TodoListWidget> createState() => _TodoListWidgetState();
49+
}
50+
51+
class _TodoListWidgetState extends State<TodoListWidget> {
52+
SyncStreamSubscription? _listSubscription;
53+
54+
void _subscribe(String listId) {
55+
db
56+
.syncStream('todos', {'list': listId})
57+
.subscribe(ttl: const Duration(hours: 1))
58+
.then((sub) {
59+
if (mounted && widget.list.id == listId) {
60+
setState(() {
61+
_listSubscription = sub;
62+
});
63+
} else {
64+
sub.unsubscribe();
65+
}
66+
});
67+
}
68+
69+
@override
70+
void initState() {
71+
super.initState();
72+
_subscribe(widget.list.id);
73+
}
74+
75+
@override
76+
void didUpdateWidget(covariant TodoListWidget oldWidget) {
77+
super.didUpdateWidget(oldWidget);
78+
_subscribe(widget.list.id);
79+
}
80+
81+
@override
82+
void dispose() {
83+
super.dispose();
84+
_listSubscription?.unsubscribe();
85+
}
86+
4687
@override
4788
Widget build(BuildContext context) {
4889
return StreamBuilder(
49-
stream: TodoList.watchSyncStatus().map((e) => e.hasSynced),
50-
initialData: db.currentStatus.hasSynced,
90+
stream: db.statusStream,
91+
initialData: db.currentStatus,
5192
builder: (context, snapshot) {
52-
return StreamBuilder(
53-
stream: list.watchItems(),
54-
builder: (context, snapshot) {
55-
final items = snapshot.data ?? const [];
56-
57-
return ListView(
58-
padding: const EdgeInsets.symmetric(vertical: 8.0),
59-
children: items.map((todo) {
60-
return TodoItemWidget(todo: todo);
61-
}).toList(),
62-
);
63-
},
64-
);
93+
final hasSynced = switch (_listSubscription) {
94+
null => null,
95+
final sub => snapshot.requireData.statusFor(sub),
96+
}
97+
?.subscription
98+
.hasSynced ??
99+
false;
100+
101+
if (!hasSynced) {
102+
return const CircularProgressIndicator();
103+
} else {
104+
return StreamBuilder(
105+
stream: widget.list.watchItems(),
106+
builder: (context, snapshot) {
107+
final items = snapshot.data ?? const [];
108+
109+
return ListView(
110+
padding: const EdgeInsets.symmetric(vertical: 8.0),
111+
children: items.map((todo) {
112+
return TodoItemWidget(todo: todo);
113+
}).toList(),
114+
);
115+
},
116+
);
117+
}
65118
},
66119
);
67120
}

packages/powersync_core/lib/src/database/native/native_powersync_database.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ Future<void> _syncIsolate(_PowerSyncDatabaseIsolateArgs args) async {
376376
await shutdown();
377377
} else if (action == 'changed_subscriptions') {
378378
openedStreamingSync
379-
?.updateSubscriptions(action[1] as List<SubscribedStream>);
379+
?.updateSubscriptions(message[1] as List<SubscribedStream>);
380380
}
381381
}
382382
});

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,15 @@ extension type ResolvedSyncOptions(SyncOptions source) {
107107
crudThrottleTime: other.crudThrottleTime ?? crudThrottleTime,
108108
retryDelay: other.retryDelay ?? retryDelay,
109109
params: other.params ?? params,
110+
syncImplementation: other.syncImplementation,
110111
includeDefaultStreams:
111112
other.includeDefaultStreams ?? includeDefaultStreams,
112113
);
113114

114115
final didChange = !_mapEquality.equals(newOptions.params, params) ||
115116
newOptions.crudThrottleTime != crudThrottleTime ||
116117
newOptions.retryDelay != retryDelay ||
118+
newOptions.syncImplementation != source.syncImplementation ||
117119
newOptions.includeDefaultStreams != includeDefaultStreams;
118120
return (ResolvedSyncOptions(newOptions), didChange);
119121
}

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,24 @@ final class CoreActiveStreamSubscription implements SyncSubscriptionDefinition {
144144
},
145145
);
146146
}
147+
148+
Map<String, Object?> toJson() {
149+
return {
150+
'name': name,
151+
'parameters': parameters,
152+
'priority': priority.priorityNumber,
153+
'associated_buckets': associatedBuckets,
154+
'active': active,
155+
'is_default': isDefault,
156+
'has_explicit_subscription': hasExplicitSubscription,
157+
'expires_at': switch (expiresAt) {
158+
null => null,
159+
final expiresAt => expiresAt.millisecondsSinceEpoch / 1000,
160+
},
161+
'last_synced_at': switch (lastSyncedAt) {
162+
null => null,
163+
final lastSyncedAt => lastSyncedAt.millisecondsSinceEpoch / 1000,
164+
}
165+
};
166+
}
147167
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ final class SyncStatus {
5858

5959
final List<CoreActiveStreamSubscription>? _internalSubscriptions;
6060

61+
@internal
6162
const SyncStatus({
6263
this.connected = false,
6364
this.connecting = false,

packages/powersync_core/lib/src/web/sync_worker.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ class _ConnectedClient {
109109
_runner = null;
110110
return (JSObject(), null);
111111
case SyncWorkerMessageType.updateSubscriptions:
112+
_runner?.updateClientSubscriptions(
113+
this, (payload as UpdateSubscriptions).toDart);
112114
return (JSObject(), null);
113115
default:
114116
throw StateError('Unexpected message type $type');

packages/powersync_core/lib/src/web/sync_worker_protocol.dart

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'dart:js_interop';
55
import 'package:logging/logging.dart';
66
import 'package:powersync_core/src/schema.dart';
77
import 'package:powersync_core/src/sync/options.dart';
8+
import 'package:powersync_core/src/sync/stream.dart';
89
import 'package:web/web.dart';
910

1011
import '../connector.dart';
@@ -247,6 +248,7 @@ extension type SerializedSyncStatus._(JSObject _) implements JSObject {
247248
required String? downloadError,
248249
required JSArray? priorityStatusEntries,
249250
required JSArray<SerializedBucketProgress>? syncProgress,
251+
required JSString streamSubscriptions,
250252
});
251253

252254
factory SerializedSyncStatus.from(SyncStatus status) {
@@ -272,6 +274,7 @@ extension type SerializedSyncStatus._(JSObject _) implements JSObject {
272274
var other => SerializedBucketProgress.serialize(
273275
InternalSyncDownloadProgress.ofPublic(other).buckets),
274276
},
277+
streamSubscriptions: json.encode(status.internalSubscriptions).toJS,
275278
);
276279
}
277280

@@ -285,8 +288,11 @@ extension type SerializedSyncStatus._(JSObject _) implements JSObject {
285288
external String? downloadError;
286289
external JSArray? priorityStatusEntries;
287290
external JSArray<SerializedBucketProgress>? syncProgress;
291+
external JSString? streamSubscriptions;
288292

289293
SyncStatus asSyncStatus() {
294+
final streamSubscriptions = this.streamSubscriptions?.toDart;
295+
290296
return SyncStatus(
291297
connected: connected,
292298
connecting: connecting,
@@ -306,7 +312,7 @@ extension type SerializedSyncStatus._(JSObject _) implements JSObject {
306312
final syncedMillis = (rawSynced as JSNumber?)?.toDartInt;
307313

308314
return (
309-
priority: BucketPriority((rawPriority as JSNumber).toDartInt),
315+
priority: StreamPriority((rawPriority as JSNumber).toDartInt),
310316
lastSyncedAt: syncedMillis != null
311317
? DateTime.fromMicrosecondsSinceEpoch(syncedMillis)
312318
: null,
@@ -320,6 +326,13 @@ extension type SerializedSyncStatus._(JSObject _) implements JSObject {
320326
SerializedBucketProgress.deserialize(serializedProgress))
321327
.asSyncDownloadProgress,
322328
},
329+
streamSubscriptions: switch (streamSubscriptions) {
330+
null => null,
331+
final serialized => (json.decode(serialized) as List)
332+
.map((e) => CoreActiveStreamSubscription.fromJson(
333+
e as Map<String, Object?>))
334+
.toList(),
335+
},
323336
);
324337
}
325338
}

0 commit comments

Comments
 (0)