diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 40f04eb959..5fcec7fc5d 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -28,4 +28,9 @@ jobs: run: dart run realm_dart install - name: Run Realm SDK tests - run: ./scripts/test.sh + run: | + if ./scripts/test.sh --concurrency=1 2>&1 | grep "Some tests failed." + then + exit 1 + fi + diff --git a/examples/dart/bin/myapp.dart b/examples/dart/bin/myapp.dart index 8510c0f784..722a226c25 100644 --- a/examples/dart/bin/myapp.dart +++ b/examples/dart/bin/myapp.dart @@ -12,17 +12,17 @@ void main(List arguments) async { realm.add(Car(ObjectId(), "Audi", model: 'A8')); realm.add(Car(ObjectId(), "Mercedes", model: 'G Wagon')); }); - print("Bundled realm location: " + realm.config.path); + print("Bundled realm location: ${realm.config.path}"); realm.close(); // :snippet-end: Future createSyncedBundle() async { - final APP_ID = 'flutter-flexible-luccm'; + final appId = 'flutter-flexible-luccm'; // :snippet-start: create-synced-bundle print("Bundling synced realm"); // You must connect to the Device Sync server with an authenticated // user to work with the synced realm. - final app = App(AppConfiguration(APP_ID)); + final app = App(AppConfiguration(appId)); // Check if current user exists and log anonymous user if not. final user = app.currentUser ?? await app.logIn(Credentials.anonymous()); @@ -54,7 +54,7 @@ void main(List arguments) async { path: 'sync_bundle.realm'); realm.writeCopy(bundledConfig); - print("Bundled realm location: " + bundledConfig.path); + print("Bundled realm location: ${bundledConfig.path}"); realm.close(); // :snippet-end: } diff --git a/examples/dart/pubspec.lock b/examples/dart/pubspec.lock index 1b56426930..9ffe3802f6 100644 --- a/examples/dart/pubspec.lock +++ b/examples/dart/pubspec.lock @@ -162,10 +162,10 @@ packages: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.0" convert: dependency: transitive description: @@ -178,10 +178,10 @@ packages: dependency: transitive description: name: coverage - sha256: "3945034e86ea203af7a056d98e98e42a5518fff200d6e8e6647e1886b07e936e" + sha256: "576aaab8b1abdd452e0f656c3e73da9ead9d7880e15bdc494189d9c1a1baf0db" url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.0" crypto: dependency: transitive description: @@ -226,18 +226,18 @@ packages: dependency: transitive description: name: ejson - sha256: f336c6fb6c5c97db8ae59ba8ed207f542241f1db39cf2ef03776d308de3432ff + sha256: "42bdc6f57444e8c9cbf2c8dc8044424c27890a1d8cf64953b95f02d289afd88b" url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "0.3.1" ejson_annotation: dependency: transitive description: name: ejson_annotation - sha256: b265eea722ee340d77d1c36a55a1f963d517a0dabb569b0775664c319a4e3ebf + sha256: "7053cff1b6acf375b8e76270d576915fe434701f1f25b5751c8f9e1e73e50bcf" url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "0.3.1" faker: dependency: "direct main" description: @@ -290,18 +290,18 @@ packages: dependency: transitive description: name: graphs - sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" http: dependency: transitive description: name: http - sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" + sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" http_multi_server: dependency: transitive description: @@ -314,10 +314,10 @@ packages: dependency: transitive description: name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + sha256: "40f592dd352890c3b60fec1b68e786cefb9603e05ff303dbc4dda49b304ecdf4" url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.1.0" intl: dependency: transitive description: @@ -474,42 +474,42 @@ packages: dependency: transitive description: name: realm_common - sha256: "6db42e97d88a2866521467faa409aca3b92605071e1eb56c9afee78518ed0721" + sha256: "73919ec7a92cca6d6889cbf2688cca53e92779a115f5bba5bc69eb341c29581f" url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.3.0" realm_dart: dependency: "direct main" description: name: realm_dart - sha256: "1b5783b5ef88f7b7e34fe67ab7641ba1d0939052b5ad2c9391b0b2a9171a2a49" + sha256: "5ba69ba9a7533beedb23b64ea16291728c1cff2143f699f82bcfae958fcec50b" url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.3.0" realm_generator: dependency: transitive description: name: realm_generator - sha256: "99e056fb6dab76679e9de8928bc7b87e95f162e4cbc569dca09727066d96d63a" + sha256: ab1743027815a543faf348b12361662a2bf8ec7b9bcc0d9847276db70430c79e url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.3.0" sane_uuid: dependency: transitive description: name: sane_uuid - sha256: "5e83f796a7d19d38d3ba3a940642998fdd8c4a4049be135ed25404e37f76a18c" + sha256: "5b3fd581f51d01aef0526344c175e198d04ff701249c1a75186429dbb4367265" url: "https://pub.dev" source: hosted - version: "1.0.0-alpha.5" + version: "1.1.0" shelf: dependency: transitive description: name: shelf - sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 url: "https://pub.dev" source: hosted - version: "1.4.1" + version: "1.4.2" shelf_packages_handler: dependency: transitive description: @@ -594,10 +594,10 @@ packages: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" tar: dependency: transitive description: @@ -618,26 +618,26 @@ packages: dependency: "direct main" description: name: test - sha256: "7ee44229615f8f642b68120165ae4c2a75fe77ae2065b1e55ae4711f6cf0899e" + sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f" url: "https://pub.dev" source: hosted - version: "1.25.7" + version: "1.25.8" test_api: dependency: transitive description: name: test_api - sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" + sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" url: "https://pub.dev" source: hosted - version: "0.7.2" + version: "0.7.3" test_core: dependency: transitive description: name: test_core - sha256: "55ea5a652e38a1dfb32943a7973f3681a60f872f8c3a05a14664ad54ef9c6696" + sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d" url: "https://pub.dev" source: hosted - version: "0.6.4" + version: "0.6.5" timing: dependency: transitive description: @@ -666,10 +666,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "360c4271613beb44db559547d02f8b0dc044741d0eeb9aa6ccdb47e8ec54c63a" + sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc url: "https://pub.dev" source: hosted - version: "14.2.3" + version: "14.2.4" watcher: dependency: transitive description: @@ -682,26 +682,26 @@ packages: dependency: transitive description: name: web - sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062 url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "1.0.0" web_socket: dependency: transitive description: name: web_socket - sha256: "24301d8c293ce6fe327ffe6f59d8fd8834735f0ec36e4fd383ec7ff8a64aa078" + sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83" url: "https://pub.dev" source: hosted - version: "0.1.5" + version: "0.1.6" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: a2d56211ee4d35d9b344d9d4ce60f362e4f5d1aafb988302906bd732bc731276 + sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f" url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.0.1" webkit_inspection_protocol: dependency: transitive description: diff --git a/examples/dart/pubspec.yaml b/examples/dart/pubspec.yaml index e54bfbb70b..e35ed46e21 100644 --- a/examples/dart/pubspec.yaml +++ b/examples/dart/pubspec.yaml @@ -11,7 +11,7 @@ dependencies: dart_jsonwebtoken: ^2.4.2 faker: ^2.0.0 test: ^1.20.1 - realm_dart: ^3.0.0 + realm_dart: ^3.3.0 dev_dependencies: lints: ^4.0.0 diff --git a/examples/dart/test/access_token_test.dart b/examples/dart/test/access_token_test.dart index 2e2f9e74a3..a74787ec07 100644 --- a/examples/dart/test/access_token_test.dart +++ b/examples/dart/test/access_token_test.dart @@ -4,11 +4,11 @@ import 'package:realm_dart/realm.dart'; import 'dart:convert'; void main() { - const APP_ID = "example-testers-kvjdy"; + const appId = "example-testers-kvjdy"; group('Access tokens - ', () { late App app; setUp(() async { - final appConfig = AppConfiguration(APP_ID); + final appConfig = AppConfiguration(appId); app = App(appConfig); final authProvider = EmailPasswordAuthProvider(app); final email = "lisa@example.com"; diff --git a/examples/dart/test/add_sync_to_app.dart b/examples/dart/test/add_sync_to_app.dart index 7b42f73fac..1461f08479 100644 --- a/examples/dart/test/add_sync_to_app.dart +++ b/examples/dart/test/add_sync_to_app.dart @@ -16,11 +16,11 @@ class _Car { } void main() { - const APP_ID = "flutter-flexible-luccm"; + const appId = "flutter-flexible-luccm"; test("Add Sync to App", () async { // :snippet-start: connect-to-app - final app = App(AppConfiguration(APP_ID)); + final app = App(AppConfiguration(appId)); // :snippet-end: // :snippet-start: log-in final user = await app.logIn(Credentials.anonymous()); diff --git a/examples/dart/test/app_services_test.dart b/examples/dart/test/app_services_test.dart index ea2aac321a..2765f7e07f 100644 --- a/examples/dart/test/app_services_test.dart +++ b/examples/dart/test/app_services_test.dart @@ -6,30 +6,30 @@ import "dart:convert"; import "dart:isolate"; void main() { - const APP_ID = "example-testers-kvjdy"; - const EDGE_SERVER_APP_ID = "sync-edge-server-cskhoow"; + const appId = "example-testers-kvjdy"; + const edgeServerAppId = "sync-edge-server-cskhoow"; const baseUrl = 'http://localhost'; const newBaseUrl = 'https://services.cloud.mongodb.com'; group('App Services client - ', () { test('Access App client', () { // :snippet-start: access-app-client - final appConfig = AppConfiguration(APP_ID); + final appConfig = AppConfiguration(appId); final app = App(appConfig); //:snippet-end: expect(app, isNotNull); - expect(app.id, APP_ID); + expect(app.id, appId); }); test('App client advanced configuration', () { // :snippet-start: app-client-advanced-configuration - final appConfig = AppConfiguration(APP_ID, + final appConfig = AppConfiguration(appId, defaultRequestTimeout: const Duration(seconds: 120) // ... see reference docs for all available configuration options ); //:snippet-end: final app = App(appConfig); expect(app, isNotNull); - expect(app.id, APP_ID); + expect(app.id, appId); expect(appConfig.defaultRequestTimeout, Duration(seconds: 120)); }); @@ -37,7 +37,7 @@ void main() { // :snippet-start: custom-base-url // Specify a baseUrl to connect to a server other than the default final appConfig = - AppConfiguration(APP_ID, baseUrl: Uri.parse('https://example.com')); + AppConfiguration(appId, baseUrl: Uri.parse('https://example.com')); var app = App(appConfig); // :snippet-end: @@ -48,7 +48,7 @@ void main() { // :snippet-start: change-base-url // Specify a custom baseUrl to connect to. // In this case, an Edge Server instance running on the device. - final appConfig = AppConfiguration(EDGE_SERVER_APP_ID, + final appConfig = AppConfiguration(edgeServerAppId, baseUrl: Uri.parse('http://localhost:80')); var app = App(appConfig); @@ -73,9 +73,8 @@ void main() { // :snippet-start: access-app-by-id // Create an App instance once on main isolate, // ideally as soon as the app starts - final appConfig = AppConfiguration(APP_ID); + final appConfig = AppConfiguration(appId); final app = App(appConfig); - final appId = app.id; final receivePort = ReceivePort(); // :remove-start: expect(app, isNotNull); diff --git a/examples/dart/test/authenticate_users_test.dart b/examples/dart/test/authenticate_users_test.dart index 84fbd29a73..4d3c0bb28c 100644 --- a/examples/dart/test/authenticate_users_test.dart +++ b/examples/dart/test/authenticate_users_test.dart @@ -335,11 +335,11 @@ void main() { // :snippet-end: }); test('Remove a user from the device', () async { - late var user; + late User? user; if (app.currentUser != null) { user = app.currentUser; // :snippet-start: remove-user - await app.removeUser(user); + await app.removeUser(user!); // :snippet-end: } }); diff --git a/examples/dart/test/client_reset_test.dart b/examples/dart/test/client_reset_test.dart index e082626a83..c938f4a1bf 100644 --- a/examples/dart/test/client_reset_test.dart +++ b/examples/dart/test/client_reset_test.dart @@ -1,4 +1,3 @@ -import 'dart:io'; import 'package:realm_dart/realm.dart'; import 'package:test/test.dart'; diff --git a/examples/dart/test/compact_realm_test.dart b/examples/dart/test/compact_realm_test.dart index 19c5a84805..b2119ca358 100644 --- a/examples/dart/test/compact_realm_test.dart +++ b/examples/dart/test/compact_realm_test.dart @@ -1,8 +1,6 @@ import 'package:test/test.dart'; import '../bin/models/car.dart'; import 'package:realm_dart/realm.dart'; -import 'package:path/path.dart' as path; -import 'dart:io'; import './utils.dart'; void main() { diff --git a/examples/dart/test/data_ingest.test.dart b/examples/dart/test/data_ingest.test.dart index 765c8b9658..ca969a3624 100644 --- a/examples/dart/test/data_ingest.test.dart +++ b/examples/dart/test/data_ingest.test.dart @@ -22,8 +22,8 @@ void main() { // Because the Flutter/Dart SDK doesn't have a mongoClient yet, // we can't test that asymmetric objects exist in the backend. group('Create asymmetric abject and use Data Ingest', () { - const APP_ID = "flutter-flexible-luccm"; - final appConfig = AppConfiguration(APP_ID); + const appId = "flutter-flexible-luccm"; + final appConfig = AppConfiguration(appId); final app = App(appConfig); test("Create asymmetric object locally", () async { diff --git a/examples/dart/test/delete_realm_test.dart b/examples/dart/test/delete_realm_test.dart index a4be16fed5..770520322d 100644 --- a/examples/dart/test/delete_realm_test.dart +++ b/examples/dart/test/delete_realm_test.dart @@ -1,10 +1,8 @@ import 'package:test/test.dart'; import '../bin/models/car.dart'; import 'package:realm_dart/realm.dart'; -import 'package:path/path.dart' as path; import 'dart:io'; import './utils.dart'; -import 'dart:io'; void main() { test('Delete a Realm', () async { diff --git a/examples/dart/test/freeze_test.dart b/examples/dart/test/freeze_test.dart index 8450039ccd..54ddbea1bb 100644 --- a/examples/dart/test/freeze_test.dart +++ b/examples/dart/test/freeze_test.dart @@ -90,9 +90,9 @@ void main() { // Update data in the non-frozen realm final newLastName = "Foo"; realm.write(() { - people.forEach((Person person) { + for (var person in people) { person.lastName = newLastName; - }); + } }); // Data changes not in the frozen snapshot diff --git a/examples/dart/test/functions_test.dart b/examples/dart/test/functions_test.dart index cad151e69a..d5346e499a 100644 --- a/examples/dart/test/functions_test.dart +++ b/examples/dart/test/functions_test.dart @@ -1,4 +1,3 @@ -import 'dart:convert'; import 'package:realm_dart/realm.dart'; import 'package:test/test.dart'; diff --git a/examples/dart/test/manage_sync_session_test.dart b/examples/dart/test/manage_sync_session_test.dart index 1d42d4c739..b111cddfe0 100644 --- a/examples/dart/test/manage_sync_session_test.dart +++ b/examples/dart/test/manage_sync_session_test.dart @@ -55,12 +55,14 @@ main() { dynamic streamListener; streamListener = syncProgress.listen((syncProgressEvent) { if (called == false) { + print(syncProgressEvent.progressEstimate); expect(syncProgressEvent.progressEstimate > 0.0, isTrue); expect(syncProgressEvent.progressEstimate > 0.0, isTrue); called = true; streamListener.cancel(); } }); + // :remove-end: // Add data locally realm.write(() { @@ -111,15 +113,16 @@ main() { // :snippet-start: monitor-progress final stream = realm.syncSession.getProgressStream( ProgressDirection.upload, ProgressMode.forCurrentlyOutstandingWork); - + double progressEstimate = -1; late StreamSubscription streamListener; streamListener = stream.listen((syncProgressEvent) { - final progressEstimate = syncProgressEvent.progressEstimate; + progressEstimate = syncProgressEvent.progressEstimate; if (progressEstimate < 1.0) { print('Upload progress: ${progressEstimate * 100}%'); } }, onDone: () { + print('Upload progress: ${progressEstimate * 100}%'); print("Upload complete"); isCalled = true; // :remove: }, onError: (error) { diff --git a/examples/dart/test/migrations_test.dart b/examples/dart/test/migrations_test.dart index dd251d9e60..81589fcc6c 100644 --- a/examples/dart/test/migrations_test.dart +++ b/examples/dart/test/migrations_test.dart @@ -74,9 +74,7 @@ void main() { // That person must have been deleted, so nothing to do. continue; } - newPerson.fullName = oldPerson.dynamic.get("firstName") + - " " + - oldPerson.dynamic.get("lastName"); + newPerson.fullName = "${oldPerson.dynamic.get("firstName")} ${oldPerson.dynamic.get("lastName")}"; final oldId = oldPerson.dynamic.get("id"); newPerson.id = oldId.toString(); } @@ -110,9 +108,7 @@ void main() { } // Use dynamic API to get properties from old schema and use in the // new schema - newPerson.fullName = oldPerson.dynamic.get("firstName") + - " " + - oldPerson.dynamic.get("lastName"); + newPerson.fullName = "${oldPerson.dynamic.get("firstName")} ${oldPerson.dynamic.get("lastName")}"; // convert `id` from ObjectId to String final oldId = oldPerson.dynamic.get("id"); newPerson.id = oldId.toString(); diff --git a/examples/dart/test/open_flexible_sync_realm_test.dart b/examples/dart/test/open_flexible_sync_realm_test.dart index ce7766caf5..1189e3a8c4 100644 --- a/examples/dart/test/open_flexible_sync_realm_test.dart +++ b/examples/dart/test/open_flexible_sync_realm_test.dart @@ -9,7 +9,6 @@ class _Tricycle { @PrimaryKey() @MapTo('_id') late int id; - late String name; } @@ -26,8 +25,8 @@ class _Car { void main() { group('Open Flexible Sync Realm', () { - const APP_ID = "flutter-flexible-luccm"; - final appConfig = AppConfiguration(APP_ID); + const appId = "flutter-flexible-luccm"; + final appConfig = AppConfiguration(appId); final app = App(appConfig); test("Open Flexible Sync Realm", () async { final credentials = Credentials.anonymous(); @@ -68,34 +67,63 @@ void main() { expect(realm.isClosed, false); cleanUpRealm(realm, app); }); - test('Track download progress', () async { - final credentials = Credentials.anonymous(); - final currentUser = await app.logIn(credentials); - late int transferred; - late int transferable; - final config = Configuration.flexibleSync(currentUser, [Tricycle.schema]); - // :snippet-start: async-open-track-progress - final realm = - await Realm.open(config, onProgressCallback: (syncProgress) { - if (syncProgress.transferableBytes == syncProgress.transferredBytes) { - print('All bytes transferred!'); - // :remove-start: - transferred = syncProgress.transferredBytes; - transferable = syncProgress.transferableBytes; - // :remove-end: - } - }); - // :snippet-end: - expect(realm.isClosed, false); - expect(transferred, transferable); - expect(transferred, greaterThanOrEqualTo(0)); - cleanUpRealm(realm, app); + +Future addSubscriptions(Realm realm, String searchByPrefix) async { + final query = realm.query(r'name BEGINSWITH $0', ["a"]); + if (realm.subscriptions.find(query) == null) { + realm.subscriptions.update((mutableSubscriptions) => mutableSubscriptions.add(query)); + } + await realm.subscriptions.waitForSynchronization(); +} + +Future subscribeForAtlasAddedData(App app, {int itemsCount = 100}) async { + final productNamePrefix = "a"; + final user1 = await app.logIn(Credentials.anonymous(reuseCredentials: false)); + final config1 = Configuration.flexibleSync(user1, [Tricycle.schema]); + final realm1 = Realm(config1); + await addSubscriptions(realm1, productNamePrefix); + realm1.close(); + + final user2 = await app.logIn(Credentials.anonymous(reuseCredentials: false)); + final config2 = Configuration.flexibleSync(user2, [Tricycle.schema]); + final realm2 = Realm(config2); + + await addSubscriptions(realm2, productNamePrefix); + + final trikes = realm2.all(); + realm2.write(() { + realm2.deleteMany(trikes); + realm2.add(Tricycle(1001, "a1001")); + realm2.add(Tricycle(2002, "a2002")); + realm2.add(Tricycle(3003, "a3003")); + }); + + await realm2.syncSession.waitForUpload(); + await realm2.syncSession.waitForDownload(); + realm2.close(); + return config1; +} + +test("Track upload progress", () async { + final config = await subscribeForAtlasAddedData(app); + // :snippet-start: async-open-track-progress + double progressEstimate = -1; + final realm = await Realm.open(config, onProgressCallback: (syncProgress) { + progressEstimate = syncProgress.progressEstimate; + print('Sync progress: ${progressEstimate * 100}% complete.'); + if (progressEstimate == 1.0) { + // Transfer is complete + } }); + // :snippet-end: + expect(realm.isClosed, false); + expect(progressEstimate, 1.0); + cleanUpRealm(realm, app); + }); + test('Cancel download in progress', () async { final credentials = Credentials.anonymous(); final currentUser = await app.logIn(credentials); - late int transferred; - late int transferable; final config = Configuration.flexibleSync(currentUser, [Tricycle.schema]); // :snippet-start: async-open-cancel final token = CancellationToken(); @@ -132,7 +160,7 @@ void main() { final config = Configuration.flexibleSync(currentUser, [Car.schema], syncErrorHandler: (SyncError error) { handlerCalled = true; // :remove: - print("Error message" + error.message.toString()); + print("Error message${error.message}"); }); final realm = Realm(config); @@ -176,7 +204,7 @@ void main() { testCompensatingWriteError = compensatingWriteError; // :remove: final writeReason = compensatingWriteError.compensatingWrites!.first; - print("Error message: " + writeReason.reason); + print("Error message: ${writeReason.reason}"); // ... handle compensating write error as needed. } diff --git a/examples/dart/test/pet.realm.dart b/examples/dart/test/pet.realm.dart index 61132aa9d5..4a5fb18d1a 100644 --- a/examples/dart/test/pet.realm.dart +++ b/examples/dart/test/pet.realm.dart @@ -49,6 +49,10 @@ class Pet extends _Pet with RealmEntity, RealmObjectBase, RealmObject { Stream> get changes => RealmObjectBase.getChanges(this); + @override + Stream> changesFor([List? keyPaths]) => + RealmObjectBase.getChangesFor(this, keyPaths); + @override Pet freeze() => RealmObjectBase.freezeObject(this); diff --git a/examples/dart/test/quick_start_sync_test.dart b/examples/dart/test/quick_start_sync_test.dart index e374d07fa8..8ec9e1d8c8 100644 --- a/examples/dart/test/quick_start_sync_test.dart +++ b/examples/dart/test/quick_start_sync_test.dart @@ -17,11 +17,11 @@ class _Todo { void main() async { test('Add query to subscription set', () async { - const YOUR_APP_ID_HERE = 'flutter-flexible-luccm'; // :remove: + const yourAppIdHere = 'flutter-flexible-luccm'; // :remove: // Add your App Services App ID - const APP_ID = YOUR_APP_ID_HERE; + const appId = yourAppIdHere; // :snippet-start: init-app - final app = App(AppConfiguration(APP_ID)); + final app = App(AppConfiguration(appId)); // :snippet-end: // :snippet-start: log-in final loggedInUser = await app.logIn(Credentials.anonymous()); diff --git a/examples/dart/test/quick_start_test.dart b/examples/dart/test/quick_start_test.dart index 83002038cc..f4a6471f19 100644 --- a/examples/dart/test/quick_start_test.dart +++ b/examples/dart/test/quick_start_test.dart @@ -2,7 +2,6 @@ import 'package:test/test.dart'; import '../bin/models/car.dart'; import 'package:realm_dart/realm.dart'; -import 'utils.dart'; void main() { group('CRUD Operations', () { diff --git a/examples/dart/test/serialization_test.realm.dart b/examples/dart/test/serialization_test.realm.dart index c6398f6b33..b2558322cd 100644 --- a/examples/dart/test/serialization_test.realm.dart +++ b/examples/dart/test/serialization_test.realm.dart @@ -47,6 +47,10 @@ class Address extends _Address Stream> get changes => RealmObjectBase.getChanges
(this); + @override + Stream> changesFor([List? keyPaths]) => + RealmObjectBase.getChangesFor
(this, keyPaths); + @override Address freeze() => RealmObjectBase.freezeObject
(this); @@ -233,6 +237,11 @@ class SerializeModel extends _SerializeModel Stream> get changes => RealmObjectBase.getChanges(this); + @override + Stream> changesFor( + [List? keyPaths]) => + RealmObjectBase.getChangesFor(this, keyPaths); + @override SerializeModel freeze() => RealmObjectBase.freezeObject(this); diff --git a/examples/dart/test/sync_multiple_processes_test.dart b/examples/dart/test/sync_multiple_processes_test.dart index d6cc02cf7d..8725bb076b 100644 --- a/examples/dart/test/sync_multiple_processes_test.dart +++ b/examples/dart/test/sync_multiple_processes_test.dart @@ -1,5 +1,4 @@ // @Skip('hmm') -import 'dart:io'; import 'package:test/test.dart'; import 'package:realm_dart/realm.dart'; @@ -45,7 +44,7 @@ void main() { realmWithSync.subscriptions.update((mutableSubscriptions) { mutableSubscriptions.add(realmWithSync.all()); }); - realmWithSync.write(() => realmWithSync.add(Tricycle(1, 'MyTri'))); + realmWithSync.write(() => realmWithSync.add(Tricycle(10, 'MyTri'))); await realmWithSync.subscriptions.waitForSynchronization(); realmWithSync.close(); // :snippet-start: secondary-process @@ -57,8 +56,9 @@ void main() { Configuration.disconnectedSync(schema, path: sameRealmPath); final realmWithDisconnectedSync = Realm(disconnectedSyncConfig); // :snippet-end: - final myTri = realmWithDisconnectedSync.find(1); + final myTri = realmWithDisconnectedSync.find(10); expect(myTri, isNotNull); + realmWithSync.close(); realmWithDisconnectedSync.close(); // since both realm connections are only for 1 realm, this deletes both await cleanUpRealm(realmWithSync, app); diff --git a/examples/dart/test/utils.dart b/examples/dart/test/utils.dart index ffae7021df..098d18e112 100644 --- a/examples/dart/test/utils.dart +++ b/examples/dart/test/utils.dart @@ -1,24 +1,20 @@ -import 'dart:io'; import 'package:realm_dart/realm.dart'; import 'dart:math'; Future cleanUpRealm(Realm realm, [App? app]) async { await app?.currentUser?.logOut(); - if (!realm.isClosed) { realm.close(); } - - await delay(500); - + await delay(1000); Realm.deleteRealm(realm.config.path); } final random = Random(); String generateRandomString(int len) { - const _chars = 'abcdefghjklmnopqrstuvwxuz'; - return List.generate(len, (index) => _chars[random.nextInt(_chars.length)]) + const chars = 'abcdefghjklmnopqrstuvwxuz'; + return List.generate(len, (index) => chars[random.nextInt(chars.length)]) .join(); } diff --git a/source/examples/generated/flutter/add_sync_to_app.snippet.connect-to-app.dart b/source/examples/generated/flutter/add_sync_to_app.snippet.connect-to-app.dart index 494c6cf168..a483a3fa3d 100644 --- a/source/examples/generated/flutter/add_sync_to_app.snippet.connect-to-app.dart +++ b/source/examples/generated/flutter/add_sync_to_app.snippet.connect-to-app.dart @@ -1 +1 @@ -final app = App(AppConfiguration(APP_ID)); +final app = App(AppConfiguration(appId)); diff --git a/source/examples/generated/flutter/app_services_test.snippet.access-app-by-id.dart b/source/examples/generated/flutter/app_services_test.snippet.access-app-by-id.dart index b9862c6d36..c985dd21a5 100644 --- a/source/examples/generated/flutter/app_services_test.snippet.access-app-by-id.dart +++ b/source/examples/generated/flutter/app_services_test.snippet.access-app-by-id.dart @@ -1,8 +1,7 @@ // Create an App instance once on main isolate, // ideally as soon as the app starts -final appConfig = AppConfiguration(APP_ID); +final appConfig = AppConfiguration(appId); final app = App(appConfig); -final appId = app.id; final receivePort = ReceivePort(); // Later, access the App instance on background isolate diff --git a/source/examples/generated/flutter/app_services_test.snippet.access-app-client.dart b/source/examples/generated/flutter/app_services_test.snippet.access-app-client.dart index ca0fd71da7..3cb91a8980 100644 --- a/source/examples/generated/flutter/app_services_test.snippet.access-app-client.dart +++ b/source/examples/generated/flutter/app_services_test.snippet.access-app-client.dart @@ -1,2 +1,2 @@ -final appConfig = AppConfiguration(APP_ID); +final appConfig = AppConfiguration(appId); final app = App(appConfig); diff --git a/source/examples/generated/flutter/app_services_test.snippet.app-client-advanced-configuration.dart b/source/examples/generated/flutter/app_services_test.snippet.app-client-advanced-configuration.dart index 4babc7bff7..7e744a774c 100644 --- a/source/examples/generated/flutter/app_services_test.snippet.app-client-advanced-configuration.dart +++ b/source/examples/generated/flutter/app_services_test.snippet.app-client-advanced-configuration.dart @@ -1,4 +1,4 @@ -final appConfig = AppConfiguration(APP_ID, +final appConfig = AppConfiguration(appId, defaultRequestTimeout: const Duration(seconds: 120) // ... see reference docs for all available configuration options ); diff --git a/source/examples/generated/flutter/app_services_test.snippet.change-base-url.dart b/source/examples/generated/flutter/app_services_test.snippet.change-base-url.dart index 73f1fc6a43..a4cbca41bf 100644 --- a/source/examples/generated/flutter/app_services_test.snippet.change-base-url.dart +++ b/source/examples/generated/flutter/app_services_test.snippet.change-base-url.dart @@ -1,6 +1,6 @@ // Specify a custom baseUrl to connect to. // In this case, an Edge Server instance running on the device. -final appConfig = AppConfiguration(EDGE_SERVER_APP_ID, +final appConfig = AppConfiguration(edgeServerAppId, baseUrl: Uri.parse('http://localhost:80')); var app = App(appConfig); diff --git a/source/examples/generated/flutter/app_services_test.snippet.custom-base-url.dart b/source/examples/generated/flutter/app_services_test.snippet.custom-base-url.dart index 8ee460fc4a..9f8807993e 100644 --- a/source/examples/generated/flutter/app_services_test.snippet.custom-base-url.dart +++ b/source/examples/generated/flutter/app_services_test.snippet.custom-base-url.dart @@ -1,5 +1,5 @@ // Specify a baseUrl to connect to a server other than the default final appConfig = - AppConfiguration(APP_ID, baseUrl: Uri.parse('https://example.com')); + AppConfiguration(appId, baseUrl: Uri.parse('https://example.com')); var app = App(appConfig); diff --git a/source/examples/generated/flutter/authenticate_users_test.snippet.remove-user.dart b/source/examples/generated/flutter/authenticate_users_test.snippet.remove-user.dart index 9ddd85a16e..a824c6f69c 100644 --- a/source/examples/generated/flutter/authenticate_users_test.snippet.remove-user.dart +++ b/source/examples/generated/flutter/authenticate_users_test.snippet.remove-user.dart @@ -1 +1 @@ -await app.removeUser(user); +await app.removeUser(user!); diff --git a/source/examples/generated/flutter/freeze_test.snippet.freeze-realm-results.dart b/source/examples/generated/flutter/freeze_test.snippet.freeze-realm-results.dart index 8011554b5c..3bdf1df624 100644 --- a/source/examples/generated/flutter/freeze_test.snippet.freeze-realm-results.dart +++ b/source/examples/generated/flutter/freeze_test.snippet.freeze-realm-results.dart @@ -10,9 +10,9 @@ final frozenPeople = people.freeze(); // Update data in the non-frozen realm final newLastName = "Foo"; realm.write(() { - people.forEach((Person person) { + for (var person in people) { person.lastName = newLastName; - }); + } }); // Data changes not in the frozen snapshot diff --git a/source/examples/generated/flutter/manage_sync_session_test.snippet.monitor-progress.dart b/source/examples/generated/flutter/manage_sync_session_test.snippet.monitor-progress.dart index 392fb58861..71cde5d61f 100644 --- a/source/examples/generated/flutter/manage_sync_session_test.snippet.monitor-progress.dart +++ b/source/examples/generated/flutter/manage_sync_session_test.snippet.monitor-progress.dart @@ -1,14 +1,15 @@ final stream = realm.syncSession.getProgressStream( ProgressDirection.upload, ProgressMode.forCurrentlyOutstandingWork); - +double progressEstimate = -1; late StreamSubscription streamListener; streamListener = stream.listen((syncProgressEvent) { - final progressEstimate = syncProgressEvent.progressEstimate; + progressEstimate = syncProgressEvent.progressEstimate; if (progressEstimate < 1.0) { print('Upload progress: ${progressEstimate * 100}%'); } }, onDone: () { + print('Upload progress: ${progressEstimate * 100}%'); print("Upload complete"); }, onError: (error) { print("An error occurred: $error"); diff --git a/source/examples/generated/flutter/migrations_test.snippet.migrations-other.dart b/source/examples/generated/flutter/migrations_test.snippet.migrations-other.dart index bc180feeef..b093f194d7 100644 --- a/source/examples/generated/flutter/migrations_test.snippet.migrations-other.dart +++ b/source/examples/generated/flutter/migrations_test.snippet.migrations-other.dart @@ -12,9 +12,7 @@ final configWithChanges = Configuration.local([Person.schema, Car.schema], } // Use dynamic API to get properties from old schema and use in the // new schema - newPerson.fullName = oldPerson.dynamic.get("firstName") + - " " + - oldPerson.dynamic.get("lastName"); + newPerson.fullName = "${oldPerson.dynamic.get("firstName")} ${oldPerson.dynamic.get("lastName")}"; // convert `id` from ObjectId to String final oldId = oldPerson.dynamic.get("id"); newPerson.id = oldId.toString(); diff --git a/source/examples/generated/flutter/open_flexible_sync_realm_test.snippet.async-open-track-progress.dart b/source/examples/generated/flutter/open_flexible_sync_realm_test.snippet.async-open-track-progress.dart index 19f654f71d..dba65d4b20 100644 --- a/source/examples/generated/flutter/open_flexible_sync_realm_test.snippet.async-open-track-progress.dart +++ b/source/examples/generated/flutter/open_flexible_sync_realm_test.snippet.async-open-track-progress.dart @@ -1,6 +1,8 @@ -final realm = - await Realm.open(config, onProgressCallback: (syncProgress) { - if (syncProgress.transferableBytes == syncProgress.transferredBytes) { - print('All bytes transferred!'); +double progressEstimate = -1; +final realm = await Realm.open(config, onProgressCallback: (syncProgress) { + progressEstimate = syncProgress.progressEstimate; + print('Sync progress: ${progressEstimate * 100}% complete.'); + if (progressEstimate == 1.0) { + // Transfer is complete } }); diff --git a/source/examples/generated/flutter/open_flexible_sync_realm_test.snippet.handle-compensating-write-error.dart b/source/examples/generated/flutter/open_flexible_sync_realm_test.snippet.handle-compensating-write-error.dart index ddfa432552..c55fa4029d 100644 --- a/source/examples/generated/flutter/open_flexible_sync_realm_test.snippet.handle-compensating-write-error.dart +++ b/source/examples/generated/flutter/open_flexible_sync_realm_test.snippet.handle-compensating-write-error.dart @@ -2,7 +2,7 @@ void handleCompensatingWrite( CompensatingWriteError compensatingWriteError) { final writeReason = compensatingWriteError.compensatingWrites!.first; - print("Error message: " + writeReason.reason); + print("Error message: ${writeReason.reason}"); // ... handle compensating write error as needed. } diff --git a/source/examples/generated/flutter/open_flexible_sync_realm_test.snippet.sync-error-handler.dart b/source/examples/generated/flutter/open_flexible_sync_realm_test.snippet.sync-error-handler.dart index af5688bcce..845682586f 100644 --- a/source/examples/generated/flutter/open_flexible_sync_realm_test.snippet.sync-error-handler.dart +++ b/source/examples/generated/flutter/open_flexible_sync_realm_test.snippet.sync-error-handler.dart @@ -1,6 +1,6 @@ final config = Configuration.flexibleSync(currentUser, [Car.schema], syncErrorHandler: (SyncError error) { - print("Error message" + error.message.toString()); + print("Error message${error.message}"); }); final realm = Realm(config); diff --git a/source/examples/generated/flutter/quick_start_sync_test.snippet.init-app.dart b/source/examples/generated/flutter/quick_start_sync_test.snippet.init-app.dart index 494c6cf168..a483a3fa3d 100644 --- a/source/examples/generated/flutter/quick_start_sync_test.snippet.init-app.dart +++ b/source/examples/generated/flutter/quick_start_sync_test.snippet.init-app.dart @@ -1 +1 @@ -final app = App(AppConfiguration(APP_ID)); +final app = App(AppConfiguration(appId)); diff --git a/source/examples/generated/flutter/serialization_test.snippet.deserialize.dart b/source/examples/generated/flutter/serialization_test.snippet.deserialize.dart index 999f36d064..d64f85fa63 100644 --- a/source/examples/generated/flutter/serialization_test.snippet.deserialize.dart +++ b/source/examples/generated/flutter/serialization_test.snippet.deserialize.dart @@ -1,2 +1,5 @@ // Pass the serialized object to the method +final deserializeFromEjsonWithExplicitType = fromEJson(serializeByParam); + +// The method can also infer the object type Pet deserializeFromEjson = fromEJson(serializeByParam); diff --git a/source/sdk/flutter/sync/manage-sync-session.txt b/source/sdk/flutter/sync/manage-sync-session.txt index 8377bcc854..7149130a3f 100644 --- a/source/sdk/flutter/sync/manage-sync-session.txt +++ b/source/sdk/flutter/sync/manage-sync-session.txt @@ -119,8 +119,9 @@ ranges from ``0.0`` to ``1.0``. At ``1.0``, the progress stream is complete. .. tip:: - Use the ``progressEstimate`` to display a progress indicator or estimated - data transfer percentage. + You can also configure sync monitoring by using the + :ref:`onProgressCallback ` when you first open a + Realm. .. _flutter-monitor-network-connection: diff --git a/source/sdk/flutter/sync/open-synced-realm.txt b/source/sdk/flutter/sync/open-synced-realm.txt index 0cb8fa78ee..70dd075232 100644 --- a/source/sdk/flutter/sync/open-synced-realm.txt +++ b/source/sdk/flutter/sync/open-synced-realm.txt @@ -64,12 +64,19 @@ to open a realm immediately and sync data in the background when an internet con .. literalinclude:: /examples/generated/flutter/open_flexible_sync_realm_test.snippet.async-open.dart :language: dart +.. _flutter-progress-callback: + To track the state of the synchronization, pass a :flutter-sdk:`ProgressCallback ` to the optional named argument ``onProgressCallback``. .. literalinclude:: /examples/generated/flutter/open_flexible_sync_realm_test.snippet.async-open-track-progress.dart :language: dart +.. tip:: + + If you want to configure progress notifications *after* opening a realm, use + :ref:`SyncSession.getProgressStream `. + To be able to cancel a synchronization in progress, pass a `CancellationToken `__ instance to the optional named argument ``cancellationToken``.