diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 12ba268e3..f4c42dc4f 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -19,7 +19,7 @@ jobs: - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0 with: - flutter-version: '3.24' + flutter-version: '3.47.3' cache: true # This step requires fetch of test_integration packages because flutter format and diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 3f9cb3860..83cd926dd 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -16,7 +16,7 @@ jobs: - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0 with: - flutter-version: '3.24' + flutter-version: '3.47.3' cache: true - name: Use Intro Blurb As Homepage diff --git a/.github/workflows/flutter_example_app.yaml b/.github/workflows/flutter_example_app.yaml index 5667878ae..d41e1f59e 100644 --- a/.github/workflows/flutter_example_app.yaml +++ b/.github/workflows/flutter_example_app.yaml @@ -17,7 +17,7 @@ jobs: - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0 with: - flutter-version: "3.24" + flutter-version: "3.47.3" cache: true - name: "Build example app for iOS" @@ -39,7 +39,7 @@ jobs: - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0 with: - flutter-version: "3.29" + flutter-version: "3.47.3" cache: true - name: "Build example app for Android" diff --git a/.github/workflows/flutter_integration.yaml b/.github/workflows/flutter_integration.yaml index b6bb41ebe..4df1f8b11 100644 --- a/.github/workflows/flutter_integration.yaml +++ b/.github/workflows/flutter_integration.yaml @@ -18,7 +18,7 @@ jobs: - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0 with: - flutter-version: '3.29' + flutter-version: '3.47.3' cache: true # test_integration package depends on ably_flutter, so before we run integration @@ -81,7 +81,7 @@ jobs: - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0 with: - flutter-version: '3.29' + flutter-version: '3.47.3' cache: true - name: 'Run Flutter Driver tests' diff --git a/.github/workflows/ios_unit_tests.yml b/.github/workflows/ios_unit_tests.yml index 71510f3d2..916a7033c 100644 --- a/.github/workflows/ios_unit_tests.yml +++ b/.github/workflows/ios_unit_tests.yml @@ -18,7 +18,7 @@ jobs: - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0 with: - flutter-version: '3.29' + flutter-version: '3.47.3' cache: true - name: Set up iOS test project diff --git a/.tool-versions b/.tool-versions index 2d7c47ed4..544ec6c3d 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ ruby 3.4.5 -flutter 3.29.0 +flutter 3.47.3-stable diff --git a/PushNotifications.md b/PushNotifications.md index 6ecf4acda..9c9995536 100644 --- a/PushNotifications.md +++ b/PushNotifications.md @@ -25,7 +25,7 @@ See [issue #226](https://github.com/ably/ably-flutter/issues/226). - Android API level 19+ (Android 4.4+) - Android devices - Android emulator (with Google APIs) -- iOS 10+ +- iOS 13+ - Physical devices only - **Not supported:** iOS Simulator. Calling [`UIApplication:registerForRemoteNotifications`](https://developer.apple.com/documentation/uikit/uiapplication/1623078-registerforremotenotifications) will result in [`application:didFailToRegisterForRemoteNotificationsWithError`](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622962-application) method being called in your AppDelegate with an error: `remote notifications are not supported in the simulator`). This is an iOS simulator limitation. diff --git a/README.md b/README.md index febbb2d81..da15acb09 100644 --- a/README.md +++ b/README.md @@ -35,8 +35,8 @@ This SDK supports the following platforms: | Platform | Support | |----------|---------| | Android | Android 4.4 (API level 19) or newer. Java 8 language features supported via [Desugaring](https://developer.android.com/studio/write/java8-support#library-desugaring). | -| iOS | iOS 10 or newer | -| Flutter | Flutter 2.5.0 or higher | +| iOS | iOS 13 or newer | +| Flutter | Flutter 3.44.0 or higher | > [!NOTE] > If your project needs support for SDK Version lower than 24, Android Gradle Plugin 4.0.0+ must be used. diff --git a/analysis_options.yaml b/analysis_options.yaml index f815b7078..91aa6cefb 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -4,6 +4,9 @@ analyzer: # Templates for code generation can be excluded from analysis exclude: - bin/templates/** + - build/** + - android/** + - ios/** language: # Replacements for deprecated implicit-casts: false # Following https://dart.dev/guides/language/analysis-options#enabling-additional-type-checks @@ -18,6 +21,11 @@ analyzer: # allow self-reference to deprecated members # suppresses issues for deprecated members of the library like ClientOptions.fallbackHostsUseDefault deprecated_member_use_from_same_package: ignore + # Dart 3.13's analyzer extended this rule to private fields initialised from + # a named parameter, but the fix it suggests -- `this._field` in the + # parameter list -- is only legal under the off-by-default + # `private-named-parameters` experiment, so the reports are unactionable. + prefer_initializing_formals: ignore linter: # subject to false positives, perhaps worth suppressing in code in such cases @@ -37,7 +45,6 @@ linter: - avoid_implementing_value_types - avoid_init_to_null - avoid_js_rounded_ints - - avoid_null_checks_in_equality_operators - avoid_positional_boolean_parameters - avoid_redundant_argument_values - avoid_relative_lib_imports @@ -73,7 +80,6 @@ linter: - no_runtimeType_toString - omit_local_variable_types - only_throw_errors - - package_api_docs - prefer_adjacent_string_concatenation - prefer_asserts_in_initializer_lists - prefer_expression_function_bodies diff --git a/bin/codegen_context.dart b/bin/codegen_context.dart index 3b91e3079..baace2ed7 100644 --- a/bin/codegen_context.dart +++ b/bin/codegen_context.dart @@ -95,7 +95,7 @@ const List> _platformMethods = [ {'name': 'onRealtimePresenceMessage', 'value': 'onRealtimePresenceMessage'}, { 'name': 'publishRealtimeChannelMessage', - 'value': 'publishRealtimeChannelMessage' + 'value': 'publishRealtimeChannelMessage', }, {'name': 'releaseRealtimeChannel', 'value': 'releaseRealtimeChannel'}, {'name': 'realtimeHistory', 'value': 'realtimeHistory'}, @@ -104,7 +104,7 @@ const List> _platformMethods = [ {'name': 'realtimeAuthAuthorize', 'value': 'realtimeAuthAuthorize'}, { 'name': 'realtimeAuthCreateTokenRequest', - 'value': 'realtimeAuthCreateTokenRequest' + 'value': 'realtimeAuthCreateTokenRequest', }, {'name': 'realtimeAuthRequestToken', 'value': 'realtimeAuthRequestToken'}, {'name': 'realtimeAuthGetClientId', 'value': 'realtimeAuthGetClientId'}, @@ -124,7 +124,7 @@ const List> _platformMethods = [ // Used only on iOS { 'name': 'pushGetNotificationSettings', - 'value': 'pushGetNotificationSettings' + 'value': 'pushGetNotificationSettings', }, // Used only on iOS {'name': 'pushOpenSettingsFor', 'value': 'pushOpenSettingsFor'}, @@ -135,11 +135,11 @@ const List> _platformMethods = [ // Push Notification Events { 'name': 'pushNotificationTapLaunchedAppFromTerminated', - 'value': 'pushNotificationTapLaunchedAppFromTerminated' + 'value': 'pushNotificationTapLaunchedAppFromTerminated', }, { 'name': 'pushOnShowNotificationInForeground', - 'value': 'pushOnShowNotificationInForeground' + 'value': 'pushOnShowNotificationInForeground', }, {'name': 'pushOnMessage', 'value': 'pushOnMessage'}, {'name': 'pushOnBackgroundMessage', 'value': 'pushOnBackgroundMessage'}, @@ -147,17 +147,17 @@ const List> _platformMethods = [ // Used only on Android { 'name': 'pushBackgroundFlutterApplicationReadyOnAndroid', - 'value': 'pushBackgroundFlutterApplicationReadyOnAndroid' + 'value': 'pushBackgroundFlutterApplicationReadyOnAndroid', }, // Realtime events { 'name': 'onRealtimeConnectionStateChanged', - 'value': 'onRealtimeConnectionStateChanged' + 'value': 'onRealtimeConnectionStateChanged', }, { 'name': 'onRealtimeChannelStateChanged', - 'value': 'onRealtimeChannelStateChanged' + 'value': 'onRealtimeChannelStateChanged', }, {'name': 'onRealtimeChannelMessage', 'value': 'onRealtimeChannelMessage'}, @@ -183,15 +183,15 @@ const List> _objects = [ 'clientId', 'options', 'messages', - ] + ], }, { 'name': 'AblyMessage', - 'properties': ['registrationHandle', 'type', 'message'] + 'properties': ['registrationHandle', 'type', 'message'], }, { 'name': 'AblyEventMessage', - 'properties': ['eventName', 'type', 'message'] + 'properties': ['eventName', 'type', 'message'], }, { 'name': 'ErrorInfo', @@ -201,20 +201,20 @@ const List> _objects = [ 'statusCode', 'href', 'requestId', - 'cause' - ] + 'cause', + ], }, { 'name': 'MessageData', - 'properties': ['data', 'type'] + 'properties': ['data', 'type'], }, { 'name': 'DeltaExtras', - 'properties': ['format', 'from'] + 'properties': ['format', 'from'], }, { 'name': 'MessageExtras', - 'properties': ['extras', 'delta'] + 'properties': ['extras', 'delta'], }, { 'name': 'ClientOptions', @@ -255,15 +255,15 @@ const List> _objects = [ 'channelRetryTimeout', 'transportParams', 'dartVersion', - ] + ], }, { 'name': 'RestChannelOptions', - 'properties': ['cipherParams'] + 'properties': ['cipherParams'], }, { 'name': 'RealtimeChannelOptions', - 'properties': ['params', 'modes', 'cipherParams'] + 'properties': ['params', 'modes', 'cipherParams'], }, { 'name': 'CipherParams', @@ -276,8 +276,8 @@ const List> _objects = [ 'expires', 'issued', 'capability', - 'clientId' - ] + 'clientId', + ], }, { 'name': 'AuthOptions', @@ -291,8 +291,8 @@ const List> _objects = [ 'authHeaders', 'authParams', 'queryTime', - 'useTokenAuth' - ] + 'useTokenAuth', + ], }, { 'name': 'TokenParams', @@ -301,8 +301,8 @@ const List> _objects = [ 'clientId', 'nonce', 'timestamp', - 'ttl' - ] + 'ttl', + ], }, { 'name': 'TokenRequest', @@ -313,8 +313,8 @@ const List> _objects = [ 'mac', 'nonce', 'timestamp', - 'ttl' - ] + 'ttl', + ], }, { 'name': 'EnumConstants', @@ -342,8 +342,8 @@ const List> _objects = [ 'presence', 'publish', 'subscribe', - 'presenceSubscribe' - ] + 'presenceSubscribe', + ], }, { 'name': 'FormFactorEnum', @@ -355,8 +355,8 @@ const List> _objects = [ 'watch', 'car', 'embedded', - 'other' - ] + 'other', + ], }, { 'name': 'LogLevelEnum', @@ -364,19 +364,19 @@ const List> _objects = [ }, { 'name': 'DevicePlatformEnum', - 'properties': ['ios', 'android', 'browser'] + 'properties': ['ios', 'android', 'browser'], }, { 'name': 'DevicePushStateEnum', - 'properties': ['active', 'failing', 'failed'] + 'properties': ['active', 'failing', 'failed'], }, { 'name': 'ConnectionStateChange', - 'properties': ['current', 'previous', 'event', 'retryIn', 'reason'] + 'properties': ['current', 'previous', 'event', 'retryIn', 'reason'], }, { 'name': 'ChannelStateChange', - 'properties': ['current', 'previous', 'event', 'resumed', 'reason'] + 'properties': ['current', 'previous', 'event', 'resumed', 'reason'], }, { 'name': 'Message', @@ -388,8 +388,8 @@ const List> _objects = [ 'encoding', 'data', 'name', - 'extras' - ] + 'extras', + ], }, { 'name': 'PresenceMessage', @@ -402,46 +402,27 @@ const List> _objects = [ 'encoding', 'extras', 'timestamp', - ] + ], }, { 'name': 'PaginatedResult', - 'properties': ['items', 'type', 'hasNext'] + 'properties': ['items', 'type', 'hasNext'], }, { 'name': 'RestHistoryParams', - 'properties': [ - 'start', - 'end', - 'direction', - 'limit', - ] + 'properties': ['start', 'end', 'direction', 'limit'], }, { 'name': 'RealtimeHistoryParams', - 'properties': [ - 'start', - 'end', - 'direction', - 'limit', - 'untilAttach', - ] + 'properties': ['start', 'end', 'direction', 'limit', 'untilAttach'], }, { 'name': 'RestPresenceParams', - 'properties': [ - 'limit', - 'clientId', - 'connectionId', - ] + 'properties': ['limit', 'clientId', 'connectionId'], }, { 'name': 'RealtimePresenceParams', - 'properties': [ - 'waitForSync', - 'clientId', - 'connectionId', - ] + 'properties': ['waitForSync', 'clientId', 'connectionId'], }, { 'name': 'DeviceDetails', @@ -451,20 +432,20 @@ const List> _objects = [ 'platform', 'formFactor', 'metadata', - 'devicePushDetails' - ] + 'devicePushDetails', + ], }, { 'name': 'DevicePushDetails', - 'properties': ['recipient', 'state', 'errorReason'] + 'properties': ['recipient', 'state', 'errorReason'], }, { 'name': 'LocalDevice', - 'properties': ['deviceSecret', 'deviceIdentityToken'] + 'properties': ['deviceSecret', 'deviceIdentityToken'], }, { 'name': 'PushChannelSubscription', - 'properties': ['channel', 'deviceId', 'clientId'] + 'properties': ['channel', 'deviceId', 'clientId'], }, { 'name': 'PushRequestPermission', @@ -477,7 +458,7 @@ const List> _objects = [ 'providesAppNotificationSettings', 'provisional', 'announcement', - ] + ], }, { 'name': 'UNNotificationSettings', @@ -496,15 +477,15 @@ const List> _objects = [ 'announcementSetting', 'scheduledDeliverySetting', 'timeSensitiveSetting', - ] + ], }, { 'name': 'UNNotificationSettingEnum', - 'properties': ['notSupported', 'disabled', 'enabled'] + 'properties': ['notSupported', 'disabled', 'enabled'], }, { 'name': 'UNAlertStyleEnum', - 'properties': ['none', 'banner', 'alert'] + 'properties': ['none', 'banner', 'alert'], }, { 'name': 'UNAuthorizationStatusEnum', @@ -514,31 +495,28 @@ const List> _objects = [ 'authorized', 'provisional', 'ephemeral', - ] + ], }, { 'name': 'UNShowPreviewsSettingEnum', - 'properties': ['always', 'whenAuthenticated', 'never'] + 'properties': ['always', 'whenAuthenticated', 'never'], }, { 'name': 'RemoteMessage', - 'properties': [ - 'data', - 'notification', - ] + 'properties': ['data', 'notification'], }, { 'name': 'Notification', - 'properties': ['title', 'body'] + 'properties': ['title', 'body'], }, { 'name': 'CryptoGetParams', - 'properties': ['algorithm', 'key'] + 'properties': ['algorithm', 'key'], }, { 'name': 'CryptoGenerateRandomKey', - 'properties': ['keyLength'] - } + 'properties': ['keyLength'], + }, ]; // exporting all the constants as a single map @@ -546,5 +524,5 @@ const List> _objects = [ Map context = { 'types': _types, 'methods': _platformMethods, - 'objects': _objects + 'objects': _objects, }; diff --git a/bin/templates/platformconstants.dart.dart b/bin/templates/platformconstants.dart.dart index 7864dcde3..fbeec905e 100644 --- a/bin/templates/platformconstants.dart.dart +++ b/bin/templates/platformconstants.dart.dart @@ -1,6 +1,7 @@ String getPrefix(String str) => (str.length > 26) ? '\n ' : ' '; -String $(Map c) => ''' +String $(Map c) => + ''' // ignore_for_file: public_member_api_docs class CodecTypes { diff --git a/bin/templates/platformconstants.h.dart b/bin/templates/platformconstants.h.dart index 635ab269c..643957dcf 100644 --- a/bin/templates/platformconstants.h.dart +++ b/bin/templates/platformconstants.h.dart @@ -1,4 +1,5 @@ -String $(Map c) => ''' +String $(Map c) => + ''' @import Foundation; typedef NS_ENUM(UInt8, CodecType) { diff --git a/bin/templates/platformconstants.java.dart b/bin/templates/platformconstants.java.dart index 17fccf9ab..314396a9d 100644 --- a/bin/templates/platformconstants.java.dart +++ b/bin/templates/platformconstants.java.dart @@ -1,4 +1,5 @@ -String $(Map c) => ''' +String $(Map c) => + ''' package io.ably.flutter.plugin.generated; diff --git a/bin/templates/platformconstants.m.dart b/bin/templates/platformconstants.m.dart index 9ac7657b7..9f6b6a7c3 100644 --- a/bin/templates/platformconstants.m.dart +++ b/bin/templates/platformconstants.m.dart @@ -1,4 +1,5 @@ -String $(Map c) => ''' +String $(Map c) => + ''' #import "AblyPlatformConstants.h" diff --git a/example/ios/.gitignore b/example/ios/.gitignore index e96ef602b..eb5573aef 100644 --- a/example/ios/.gitignore +++ b/example/ios/.gitignore @@ -20,6 +20,7 @@ Flutter/Flutter.podspec Flutter/Generated.xcconfig Flutter/app.flx Flutter/app.zip +Flutter/ephemeral/ Flutter/flutter_assets/ Flutter/flutter_export_environment.sh ServiceDefinitions.json diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist index f2872cf47..ab8e063fe 100644 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -20,7 +20,5 @@ ???? CFBundleVersion 1.0 - MinimumOSVersion - 9.0 diff --git a/example/ios/Podfile b/example/ios/Podfile index b5196d5f2..10f3c9b47 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '12.0' +platform :ios, '13.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -38,11 +38,4 @@ post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) end - installer.generated_projects.each do |project| - project.targets.each do |target| - target.build_configurations.each do |config| - config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '10.0' - end - end - end end diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index ee9865844..232d372f4 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -42,14 +42,14 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: Ably: 1756d6590a572809c10fc4bcc32e05fe9e7867d7 - ably_flutter: 95785161fc2858c7be524af4334925d30682b3b0 + ably_flutter: 03c57b59bcbf92ba2bd6910f10ed4e155bced176 AblyDeltaCodec: add5d06a756b3581b12aab5b5500a320b8c55bea device_info_plus: 71ffc6ab7634ade6267c7a93088ed7e4f74e5896 - Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 flutter_local_notifications: ad39620c743ea4c15127860f4b5641649a988100 fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1 msgpack: c85f6251873059738472ae136951cec5f30f3251 -PODFILE CHECKSUM: 5dac7b8eff57b86c98038531a0cc7562fb467acc +PODFILE CHECKSUM: cc1f88378b4bfcf93a6ce00d2c587857c6008d3b COCOAPODS: 1.16.2 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 96babbb61..8d1a6f302 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -157,7 +157,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = "The Chromium Authors"; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -203,10 +203,12 @@ /* Begin PBXShellScriptBuildPhase section */ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( @@ -224,39 +226,21 @@ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", "${BUILT_PRODUCTS_DIR}/Ably/Ably.framework", "${BUILT_PRODUCTS_DIR}/AblyDeltaCodec/AblyDeltaCodec.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseCore/FirebaseCore.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal/FirebaseCoreInternal.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseInstallations/FirebaseInstallations.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseMessaging/FirebaseMessaging.framework", - "${BUILT_PRODUCTS_DIR}/GoogleDataTransport/GoogleDataTransport.framework", - "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework", - "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework", - "${BUILT_PRODUCTS_DIR}/Toast/Toast.framework", "${BUILT_PRODUCTS_DIR}/ably_flutter/ably_flutter.framework", "${BUILT_PRODUCTS_DIR}/device_info_plus/device_info_plus.framework", "${BUILT_PRODUCTS_DIR}/flutter_local_notifications/flutter_local_notifications.framework", "${BUILT_PRODUCTS_DIR}/fluttertoast/fluttertoast.framework", "${BUILT_PRODUCTS_DIR}/msgpack/msgpack.framework", - "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Ably.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AblyDeltaCodec.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreInternal.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseInstallations.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseMessaging.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleDataTransport.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Toast.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ably_flutter.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/device_info_plus.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_local_notifications.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fluttertoast.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/msgpack.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -265,6 +249,7 @@ }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -374,7 +359,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -400,7 +385,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -465,7 +450,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -514,7 +499,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -540,7 +525,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -576,7 +561,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index c87d15a33..9c12df59c 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist index ed3e8743b..ca132f81e 100644 --- a/example/ios/Runner/Info.plist +++ b/example/ios/Runner/Info.plist @@ -49,5 +49,9 @@ UIViewControllerBasedStatusBarAppearance + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + diff --git a/example/lib/app_provisioning.dart b/example/lib/app_provisioning.dart index 87f035128..bd5b417ec 100644 --- a/example/lib/app_provisioning.dart +++ b/example/lib/app_provisioning.dart @@ -66,30 +66,27 @@ class AppProvisioning { /// A set of base headers for HTTP requests Map get _requestHeaders => { - 'Content-Type': 'application/json', - 'Accept': 'application/json', - }; + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }; /// App spec used to provision the app /// /// See: https://docs.ably.com/client-lib-development-guide/test-api Map> get _appSpec => { - 'namespaces': [ - { - 'id': 'pushenabled', - 'pushEnabled': pushEnabled, - } - ], - 'keys': [ - { - // The need to use jsonEncode here is a requirement of the - // Sandbox Test API. The capability map has to be JSON encoded - // as a string and then appropriately escaped in order for - // presentation within a string value. - 'capability': jsonEncode(keyCapabilities), - }, - ], - }; + 'namespaces': [ + {'id': 'pushenabled', 'pushEnabled': pushEnabled}, + ], + 'keys': [ + { + // The need to use jsonEncode here is a requirement of the + // Sandbox Test API. The capability map has to be JSON encoded + // as a string and then appropriately escaped in order for + // presentation within a string value. + 'capability': jsonEncode(keyCapabilities), + }, + ], + }; /// Makes request to configured Ably provisioning URL and returns a /// new key for test application instance @@ -102,8 +99,10 @@ class AppProvisioning { if (response.statusCode != HttpStatus.created) { log("Server didn't return success. ${response.body}"); - throw HttpException("Server didn't return success." - ' Status: ${response.statusCode} : ${response.body}'); + throw HttpException( + "Server didn't return success." + ' Status: ${response.statusCode} : ${response.body}', + ); } final responseBody = jsonDecode(response.body) as Map; @@ -122,8 +121,10 @@ class AppProvisioning { if (response.statusCode != HttpStatus.ok) { log("Server didn't return success. ${response.body}"); - throw HttpException("Server didn't return success." - ' Status: ${response.statusCode} : ${response.body}'); + throw HttpException( + "Server didn't return success." + ' Status: ${response.statusCode} : ${response.body}', + ); } return Map.castFrom( diff --git a/example/lib/main.dart b/example/lib/main.dart index d3057f547..f40947235 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -22,33 +22,27 @@ Future main() async { class AblyFlutterExampleApp extends StatelessWidget { final AblyService ablyService; - const AblyFlutterExampleApp({ - required this.ablyService, - Key? key, - }) : super(key: key); + const AblyFlutterExampleApp({required this.ablyService, Key? key}) + : super(key: key); @override Widget build(BuildContext context) => MaterialApp( - home: Scaffold( - appBar: AppBar( - title: const Text('Ably Flutter Example App'), - ), - body: Center( - child: ListView( - padding: - const EdgeInsets.symmetric(vertical: 24, horizontal: 36), - children: [ - SystemDetailsSliver( - apiKeyProvision: ablyService.apiKeyProvision, - ), - const Divider(), - RealtimeSliver(ablyService), - const Divider(), - RestSliver(ablyService.rest), - const Divider(), - PushNotificationsSliver(ablyService.pushNotificationService) - ]), - ), + home: Scaffold( + appBar: AppBar(title: const Text('Ably Flutter Example App')), + body: Center( + child: ListView( + padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 36), + children: [ + SystemDetailsSliver(apiKeyProvision: ablyService.apiKeyProvision), + const Divider(), + RealtimeSliver(ablyService), + const Divider(), + RestSliver(ablyService.rest), + const Divider(), + PushNotificationsSliver(ablyService.pushNotificationService), + ], ), - ); + ), + ), + ); } diff --git a/example/lib/nested_realtime_events.dart b/example/lib/nested_realtime_events.dart index 574c14758..9657f3fdb 100644 --- a/example/lib/nested_realtime_events.dart +++ b/example/lib/nested_realtime_events.dart @@ -15,16 +15,20 @@ void listenRealtimeConnection(ably.Realtime realtime) { // and must cancel each subscription one by one //RETAINING LISTENER - α realtime.connection.on().listen((stateChange) { - print('RETAINING LISTENER α :: Change event arrived!: ${stateChange.event}' - '\nReason: ${stateChange.reason}'); + print( + 'RETAINING LISTENER α :: Change event arrived!: ${stateChange.event}' + '\nReason: ${stateChange.reason}', + ); }); //DISPOSE ON CONNECTED final stream = realtime.connection.on(); late StreamSubscription omegaSubscription; omegaSubscription = stream.listen((stateChange) async { - print('DISPOSABLE LISTENER ω :: Change event arrived!:' - ' ${stateChange.event}'); + print( + 'DISPOSABLE LISTENER ω :: Change event arrived!:' + ' ${stateChange.event}', + ); if (stateChange.event == ably.ConnectionEvent.connected) { await omegaSubscription.cancel(); } @@ -32,8 +36,10 @@ void listenRealtimeConnection(ably.Realtime realtime) { //RETAINING LISTENER - β realtime.connection.on().listen((stateChange) { - print('RETAINING LISTENER β :: Change event arrived!:' - ' ${stateChange.event}'); + print( + 'RETAINING LISTENER β :: Change event arrived!:' + ' ${stateChange.event}', + ); // NESTED LISTENER - ξ // will be registered only when connected event is received by β listener realtime.connection.on().listen((stateChange) { @@ -54,7 +60,8 @@ void listenRealtimeConnection(ably.Realtime realtime) { //RETAINING LISTENER - γ realtime.connection.on().listen((stateChange) async { print( - 'RETAINING LISTENER γ :: Change event arrived!: ${stateChange.event}'); + 'RETAINING LISTENER γ :: Change event arrived!: ${stateChange.event}', + ); if (stateChange.event == ably.ConnectionEvent.connected) { //by the time this cancel is triggered, // preZeta will already have received current event. diff --git a/example/lib/op_state.dart b/example/lib/op_state.dart index 3a2795914..8986ec6c7 100644 --- a/example/lib/op_state.dart +++ b/example/lib/op_state.dart @@ -1,6 +1 @@ -enum OpState { - notStarted, - inProgress, - succeeded, - failed, -} +enum OpState { notStarted, inProgress, succeeded, failed } diff --git a/example/lib/push_notifications/android_push_notification_configuration.dart b/example/lib/push_notifications/android_push_notification_configuration.dart index 248628359..fac28f79a 100644 --- a/example/lib/push_notifications/android_push_notification_configuration.dart +++ b/example/lib/push_notifications/android_push_notification_configuration.dart @@ -18,7 +18,8 @@ class AndroidPushNotificationConfiguration { await _flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< - AndroidFlutterLocalNotificationsPlugin>() + AndroidFlutterLocalNotificationsPlugin + >() ?.createNotificationChannel(channel); } } diff --git a/example/lib/push_notifications/push_notification_handlers.dart b/example/lib/push_notifications/push_notification_handlers.dart index 7dbbcc9c7..0cc11ee3b 100644 --- a/example/lib/push_notifications/push_notification_handlers.dart +++ b/example/lib/push_notifications/push_notification_handlers.dart @@ -9,7 +9,7 @@ class PushNotificationHandlers { static final notificationEvents = ably.Push.notificationEvents; static final BehaviorSubject> - _receivedMessagesBehaviorSubject = + _receivedMessagesBehaviorSubject = BehaviorSubject>.seeded([]); static ValueStream> receivedMessagesStream = @@ -17,8 +17,10 @@ class PushNotificationHandlers { static void setUpEventHandlers() { activationEvents.onUpdateFailed.listen((error) async { - logAndDisplayError(error, - prefixMessage: 'Push update registration failed'); + logAndDisplayError( + error, + prefixMessage: 'Push update registration failed', + ); }); activationEvents.onActivate.listen((error) async { logAndDisplayError(error, prefixMessage: 'Push activation failed'); @@ -39,14 +41,17 @@ class PushNotificationHandlers { notificationEvents.onMessage.listen((message) { addMessage(message); - print('RemoteMessage received while app is in foreground:\n' - 'RemoteMessage.Notification: ${message.notification}' - 'RemoteMessage.Data: ${message.data}'); + print( + 'RemoteMessage received while app is in foreground:\n' + 'RemoteMessage.Notification: ${message.notification}' + 'RemoteMessage.Data: ${message.data}', + ); }); notificationEvents.setOnShowNotificationInForeground((message) async { print( - 'Opting to show the notification when the app is in the foreground.'); + 'Opting to show the notification when the app is in the foreground.', + ); return true; }); @@ -58,8 +63,9 @@ class PushNotificationHandlers { /// You can get the notification which launched the app by a user tapping it. static void getLaunchMessage() { - notificationEvents.notificationTapLaunchedAppFromTerminated - .then((remoteMessage) { + notificationEvents.notificationTapLaunchedAppFromTerminated.then(( + remoteMessage, + ) { if (remoteMessage != null) { addMessage(remoteMessage); print('The app was launched by the user by tapping the notification'); @@ -73,11 +79,14 @@ class PushNotificationHandlers { } static Future _backgroundMessageHandler( - ably.RemoteMessage message) async { + ably.RemoteMessage message, + ) async { addMessage(message); - print('RemoteMessage received while app is in background:\n' - 'RemoteMessage.Notification: ${message.notification}' - 'RemoteMessage.Data: ${message.data}'); + print( + 'RemoteMessage received while app is in background:\n' + 'RemoteMessage.Notification: ${message.notification}' + 'RemoteMessage.Data: ${message.data}', + ); } static void addMessage(ably.RemoteMessage message) { diff --git a/example/lib/push_notifications/push_notification_message_examples.dart b/example/lib/push_notifications/push_notification_message_examples.dart index abc51b8c6..98d9b86e5 100644 --- a/example/lib/push_notifications/push_notification_message_examples.dart +++ b/example/lib/push_notifications/push_notification_message_examples.dart @@ -2,48 +2,54 @@ import 'package:ably_flutter/ably_flutter.dart' as ably; class PushNotificationMessageExamples { static final ably.Message pushNotificationMessage = ably.Message( - data: 'This is an Ably message published on channels that is also sent ' - 'as a notification message to registered push devices.', - extras: const ably.MessageExtras({ - 'push': { - 'notification': { - 'title': 'Hello from Ably!', - 'body': 'Example push notification from Ably.', - 'sound': 'default' - }, + data: + 'This is an Ably message published on channels that is also sent ' + 'as a notification message to registered push devices.', + extras: const ably.MessageExtras({ + 'push': { + 'notification': { + 'title': 'Hello from Ably!', + 'body': 'Example push notification from Ably.', + 'sound': 'default', }, - })); + }, + }), + ); static ably.Message pushDataMessage = ably.Message( - data: 'This is a Ably message published on channels that is also ' - 'sent as a data message to registered push devices.', - extras: const ably.MessageExtras({ - 'push': { - 'data': {'foo': 'bar', 'baz': 'quz'}, - 'apns': { - 'apns-headers': { - 'apns-push-type': 'background', - 'apns-priority': '5', - }, - 'aps': {'content-available': 1} - } + data: + 'This is a Ably message published on channels that is also ' + 'sent as a data message to registered push devices.', + extras: const ably.MessageExtras({ + 'push': { + 'data': {'foo': 'bar', 'baz': 'quz'}, + 'apns': { + 'apns-headers': { + 'apns-push-type': 'background', + 'apns-priority': '5', + }, + 'aps': {'content-available': 1}, }, - })); + }, + }), + ); static ably.Message pushDataNotificationMessage = ably.Message( - data: 'This is a Ably message published on channels that is also ' - 'sent as a data message to registered push devices.', - extras: const ably.MessageExtras({ - 'push': { - 'notification': { - 'title': 'Hello from Ably!', - 'body': 'Example push notification from Ably.', - 'sound': 'default' - }, - 'data': {'foo': 'bar', 'baz': 'quz'}, - 'apns': { - 'aps': {'content-available': 1} - } + data: + 'This is a Ably message published on channels that is also ' + 'sent as a data message to registered push devices.', + extras: const ably.MessageExtras({ + 'push': { + 'notification': { + 'title': 'Hello from Ably!', + 'body': 'Example push notification from Ably.', + 'sound': 'default', + }, + 'data': {'foo': 'bar', 'baz': 'quz'}, + 'apns': { + 'aps': {'content-available': 1}, }, - })); + }, + }), + ); } diff --git a/example/lib/push_notifications/push_notification_service.dart b/example/lib/push_notifications/push_notification_service.dart index 4769a7e64..f75958279 100644 --- a/example/lib/push_notifications/push_notification_service.dart +++ b/example/lib/push_notifications/push_notification_service.dart @@ -30,20 +30,20 @@ class PushNotificationService { } final BehaviorSubject> - _pushChannelDeviceSubscriptionsSubject = + _pushChannelDeviceSubscriptionsSubject = BehaviorSubject>(); ValueStream> - get pushChannelDeviceSubscriptionsStream => - _pushChannelDeviceSubscriptionsSubject.stream; + get pushChannelDeviceSubscriptionsStream => + _pushChannelDeviceSubscriptionsSubject.stream; final BehaviorSubject> - _pushChannelClientSubscriptionsSubject = + _pushChannelClientSubscriptionsSubject = BehaviorSubject>(); ValueStream> - get pushChannelClientSubscriptionsStream => - _pushChannelClientSubscriptionsSubject.stream; + get pushChannelClientSubscriptionsStream => + _pushChannelClientSubscriptionsSubject.stream; final BehaviorSubject _hasPushChannelSubject = BehaviorSubject.seeded(false); @@ -61,9 +61,9 @@ class PushNotificationService { _userNotificationPermissionGrantedSubject.stream; final BehaviorSubject - _notificationSettingsSubject = BehaviorSubject(); + _notificationSettingsSubject = BehaviorSubject(); late final ValueStream - notificationSettingsStream = _notificationSettingsSubject.stream; + notificationSettingsStream = _notificationSettingsSubject.stream; Future ensureRealtimeClientConnected() async { if (_realtime.connection.state != ably.ConnectionState.connected) { @@ -72,18 +72,21 @@ class PushNotificationService { } /// Only valid on iOS - Future requestNotificationPermission( - {bool provisional = false, - bool providesAppNotificationSettings = true}) async { + Future requestNotificationPermission({ + bool provisional = false, + bool providesAppNotificationSettings = true, + }) async { if (useRealtimeClient) { final granted = await _realtime.push.requestPermission( - provisional: provisional, - providesAppNotificationSettings: providesAppNotificationSettings); + provisional: provisional, + providesAppNotificationSettings: providesAppNotificationSettings, + ); _userNotificationPermissionGrantedSubject.add(granted); } else { final granted = await _rest.push.requestPermission( - provisional: provisional, - providesAppNotificationSettings: providesAppNotificationSettings); + provisional: provisional, + providesAppNotificationSettings: providesAppNotificationSettings, + ); _userNotificationPermissionGrantedSubject.add(granted); } await updateNotificationSettings(); @@ -95,8 +98,9 @@ class PushNotificationService { final settings = await _realtime.push.getNotificationSettings(); _notificationSettingsSubject.add(settings); } else { - _notificationSettingsSubject - .add(await _rest.push.getNotificationSettings()); + _notificationSettingsSubject.add( + await _rest.push.getNotificationSettings(), + ); } } @@ -104,6 +108,9 @@ class PushNotificationService { Future deactivateDevice() => getPushFromAblyClient().deactivate(); + // `reset` is deliberately exercised here despite being experimental: this + // example app is how we manually verify it. + // ignore: experimental_member_use Future resetActivation() => getPushFromAblyClient().reset(); Future getDevice() async { @@ -163,21 +170,25 @@ class PushNotificationService { await ensureRealtimeClientConnected(); if (useRealtimeClient) { await _realtimeChannel!.publish( - message: PushNotificationMessageExamples.pushNotificationMessage); + message: PushNotificationMessageExamples.pushNotificationMessage, + ); } else { await _restChannel!.publish( - message: PushNotificationMessageExamples.pushNotificationMessage); + message: PushNotificationMessageExamples.pushNotificationMessage, + ); } } Future publishDataMessageToChannel() async { await ensureRealtimeClientConnected(); if (useRealtimeClient) { - await _realtimeChannel! - .publish(message: PushNotificationMessageExamples.pushDataMessage); + await _realtimeChannel!.publish( + message: PushNotificationMessageExamples.pushDataMessage, + ); } else { - await _restChannel! - .publish(message: PushNotificationMessageExamples.pushDataMessage); + await _restChannel!.publish( + message: PushNotificationMessageExamples.pushDataMessage, + ); } } @@ -185,10 +196,12 @@ class PushNotificationService { await ensureRealtimeClientConnected(); if (useRealtimeClient) { await _realtimeChannel!.publish( - message: PushNotificationMessageExamples.pushDataNotificationMessage); + message: PushNotificationMessageExamples.pushDataNotificationMessage, + ); } else { await _restChannel!.publish( - message: PushNotificationMessageExamples.pushDataNotificationMessage); + message: PushNotificationMessageExamples.pushDataNotificationMessage, + ); } } @@ -205,15 +218,18 @@ class PushNotificationService { void _getChannels() { _hasPushChannelSubject.add(false); if (useRealtimeClient) { - _realtimeChannel = - _realtime.channels.get(Constants.channelNameForPushNotifications); + _realtimeChannel = _realtime.channels.get( + Constants.channelNameForPushNotifications, + ); _pushChannel = _realtimeChannel!.push; - _pushLogMetaChannel = - _realtime.channels.get(Constants.pushMetaChannelName); + _pushLogMetaChannel = _realtime.channels.get( + Constants.pushMetaChannelName, + ); _hasPushChannelSubject.add(true); } else { - _restChannel = - _rest.channels.get(Constants.channelNameForPushNotifications); + _restChannel = _rest.channels.get( + Constants.channelNameForPushNotifications, + ); _pushChannel = _restChannel!.push; _hasPushChannelSubject.add(true); } @@ -224,7 +240,7 @@ class PushNotificationService { /// ably-cocoa will only give the one you specify in params. /// This behavior is the same for [listSubscriptionsWithDeviceId] Future> - listSubscriptionsWithClientId() async { + listSubscriptionsWithClientId() async { await getDevice(); final subscriptions = await _pushChannel!.listSubscriptions({ 'clientId': localDeviceStream.value!.clientId!, @@ -236,7 +252,7 @@ class PushNotificationService { } Future> - listSubscriptionsWithDeviceId() async { + listSubscriptionsWithDeviceId() async { await getDevice(); final subscriptions = await _pushChannel!.listSubscriptions({ 'deviceId': localDeviceStream.value!.id!, diff --git a/example/lib/ui/ably_service.dart b/example/lib/ui/ably_service.dart index d812df3d9..8ff207726 100644 --- a/example/lib/ui/ably_service.dart +++ b/example/lib/ui/ably_service.dart @@ -36,27 +36,31 @@ class AblyService { } class ExampleMessages { - static ably.Message message = ably.Message(data: const { - 'I am': null, - 'and': { - 'also': 'nested', - 'too': {'deep': true} - } - }); + static ably.Message message = ably.Message( + data: const { + 'I am': null, + 'and': { + 'also': 'nested', + 'too': {'deep': true}, + }, + }, + ); static List messages = [ ably.Message(data: 42), ably.Message(data: const {'are': 'you'}), ably.Message(data: 'ok?'), - ably.Message(data: const [ - false, - { - 'I am': null, - 'and': { - 'also': 'nested', - 'too': {'deep': true} - } - } - ]), + ably.Message( + data: const [ + false, + { + 'I am': null, + 'and': { + 'also': 'nested', + 'too': {'deep': true}, + }, + }, + ], + ), ]; } diff --git a/example/lib/ui/api_key_service.dart b/example/lib/ui/api_key_service.dart index f5d54518f..951e4c3ac 100644 --- a/example/lib/ui/api_key_service.dart +++ b/example/lib/ui/api_key_service.dart @@ -8,10 +8,7 @@ class ApiKeyService { Future getOrProvisionApiKey() async { if (envKey.isNotEmpty && envKey != defaultEnvKeyPlaceholder) { - return ApiKeyProvision( - key: envKey, - source: ApiKeySource.env, - ); + return ApiKeyProvision(key: envKey, source: ApiKeySource.env); } else { final provisionedKey = await AppProvisioning().provisionApp(); return ApiKeyProvision( @@ -27,13 +24,7 @@ class ApiKeyProvision { ApiKeySource source; - ApiKeyProvision({ - required this.key, - required this.source, - }); + ApiKeyProvision({required this.key, required this.source}); } -enum ApiKeySource { - env, - testProvision, -} +enum ApiKeySource { env, testProvision } diff --git a/example/lib/ui/auth.dart b/example/lib/ui/auth.dart index 30c3b1aaa..d0d87ac1b 100644 --- a/example/lib/ui/auth.dart +++ b/example/lib/ui/auth.dart @@ -16,20 +16,23 @@ Future> getTokenDetails( ]) async { final stringToBase64 = utf8.fuse(base64); final encoded = stringToBase64.encode('$keyName:$keySecret'); - final r = await const RetryOptions( - maxAttempts: 5, - delayFactor: Duration(seconds: 2), - ).retry(() => http.post( - Uri.parse(_tokenDetailsURL(keyName, prefix)), - headers: { - 'Authorization': 'Basic $encoded', - 'Content-Type': 'application/json', - }, - body: json.encode({ - 'keyName': keyName, - 'timestamp': DateTime.now().millisecondsSinceEpoch, - }), - )); + final r = + await const RetryOptions( + maxAttempts: 5, + delayFactor: Duration(seconds: 2), + ).retry( + () => http.post( + Uri.parse(_tokenDetailsURL(keyName, prefix)), + headers: { + 'Authorization': 'Basic $encoded', + 'Content-Type': 'application/json', + }, + body: json.encode({ + 'keyName': keyName, + 'timestamp': DateTime.now().millisecondsSinceEpoch, + }), + ), + ); print('tokenDetails from server: ${r.body}'); return Map.castFrom( jsonDecode(r.body) as Map, diff --git a/example/lib/ui/bool_stream_button.dart b/example/lib/ui/bool_stream_button.dart index bd1dd0a5a..8c4514879 100644 --- a/example/lib/ui/bool_stream_button.dart +++ b/example/lib/ui/bool_stream_button.dart @@ -38,11 +38,10 @@ class BoolStreamButton extends StatelessWidget { @override Widget build(BuildContext context) => StreamBuilder( - stream: (streams != null) ? combineStreams(streams!) : stream, - builder: (context, snapshot) => TextButton( - onPressed: - (snapshot.hasData && snapshot.data == true) ? onPressed : null, - child: child, - ), - ); + stream: (streams != null) ? combineStreams(streams!) : stream, + builder: (context, snapshot) => TextButton( + onPressed: (snapshot.hasData && snapshot.data == true) ? onPressed : null, + child: child, + ), + ); } diff --git a/example/lib/ui/paginated_result_viewer.dart b/example/lib/ui/paginated_result_viewer.dart index 8be6538ca..417f31729 100644 --- a/example/lib/ui/paginated_result_viewer.dart +++ b/example/lib/ui/paginated_result_viewer.dart @@ -24,8 +24,9 @@ class PaginatedResultViewer extends HookWidget { }) : super(key: key); Future getFirstPaginatedResult( - ValueNotifier?> currentPaginatedResult, - ValueNotifier pageNumber) async { + ValueNotifier?> currentPaginatedResult, + ValueNotifier pageNumber, + ) async { final result = await query(); firstPaginatedResult = result; currentPaginatedResult.value = result; @@ -43,9 +44,9 @@ class PaginatedResultViewer extends HookWidget { return; } if (pageNumber.value == 1) { - currentPaginatedResult.value! - .first() - .then((result) => currentPaginatedResult.value = result); + currentPaginatedResult.value!.first().then( + (result) => currentPaginatedResult.value = result, + ); } else if (currentPaginatedResult.value!.hasNext()) { currentPaginatedResult.value!.next().then((result) { currentPaginatedResult.value = result; @@ -73,7 +74,7 @@ class PaginatedResultViewer extends HookWidget { onPressed: () => getFirstPaginatedResult(currentPaginatedResult, pageNumber), icon: const Icon(Icons.refresh), - ) + ), ], ), if (subtitle != null) @@ -88,19 +89,22 @@ class PaginatedResultViewer extends HookWidget { children: (items.isEmpty) ? [const Text('No messages')] : items - .map((item) => Padding( + .map( + (item) => Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: builder(context, item, null), - )) - .toList(), + ), + ) + .toList(), ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ TextRow('Page', '#${pageNumber.value}'), TextButton( - onPressed: - pageNumber.value != 1 ? () => pageNumber.value = 1 : null, + onPressed: pageNumber.value != 1 + ? () => pageNumber.value = 1 + : null, child: const Text('Go to first page'), ), TextButton( @@ -112,7 +116,7 @@ class PaginatedResultViewer extends HookWidget { child: const Text('Next page'), ), ], - ) + ), ], ); } diff --git a/example/lib/ui/push_notifications/push_notifications_activation_sliver.dart b/example/lib/ui/push_notifications/push_notifications_activation_sliver.dart index 3d7725a8a..16c7c5279 100644 --- a/example/lib/ui/push_notifications/push_notifications_activation_sliver.dart +++ b/example/lib/ui/push_notifications/push_notifications_activation_sliver.dart @@ -15,20 +15,23 @@ class PushNotificationsActivationSliver extends HookWidget { const PushNotificationsActivationSliver({ required PushNotificationService pushNotificationService, Key? key, - }) : _pushNotificationService = pushNotificationService, - super(key: key); + }) : _pushNotificationService = pushNotificationService, + super(key: key); Future showErrorDialog( - BuildContext context, ably.AblyException error) async { + BuildContext context, + ably.AblyException error, + ) async { await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Push notification error'), - content: - Text('Failed to perform operation on push notification service. ' - 'Please verify your push notification setup with Readme ' - 'files in the ably-flutter repository.\n\n' - '${error.errorInfo?.message}'), + content: Text( + 'Failed to perform operation on push notification service. ' + 'Please verify your push notification setup with Readme ' + 'files in the ably-flutter repository.\n\n' + '${error.errorInfo?.message}', + ), ), ); } @@ -66,16 +69,25 @@ class PushNotificationsActivationSliver extends HookWidget { return Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: RichText( - text: const TextSpan(children: [ - TextSpan( - text: 'Warning: ', - style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold)), - TextSpan( - text: 'APNs is not available on iOS simulators, so you cannot ' - 'activate the device Ably, since this step requires the' - ' APNs device token.', - style: TextStyle(color: Colors.black)) - ])), + text: const TextSpan( + children: [ + TextSpan( + text: 'Warning: ', + style: TextStyle( + color: Colors.red, + fontWeight: FontWeight.bold, + ), + ), + TextSpan( + text: + 'APNs is not available on iOS simulators, so you cannot ' + 'activate the device Ably, since this step requires the' + ' APNs device token.', + style: TextStyle(color: Colors.black), + ), + ], + ), + ), ); } else { return const SizedBox.shrink(); @@ -87,9 +99,9 @@ class PushNotificationsActivationSliver extends HookWidget { final isIOSSimulator = useState(false); useEffect(() { if (Platform.isIOS) { - DeviceInfoPlugin() - .iosInfo - .then((info) => isIOSSimulator.value = !info.isPhysicalDevice); + DeviceInfoPlugin().iosInfo.then( + (info) => isIOSSimulator.value = !info.isPhysicalDevice, + ); } return; }); @@ -108,29 +120,34 @@ class PushNotificationsActivationSliver extends HookWidget { children: [ Expanded( child: BoolStreamButton( - stream: _pushNotificationService.hasPushChannelStream, - onPressed: () => handleActivateDeviceButton(context), - child: const Text('Activate device')), + stream: _pushNotificationService.hasPushChannelStream, + onPressed: () => handleActivateDeviceButton(context), + child: const Text('Activate device'), + ), ), Expanded( child: BoolStreamButton( - stream: _pushNotificationService.hasPushChannelStream, - onPressed: () => handleDeactivateDeviceButton(context), - child: const Text('Deactivate device')), + stream: _pushNotificationService.hasPushChannelStream, + onPressed: () => handleDeactivateDeviceButton(context), + child: const Text('Deactivate device'), + ), ), Expanded( child: BoolStreamButton( - stream: _pushNotificationService.hasPushChannelStream, - onPressed: () => handleResetDeviceButton(context), - child: const Text('Reset activation')), - ) + stream: _pushNotificationService.hasPushChannelStream, + onPressed: () => handleResetDeviceButton(context), + child: const Text('Reset activation'), + ), + ), ], ), - const Text('Once devices are activated, a Push Admin can ' - "send push messages to devices by it's device ID, client ID or " - 'FCM/ APNs token. To send push messages between users, the ' - 'device must push-subscribe to the channel and a push payload ' - 'is added to the channel message.'), + const Text( + 'Once devices are activated, a Push Admin can ' + "send push messages to devices by it's device ID, client ID or " + 'FCM/ APNs token. To send push messages between users, the ' + 'device must push-subscribe to the channel and a push payload ' + 'is added to the channel message.', + ), ], ), ); @@ -139,20 +156,24 @@ class PushNotificationsActivationSliver extends HookWidget { Future showPermissionReminder(BuildContext context) async { if (Platform.isIOS) { final authorizationStatus = _pushNotificationService - .notificationSettingsStream.value.authorizationStatus; + .notificationSettingsStream + .value + .authorizationStatus; if (authorizationStatus == ably.UNAuthorizationStatus.notDetermined) { await showDialog( context: context, builder: (context) => CupertinoAlertDialog( title: const Text('Reminder for the developer'), content: const Text( - 'You should request permission to show notifications to the ' - 'user or a provisional permissions.'), + 'You should request permission to show notifications to the ' + 'user or a provisional permissions.', + ), actions: [ CupertinoDialogAction( onPressed: () { _pushNotificationService.requestNotificationPermission( - provisional: true); + provisional: true, + ); Navigator.pop(context); }, child: const Text('Request provisional permission'), @@ -173,12 +194,13 @@ class PushNotificationsActivationSliver extends HookWidget { ); } else if (authorizationStatus == ably.UNAuthorizationStatus.denied) { await Fluttertoast.showToast( - msg: 'The user has previously denied notifications from this app.', - toastLength: Toast.LENGTH_LONG, - gravity: ToastGravity.CENTER, - backgroundColor: Colors.red, - textColor: Colors.white, - fontSize: 16); + msg: 'The user has previously denied notifications from this app.', + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.CENTER, + backgroundColor: Colors.red, + textColor: Colors.white, + fontSize: 16, + ); } } } diff --git a/example/lib/ui/push_notifications/push_notifications_device_information.dart b/example/lib/ui/push_notifications/push_notifications_device_information.dart index a4e85652b..4b5b7dd64 100644 --- a/example/lib/ui/push_notifications/push_notifications_device_information.dart +++ b/example/lib/ui/push_notifications/push_notifications_device_information.dart @@ -9,56 +9,67 @@ class PushNotificationsDeviceInformation extends StatelessWidget { const PushNotificationsDeviceInformation({ required PushNotificationService pushNotificationService, Key? key, - }) : _pushNotificationService = pushNotificationService, - super(key: key); + }) : _pushNotificationService = pushNotificationService, + super(key: key); @override Widget build(BuildContext context) => Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const Text( - 'Local Device information', - style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), - ), - StreamBuilder( - stream: _pushNotificationService.localDeviceStream, - builder: (context, snapshot) { - if (snapshot.hasData && snapshot.data != null) { - final localDevice = snapshot.data!; - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - TextRow('deviceId', localDevice.id), - TextRow('clientId', localDevice.clientId), - TextRow('platform', localDevice.platform.toString()), - TextRow('formFactor', localDevice.formFactor.toString()), - TextRow('metadata', localDevice.metadata.toString()), - TextRow('DevicePushDetails state', - localDevice.push.state.toString()), - TextRow('DevicePushDetails recipient', - '${localDevice.push.recipient}'), - TextButton( - onPressed: _pushNotificationService.getDevice, - child: const Text('Refresh local device information'), - ), - ], - ); - } - return RichText( - text: const TextSpan(children: [ + padding: const EdgeInsets.symmetric(vertical: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const Text( + 'Local Device information', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + ), + StreamBuilder( + stream: _pushNotificationService.localDeviceStream, + builder: (context, snapshot) { + if (snapshot.hasData && snapshot.data != null) { + final localDevice = snapshot.data!; + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + TextRow('deviceId', localDevice.id), + TextRow('clientId', localDevice.clientId), + TextRow('platform', localDevice.platform.toString()), + TextRow('formFactor', localDevice.formFactor.toString()), + TextRow('metadata', localDevice.metadata.toString()), + TextRow( + 'DevicePushDetails state', + localDevice.push.state.toString(), + ), + TextRow( + 'DevicePushDetails recipient', + '${localDevice.push.recipient}', + ), + TextButton( + onPressed: _pushNotificationService.getDevice, + child: const Text('Refresh local device information'), + ), + ], + ); + } + return RichText( + text: const TextSpan( + children: [ TextSpan( - text: 'Warning: ', - style: TextStyle( - color: Colors.red, fontWeight: FontWeight.bold)), + text: 'Warning: ', + style: TextStyle( + color: Colors.red, + fontWeight: FontWeight.bold, + ), + ), TextSpan( - text: 'no local device information yet.', - style: TextStyle(color: Colors.black)) - ])); - }, - ), - ], + text: 'no local device information yet.', + style: TextStyle(color: Colors.black), + ), + ], + ), + ); + }, ), - ); + ], + ), + ); } diff --git a/example/lib/ui/push_notifications/push_notifications_ios_permissions_sliver.dart b/example/lib/ui/push_notifications/push_notifications_ios_permissions_sliver.dart index 54b985a57..79aee074d 100644 --- a/example/lib/ui/push_notifications/push_notifications_ios_permissions_sliver.dart +++ b/example/lib/ui/push_notifications/push_notifications_ios_permissions_sliver.dart @@ -13,8 +13,8 @@ class PushNotificationsIOSNotificationSettingsSliver extends StatelessWidget { const PushNotificationsIOSNotificationSettingsSliver({ required PushNotificationService pushNotificationService, Key? key, - }) : _pushNotificationService = pushNotificationService, - super(key: key); + }) : _pushNotificationService = pushNotificationService, + super(key: key); Widget buildIOSPermissionSliver() { if (Platform.isIOS) { @@ -42,15 +42,18 @@ class PushNotificationsIOSNotificationSettingsSliver extends StatelessWidget { stream: _pushNotificationService.hasPushChannelStream, onPressed: () { _pushNotificationService.requestNotificationPermission( - provisional: true); + provisional: true, + ); Fluttertoast.showToast( - msg: 'Notifications will be delivered silently to ' - 'the notification center.', - toastLength: Toast.LENGTH_LONG, - gravity: ToastGravity.CENTER, - backgroundColor: Colors.red, - textColor: Colors.white, - fontSize: 16); + msg: + 'Notifications will be delivered silently to ' + 'the notification center.', + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.CENTER, + backgroundColor: Colors.red, + textColor: Colors.white, + fontSize: 16, + ); }, child: const Text('Request Provisional Permission (no alert)'), ); @@ -80,22 +83,32 @@ class PushNotificationsIOSNotificationSettingsSliver extends StatelessWidget { 'iOS Notification Settings', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), - TextRow('Authorization Status', - '${settings.authorizationStatus}'), + TextRow( + 'Authorization Status', + '${settings.authorizationStatus}', + ), TextRow('Sound', '${settings.soundSetting}'), TextRow('Badge', '${settings.badgeSetting}'), TextRow('Alert', '${settings.alertSetting}'), - TextRow('Notification Center', - '${settings.notificationCenterSetting}'), + TextRow( + 'Notification Center', + '${settings.notificationCenterSetting}', + ), TextRow('Lock Screen', '${settings.lockScreenSetting}'), TextRow('Alert Style', '${settings.alertStyle}'), TextRow('Shows Preview', '${settings.showPreviewsSetting}'), TextRow( - 'Critical Alerts', '${settings.criticalAlertSetting}'), - TextRow('providesAppNotificationSettings', - '${settings.providesAppNotificationSettings}'), + 'Critical Alerts', + '${settings.criticalAlertSetting}', + ), TextRow( - 'Siri announcements', '${settings.announcementSetting}'), + 'providesAppNotificationSettings', + '${settings.providesAppNotificationSettings}', + ), + TextRow( + 'Siri announcements', + '${settings.announcementSetting}', + ), TextButton( onPressed: _pushNotificationService.updateNotificationSettings, @@ -114,9 +127,6 @@ class PushNotificationsIOSNotificationSettingsSliver extends StatelessWidget { @override Widget build(BuildContext context) => Column( - children: [ - buildIOSPermissionSliver(), - buildIOSNotificationSettings(), - ], - ); + children: [buildIOSPermissionSliver(), buildIOSNotificationSettings()], + ); } diff --git a/example/lib/ui/push_notifications/push_notifications_publishing_sliver.dart b/example/lib/ui/push_notifications/push_notifications_publishing_sliver.dart index d29e2ee8b..788b146a4 100644 --- a/example/lib/ui/push_notifications/push_notifications_publishing_sliver.dart +++ b/example/lib/ui/push_notifications/push_notifications_publishing_sliver.dart @@ -10,48 +10,49 @@ class PushNotificationsPublishingSliver extends StatelessWidget { const PushNotificationsPublishingSliver({ required PushNotificationService pushNotificationService, Key? key, - }) : _pushNotificationService = pushNotificationService, - super(key: key); + }) : _pushNotificationService = pushNotificationService, + super(key: key); @override Widget build(BuildContext context) => Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, + padding: const EdgeInsets.symmetric(vertical: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const Text( + 'Publishing to ' + '"${Constants.channelNameForPushNotifications}"', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + ), + const Padding( + padding: EdgeInsets.symmetric(vertical: 8), + child: Text( + 'Each message sent contains a push payload, ' + 'in the ably.Message.extras field.', + ), + ), + Row( children: [ - const Text( - 'Publishing to ' - '"${Constants.channelNameForPushNotifications}"', - style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), - ), - const Padding( - padding: EdgeInsets.symmetric(vertical: 8), - child: Text('Each message sent contains a push payload, ' - 'in the ably.Message.extras field.'), - ), - Row( - children: [ - BoolStreamButton( - stream: _pushNotificationService.hasPushChannelStream, - onPressed: _pushNotificationService - .publishNotificationMessageToChannel, - child: const Text('Notification Message'), - ), - BoolStreamButton( - stream: _pushNotificationService.hasPushChannelStream, - onPressed: - _pushNotificationService.publishDataMessageToChannel, - child: const Text('Data Message'), - ), - ], + BoolStreamButton( + stream: _pushNotificationService.hasPushChannelStream, + onPressed: + _pushNotificationService.publishNotificationMessageToChannel, + child: const Text('Notification Message'), ), BoolStreamButton( stream: _pushNotificationService.hasPushChannelStream, - onPressed: _pushNotificationService - .publishDataNotificationMessageToChannel, - child: const Text('Data + Notification Message'), + onPressed: _pushNotificationService.publishDataMessageToChannel, + child: const Text('Data Message'), ), ], ), - ); + BoolStreamButton( + stream: _pushNotificationService.hasPushChannelStream, + onPressed: + _pushNotificationService.publishDataNotificationMessageToChannel, + child: const Text('Data + Notification Message'), + ), + ], + ), + ); } diff --git a/example/lib/ui/push_notifications/push_notifications_received_sliver.dart b/example/lib/ui/push_notifications/push_notifications_received_sliver.dart index 1b5b9a663..1ba679589 100644 --- a/example/lib/ui/push_notifications/push_notifications_received_sliver.dart +++ b/example/lib/ui/push_notifications/push_notifications_received_sliver.dart @@ -4,60 +4,65 @@ import 'package:ably_flutter_example/ui/text_row.dart'; import 'package:flutter/material.dart'; class PushNotificationsReceivedSliver extends StatelessWidget { - const PushNotificationsReceivedSliver({ - Key? key, - }) : super(key: key); + const PushNotificationsReceivedSliver({Key? key}) : super(key: key); @override Widget build(BuildContext context) => Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + padding: const EdgeInsets.symmetric(vertical: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - const Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Received messages', - style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), - ), - IconButton( - onPressed: PushNotificationHandlers.clearReceivedMessages, - icon: Icon(Icons.delete)) - ], + Text( + 'Received messages', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + ), + IconButton( + onPressed: PushNotificationHandlers.clearReceivedMessages, + icon: Icon(Icons.delete), ), - StreamBuilder>( - stream: PushNotificationHandlers.receivedMessagesStream, - builder: (context, snapshot) { - if (!snapshot.hasData) { - return const Text('Widget not loaded yet.'); - } - final messages = snapshot.data; - if (messages!.isEmpty) { - return const Text('No messages yet'); - } else { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: messages - .map((e) => Padding( - padding: - const EdgeInsets.symmetric(vertical: 8), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TextRow('Notification Title', - e.notification?.title ?? 'NO TITLE'), - TextRow('Notification Body', - e.notification?.body ?? 'NO BODY'), - TextRow('Data', e.data.toString()), - ], - ), - )) - .toList(), - ); - } - }), ], ), - ); + StreamBuilder>( + stream: PushNotificationHandlers.receivedMessagesStream, + builder: (context, snapshot) { + if (!snapshot.hasData) { + return const Text('Widget not loaded yet.'); + } + final messages = snapshot.data; + if (messages!.isEmpty) { + return const Text('No messages yet'); + } else { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: messages + .map( + (e) => Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextRow( + 'Notification Title', + e.notification?.title ?? 'NO TITLE', + ), + TextRow( + 'Notification Body', + e.notification?.body ?? 'NO BODY', + ), + TextRow('Data', e.data.toString()), + ], + ), + ), + ) + .toList(), + ); + } + }, + ), + ], + ), + ); } diff --git a/example/lib/ui/push_notifications/push_notifications_sliver.dart b/example/lib/ui/push_notifications/push_notifications_sliver.dart index 0653c4d62..2da18dcf1 100644 --- a/example/lib/ui/push_notifications/push_notifications_sliver.dart +++ b/example/lib/ui/push_notifications/push_notifications_sliver.dart @@ -12,49 +12,51 @@ class PushNotificationsSliver extends StatelessWidget { final PushNotificationService _pushNotificationService; const PushNotificationsSliver(this._pushNotificationService, {Key? key}) - : super(key: key); + : super(key: key); @override Widget build(BuildContext context) => Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const Padding( - padding: EdgeInsets.only(bottom: 16), - child: Text( - 'Push Notifications', - style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), - ), - ), - buildSummaryText(), - PushNotificationsActivationSliver( - pushNotificationService: _pushNotificationService, - ), - PushNotificationsDeviceInformation( - pushNotificationService: _pushNotificationService, - ), - PushNotificationsIOSNotificationSettingsSliver( - pushNotificationService: _pushNotificationService, - ), - PushNotificationsSubscriptionsSliver( - pushNotificationService: _pushNotificationService, - ), - PushNotificationsPublishingSliver( - pushNotificationService: _pushNotificationService), - const PushNotificationsReceivedSliver(), - PushRealtimeClientReceivedSliver( - pushNotificationService: _pushNotificationService, - ), - ], - ); + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const Padding( + padding: EdgeInsets.only(bottom: 16), + child: Text( + 'Push Notifications', + style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), + ), + ), + buildSummaryText(), + PushNotificationsActivationSliver( + pushNotificationService: _pushNotificationService, + ), + PushNotificationsDeviceInformation( + pushNotificationService: _pushNotificationService, + ), + PushNotificationsIOSNotificationSettingsSliver( + pushNotificationService: _pushNotificationService, + ), + PushNotificationsSubscriptionsSliver( + pushNotificationService: _pushNotificationService, + ), + PushNotificationsPublishingSliver( + pushNotificationService: _pushNotificationService, + ), + const PushNotificationsReceivedSliver(), + PushRealtimeClientReceivedSliver( + pushNotificationService: _pushNotificationService, + ), + ], + ); Widget buildSummaryText() => const Column( - children: [ - Text( - 'Activate your device, view your local device information, ' - 'subscribe to a push channel with either your device or ' - 'client ID, and then publish to the channel.', - style: TextStyle(color: Colors.black)), - SizedBox(height: 16), - ], - ); + children: [ + Text( + 'Activate your device, view your local device information, ' + 'subscribe to a push channel with either your device or ' + 'client ID, and then publish to the channel.', + style: TextStyle(color: Colors.black), + ), + SizedBox(height: 16), + ], + ); } diff --git a/example/lib/ui/push_notifications/push_notifications_subscriptions_sliver.dart b/example/lib/ui/push_notifications/push_notifications_subscriptions_sliver.dart index f8b395bc5..4f0f684a6 100644 --- a/example/lib/ui/push_notifications/push_notifications_subscriptions_sliver.dart +++ b/example/lib/ui/push_notifications/push_notifications_subscriptions_sliver.dart @@ -11,166 +11,186 @@ class PushNotificationsSubscriptionsSliver extends StatelessWidget { const PushNotificationsSubscriptionsSliver({ required PushNotificationService pushNotificationService, Key? key, - }) : _pushNotificationService = pushNotificationService, - super(key: key); + }) : _pushNotificationService = pushNotificationService, + super(key: key); Widget buildSubscriptionsList( - Stream> stream) => - StreamBuilder>( - stream: stream, - builder: (context, snapshot) { - if (snapshot.hasData) { - final subscriptions = snapshot.data - as ably.PaginatedResult; + Stream> stream, + ) => StreamBuilder>( + stream: stream, + builder: (context, snapshot) { + if (snapshot.hasData) { + final subscriptions = + snapshot.data as ably.PaginatedResult; - if (subscriptions.items.isEmpty) { - return const Text('No subscriptions'); - } + if (subscriptions.items.isEmpty) { + return const Text('No subscriptions'); + } - final theresMoreSubscriptionsWidget = subscriptions.hasNext() - ? const Text('and more...') - : const SizedBox.shrink(); + final theresMoreSubscriptionsWidget = subscriptions.hasNext() + ? const Text('and more...') + : const SizedBox.shrink(); - return Column(children: [ - ...subscriptions.items - .map( - (e) => Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Container( - color: Colors.grey[200], - child: Column(children: [ - Text('Channel: ${e.channel}'), - if (e.deviceId != null) - Text('DeviceId: ${e.deviceId!}') - else - Text('ClientId: ${e.clientId}'), - ]), - ), + return Column( + children: [ + ...subscriptions.items + .map( + (e) => Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Container( + color: Colors.grey[200], + child: Column( + children: [ + Text('Channel: ${e.channel}'), + if (e.deviceId != null) + Text('DeviceId: ${e.deviceId!}') + else + Text('ClientId: ${e.clientId}'), + ], ), - ) - .toList(), - theresMoreSubscriptionsWidget - ]); - } - return const Text('List subscription button not pressed.'); - }); + ), + ), + ) + .toList(), + theresMoreSubscriptionsWidget, + ], + ); + } + return const Text('List subscription button not pressed.'); + }, + ); @override Widget build(BuildContext context) => Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, + padding: const EdgeInsets.symmetric(vertical: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const Padding( + padding: EdgeInsets.only(bottom: 8), + child: Text( + 'Push channel subscriptions', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + ), + ), + const Text( + 'You need to use a token/ key with the Push Admin capability ' + 'to list subscriptions by client ID or device ID. ' + 'If you subscribe both device and client to the channel, ' + 'the device will receive 2 notifications.', + ), + Row( children: [ - const Padding( - padding: EdgeInsets.only(bottom: 8), - child: Text( - 'Push channel subscriptions', - style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + Expanded( + child: BoolStreamButton( + stream: _pushNotificationService.hasPushChannelStream, + onPressed: () async { + try { + await _pushNotificationService.subscribeDevice(); + } on ably.AblyException catch (ablyException) { + await showPushActivationError(context, ablyException); + } + }, + child: const Text('Subscribe device'), ), ), - const Text( - 'You need to use a token/ key with the Push Admin capability ' - 'to list subscriptions by client ID or device ID. ' - 'If you subscribe both device and client to the channel, ' - 'the device will receive 2 notifications.'), - Row( - children: [ - Expanded( - child: BoolStreamButton( - stream: _pushNotificationService.hasPushChannelStream, - onPressed: () async { - try { - await _pushNotificationService.subscribeDevice(); - } on ably.AblyException catch (ablyException) { - await showPushActivationError(context, ablyException); - } - }, - child: const Text('Subscribe device')), - ), - Expanded( - child: BoolStreamButton( - stream: _pushNotificationService.hasPushChannelStream, - onPressed: () async { - try { - await _pushNotificationService.unsubscribeDevice(); - } on ably.AblyException catch (ablyException) { - await showPushActivationError(context, ablyException); - } - }, - child: const Text('Unsubscribe device'), - ), - ), - ], + Expanded( + child: BoolStreamButton( + stream: _pushNotificationService.hasPushChannelStream, + onPressed: () async { + try { + await _pushNotificationService.unsubscribeDevice(); + } on ably.AblyException catch (ablyException) { + await showPushActivationError(context, ablyException); + } + }, + child: const Text('Unsubscribe device'), + ), ), - BoolStreamButton( + ], + ), + BoolStreamButton( + stream: _pushNotificationService.hasPushChannelStream, + onPressed: () async { + final subscriptions = await _pushNotificationService + .listSubscriptionsWithDeviceId(); + print('Push subscriptions: ${subscriptions.items}'); + }, + child: const Text('List subscriptions with current device ID'), + ), + buildSubscriptionsList( + _pushNotificationService.pushChannelDeviceSubscriptionsStream, + ), + Row( + children: [ + Expanded( + child: BoolStreamButton( stream: _pushNotificationService.hasPushChannelStream, onPressed: () async { - final subscriptions = await _pushNotificationService - .listSubscriptionsWithDeviceId(); - print('Push subscriptions: ${subscriptions.items}'); + try { + await _pushNotificationService.subscribeClient(); + } on ably.AblyException catch (ablyException) { + await showPushActivationError(context, ablyException); + } }, - child: const Text('List subscriptions with current device ID')), - buildSubscriptionsList( - _pushNotificationService.pushChannelDeviceSubscriptionsStream), - Row( - children: [ - Expanded( - child: BoolStreamButton( - stream: _pushNotificationService.hasPushChannelStream, - onPressed: () async { - try { - await _pushNotificationService.subscribeClient(); - } on ably.AblyException catch (ablyException) { - await showPushActivationError(context, ablyException); - } - }, - child: const Text('Subscribe client')), - ), - Expanded( - child: BoolStreamButton( - stream: _pushNotificationService.hasPushChannelStream, - onPressed: () async { - try { - await _pushNotificationService.unsubscribeClient(); - } on ably.AblyException catch (ablyException) { - await showPushActivationError(context, ablyException); - } - }, - child: const Text('Unsubscribe client')), - ) - ], + child: const Text('Subscribe client'), + ), ), - BoolStreamButton( + Expanded( + child: BoolStreamButton( stream: _pushNotificationService.hasPushChannelStream, onPressed: () async { - final subscriptions = await _pushNotificationService - .listSubscriptionsWithClientId(); - print('Push subscriptions: ${subscriptions.items}'); + try { + await _pushNotificationService.unsubscribeClient(); + } on ably.AblyException catch (ablyException) { + await showPushActivationError(context, ablyException); + } }, - child: const Text('List subscriptions with current client ID')), - buildSubscriptionsList( - _pushNotificationService.pushChannelClientSubscriptionsStream), - buildWarningTextForListSubscriptionsOnAndroid(), + child: const Text('Unsubscribe client'), + ), + ), ], ), - ); + BoolStreamButton( + stream: _pushNotificationService.hasPushChannelStream, + onPressed: () async { + final subscriptions = await _pushNotificationService + .listSubscriptionsWithClientId(); + print('Push subscriptions: ${subscriptions.items}'); + }, + child: const Text('List subscriptions with current client ID'), + ), + buildSubscriptionsList( + _pushNotificationService.pushChannelClientSubscriptionsStream, + ), + buildWarningTextForListSubscriptionsOnAndroid(), + ], + ), + ); Widget buildWarningTextForListSubscriptionsOnAndroid() { if (Platform.isAndroid) { return Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: RichText( - text: - const TextSpan(style: TextStyle(color: Colors.black), children: [ - TextSpan( + text: const TextSpan( + style: TextStyle(color: Colors.black), + children: [ + TextSpan( text: 'Warning: ', - style: - TextStyle(color: Colors.red, fontWeight: FontWeight.bold)), - TextSpan( - text: 'A bug in ably-java means all client ID and device ' + style: TextStyle( + color: Colors.red, + fontWeight: FontWeight.bold, + ), + ), + TextSpan( + text: + 'A bug in ably-java means all client ID and device ' 'ID subscriptions are returned when you call ' - 'push.listSubscriptions. Track ably-java issue #705'), - ]), + 'push.listSubscriptions. Track ably-java issue #705', + ), + ], + ), ), ); } @@ -180,16 +200,16 @@ class PushNotificationsSubscriptionsSliver extends StatelessWidget { Future showPushActivationError( BuildContext context, ably.AblyException exception, - ) async => - showDialog( - context: context, - builder: (context) => AlertDialog( - title: const Text('Push notification error'), - content: - Text('Failed to perform operation on push notification service. ' - 'Please verify your push notification setup with Readme ' - 'files in the ably-flutter repository.\n\n' - '${exception.errorInfo?.message}'), - ), - ); + ) async => showDialog( + context: context, + builder: (context) => AlertDialog( + title: const Text('Push notification error'), + content: Text( + 'Failed to perform operation on push notification service. ' + 'Please verify your push notification setup with Readme ' + 'files in the ably-flutter repository.\n\n' + '${exception.errorInfo?.message}', + ), + ), + ); } diff --git a/example/lib/ui/push_notifications/push_realtime_client_received_sliver.dart b/example/lib/ui/push_notifications/push_realtime_client_received_sliver.dart index 84a66804e..cdf8539e7 100644 --- a/example/lib/ui/push_notifications/push_realtime_client_received_sliver.dart +++ b/example/lib/ui/push_notifications/push_realtime_client_received_sliver.dart @@ -9,35 +9,44 @@ class PushRealtimeClientReceivedSliver extends StatelessWidget { const PushRealtimeClientReceivedSliver({ required PushNotificationService pushNotificationService, Key? key, - }) : _pushNotificationService = pushNotificationService, - super(key: key); + }) : _pushNotificationService = pushNotificationService, + super(key: key); @override Widget build(BuildContext context) => Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Column( - children: [ - const Text( - 'Debugging messages (via realtime client)', - style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), - ), - const Text('To validate messages were sent, you can subscribe to ' - 'the channel and view the device logs.'), - BoolStreamButton( - stream: _pushNotificationService.hasPushChannelStream, - onPressed: _pushNotificationService - .subscribeToChannelWithPushChannelRule, - child: const Text('Subscribe to channel: ' - '"${Constants.channelNameForPushNotifications}"')), - const Text('To debug push notifications, ' - 'subscribe to the meta channel.'), - BoolStreamButton( - stream: _pushNotificationService.hasPushChannelStream, - onPressed: - _pushNotificationService.subscribeToPushLogMetachannel, - child: const Text('Subscribe to push metachannel: ' - '${Constants.pushMetaChannelName}')), - ], + padding: const EdgeInsets.symmetric(vertical: 8), + child: Column( + children: [ + const Text( + 'Debugging messages (via realtime client)', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), - ); + const Text( + 'To validate messages were sent, you can subscribe to ' + 'the channel and view the device logs.', + ), + BoolStreamButton( + stream: _pushNotificationService.hasPushChannelStream, + onPressed: + _pushNotificationService.subscribeToChannelWithPushChannelRule, + child: const Text( + 'Subscribe to channel: ' + '"${Constants.channelNameForPushNotifications}"', + ), + ), + const Text( + 'To debug push notifications, ' + 'subscribe to the meta channel.', + ), + BoolStreamButton( + stream: _pushNotificationService.hasPushChannelStream, + onPressed: _pushNotificationService.subscribeToPushLogMetachannel, + child: const Text( + 'Subscribe to push metachannel: ' + '${Constants.pushMetaChannelName}', + ), + ), + ], + ), + ); } diff --git a/example/lib/ui/realtime_presence_sliver.dart b/example/lib/ui/realtime_presence_sliver.dart index de5531e75..2be2778f3 100644 --- a/example/lib/ui/realtime_presence_sliver.dart +++ b/example/lib/ui/realtime_presence_sliver.dart @@ -23,47 +23,48 @@ class RealtimePresenceSliver extends HookWidget { ValueNotifier latestMessage, ably.ChannelState? channelState, ValueNotifier?> - presenceSubscription, - ) => - TextButton( - onPressed: (channelState == ably.ChannelState.attached && - presenceSubscription.value == null) - ? () { - final presenceMessageStream = channel.presence.subscribe(); - final subscription = - presenceMessageStream.listen((presenceMessage) { - latestMessage.value = presenceMessage; - }); - presenceSubscription.value = subscription; - _subscriptions.add(subscription); - } - : null, - child: const Text('Subscribe'), - ); + presenceSubscription, + ) => TextButton( + onPressed: + (channelState == ably.ChannelState.attached && + presenceSubscription.value == null) + ? () { + final presenceMessageStream = channel.presence.subscribe(); + final subscription = presenceMessageStream.listen(( + presenceMessage, + ) { + latestMessage.value = presenceMessage; + }); + presenceSubscription.value = subscription; + _subscriptions.add(subscription); + } + : null, + child: const Text('Subscribe'), + ); Widget createChannelPresenceUnsubscribeButton( ValueNotifier?> - presenceSubscription, - ) => - TextButton( - onPressed: (presenceSubscription.value != null) - ? () async { - await presenceSubscription.value!.cancel(); - presenceSubscription.value = null; - } - : null, - child: const Text('Unsubscribe'), - ); + presenceSubscription, + ) => TextButton( + onPressed: (presenceSubscription.value != null) + ? () async { + await presenceSubscription.value!.cancel(); + presenceSubscription.value = null; + } + : null, + child: const Text('Unsubscribe'), + ); Widget getRealtimeChannelPresence( - ValueNotifier> presenceMembers) => - TextButton( - onPressed: () async { - presenceMembers.value = - await channel.presence.get(const ably.RealtimePresenceParams()); - }, - child: const Text('Get Realtime presence members'), + ValueNotifier> presenceMembers, + ) => TextButton( + onPressed: () async { + presenceMembers.value = await channel.presence.get( + const ably.RealtimePresenceParams(), ); + }, + child: const Text('Get Realtime presence members'), + ); final List _presenceData = [ null, @@ -74,10 +75,10 @@ class RealtimePresenceSliver extends HookWidget { 1, 'ably', null, - {'a': 'b'} + {'a': 'b'}, ], { - 'c': ['a', 'b'] + 'c': ['a', 'b'], }, ]; @@ -88,26 +89,28 @@ class RealtimePresenceSliver extends HookWidget { .toString(); Widget enterRealtimePresence() => TextButton( - onPressed: () async { - await channel.presence.enter(_nextPresenceData); - }, - child: const Text('Enter'), - ); + onPressed: () async { + await channel.presence.enter(_nextPresenceData); + }, + child: const Text('Enter'), + ); Widget updateRealtimePresence() => TextButton( - onPressed: () async { - await channel.presence - .updateClient(Constants.clientId, _nextPresenceData); - }, - child: const Text('Update'), + onPressed: () async { + await channel.presence.updateClient( + Constants.clientId, + _nextPresenceData, ); + }, + child: const Text('Update'), + ); Widget leaveRealtimePresence() => TextButton( - onPressed: () async { - await channel.presence.leave(_nextPresenceData); - }, - child: const Text('Leave'), - ); + onPressed: () async { + await channel.presence.leave(_nextPresenceData); + }, + child: const Text('Leave'), + ); @override Widget build(BuildContext context) { @@ -128,11 +131,17 @@ class RealtimePresenceSliver extends HookWidget { Row( children: [ Expanded( - child: createChannelPresenceSubscribeButton( - latestMessage, channel.state, presenceSubscription)), + child: createChannelPresenceSubscribeButton( + latestMessage, + channel.state, + presenceSubscription, + ), + ), Expanded( - child: createChannelPresenceUnsubscribeButton( - presenceSubscription)), + child: createChannelPresenceUnsubscribeButton( + presenceSubscription, + ), + ), ], ), Text( @@ -141,15 +150,9 @@ class RealtimePresenceSliver extends HookWidget { ), Row( children: [ - Expanded( - child: enterRealtimePresence(), - ), - Expanded( - child: updateRealtimePresence(), - ), - Expanded( - child: leaveRealtimePresence(), - ), + Expanded(child: enterRealtimePresence()), + Expanded(child: updateRealtimePresence()), + Expanded(child: leaveRealtimePresence()), ], ), getRealtimeChannelPresence(presenceMembers), @@ -157,11 +160,14 @@ class RealtimePresenceSliver extends HookWidget { .map((m) => Text('${m.id}:${m.clientId}:${m.data}')) .toList(), PaginatedResultViewer( - title: 'Presence history', - query: () => channel.presence - .history(ably.RealtimeHistoryParams(limit: 10)), - builder: (context, message, _) => TextRow('clientId', - '${message.id}:${message.clientId}:${message.data}')), + title: 'Presence history', + query: () => + channel.presence.history(ably.RealtimeHistoryParams(limit: 10)), + builder: (context, message, _) => TextRow( + 'clientId', + '${message.id}:${message.clientId}:${message.data}', + ), + ), ], ), ); diff --git a/example/lib/ui/realtime_sliver.dart b/example/lib/ui/realtime_sliver.dart index 1f02e0849..e3b98f75d 100644 --- a/example/lib/ui/realtime_sliver.dart +++ b/example/lib/ui/realtime_sliver.dart @@ -18,8 +18,8 @@ class RealtimeSliver extends HookWidget { List> _subscriptions = []; RealtimeSliver(this.ablyService, {Key? key}) - : realtime = ablyService.realtime, - super(key: key) { + : realtime = ablyService.realtime, + super(key: key) { channel = realtime.channels.get(Constants.channelName); } @@ -30,70 +30,71 @@ class RealtimeSliver extends HookWidget { _subscriptions = []; } - Widget buildConnectButton() => TextButton( - onPressed: realtime.connect, - child: const Text('Connect'), - ); + Widget buildConnectButton() => + TextButton(onPressed: realtime.connect, child: const Text('Connect')); Widget buildDisconnectButton(ably.ConnectionState state) => TextButton( - onPressed: - (state == ably.ConnectionState.connected) ? realtime.close : null, - child: const Text('Disconnect'), - ); + onPressed: (state == ably.ConnectionState.connected) + ? realtime.close + : null, + child: const Text('Disconnect'), + ); - Widget buildChannelAttachButton(ably.ConnectionState connectionState, - ably.ChannelState channelState) => - TextButton( - onPressed: (connectionState == ably.ConnectionState.connected && - channelState != ably.ChannelState.attached) - ? () async { - try { - await channel.attach(); - } on ably.AblyException catch (e) { - print('Unable to attach to channel: ${e.errorInfo}'); - } - } - : null, - child: const Text('Attach'), - ); + Widget buildChannelAttachButton( + ably.ConnectionState connectionState, + ably.ChannelState channelState, + ) => TextButton( + onPressed: + (connectionState == ably.ConnectionState.connected && + channelState != ably.ChannelState.attached) + ? () async { + try { + await channel.attach(); + } on ably.AblyException catch (e) { + print('Unable to attach to channel: ${e.errorInfo}'); + } + } + : null, + child: const Text('Attach'), + ); Widget buildChannelDetachButton(ably.ChannelState channelState) => TextButton( - onPressed: (channelState == ably.ChannelState.attached) - ? channel.detach - : null, - child: const Text('Detach'), - ); + onPressed: (channelState == ably.ChannelState.attached) + ? channel.detach + : null, + child: const Text('Detach'), + ); Widget buildChannelSubscribeButton( - ably.ChannelState channelState, - ValueNotifier latestMessage, - ValueNotifier?> - channelSubscription) => - TextButton( - onPressed: (channelState == ably.ChannelState.attached && - channelSubscription.value == null) - ? () { - final subscription = channel.subscribe().listen((message) { - latestMessage.value = message; - }); - channelSubscription.value = subscription; - _subscriptions.add(subscription); - } - : null, - child: const Text('Subscribe'), - ); + ably.ChannelState channelState, + ValueNotifier latestMessage, + ValueNotifier?> channelSubscription, + ) => TextButton( + onPressed: + (channelState == ably.ChannelState.attached && + channelSubscription.value == null) + ? () { + final subscription = channel.subscribe().listen((message) { + latestMessage.value = message; + }); + channelSubscription.value = subscription; + _subscriptions.add(subscription); + } + : null, + child: const Text('Subscribe'), + ); Widget buildChannelUnsubscribeButton( - ValueNotifier?> channelSubscription) => - TextButton( - onPressed: (channelSubscription.value != null) - ? () async { - await channelSubscription.value!.cancel(); - channelSubscription.value = null; - } - : null, - child: const Text('Unsubscribe'), - ); + ValueNotifier?> channelSubscription, + ) => TextButton( + onPressed: (channelSubscription.value != null) + ? () async { + await channelSubscription.value!.cancel(); + channelSubscription.value = null; + } + : null, + child: const Text('Unsubscribe'), + ); int typeCounter = 0; int realtimePubCounter = 0; @@ -102,15 +103,20 @@ class RealtimeSliver extends HookWidget { TextButton( onPressed: (channelState == ably.ChannelState.attached) ? () async { - final data = _messagesToPublish[ - (realtimePubCounter++ % _messagesToPublish.length)]; + final data = + _messagesToPublish[(realtimePubCounter++ % + _messagesToPublish.length)]; final m = ably.Message( - name: 'Message $realtimePubCounter', data: data); + name: 'Message $realtimePubCounter', + data: data, + ); try { switch (typeCounter % 3) { case 0: await channel.publish( - name: 'Message $realtimePubCounter', data: data); + name: 'Message $realtimePubCounter', + data: data, + ); break; case 1: await channel.publish(message: m); @@ -127,9 +133,7 @@ class RealtimeSliver extends HookWidget { } } : null, - child: const Text( - 'Publish', - ), + child: const Text('Publish'), ); Widget buildReleaseRealtimeChannelButton( @@ -137,55 +141,53 @@ class RealtimeSliver extends HookWidget { ValueNotifier channelState, ValueNotifier connectionId, ValueNotifier recoveryKey, - ) => - TextButton( - onPressed: () async { - await channel.detach(); - realtime.channels.release(Constants.channelName); - channel = realtime.channels.get(Constants.channelName); - setupListeners( - connectionState, channelState, connectionId, recoveryKey); - }, - child: const Text('Release'), - ); + ) => TextButton( + onPressed: () async { + await channel.detach(); + realtime.channels.release(Constants.channelName); + channel = realtime.channels.get(Constants.channelName); + setupListeners(connectionState, channelState, connectionId, recoveryKey); + }, + child: const Text('Release'), + ); Widget buildEncryptionSwitch(ValueNotifier isEnabled) => Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Enable encryption', - style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), - ), - Switch( - onChanged: (switchedOn) async { - isEnabled.value = switchedOn; - if (switchedOn) { - await channel.setOptions( - await ably.RealtimeChannelOptions.withCipherKey( - keyFromPassword( - Constants.examplePasswordForEncryptedChannel, - ), - ), - ); - } else { - await channel.setOptions(const ably.RealtimeChannelOptions()); - } - }, - value: isEnabled.value, - ), - ], - ); + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Enable encryption', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + ), + Switch( + onChanged: (switchedOn) async { + isEnabled.value = switchedOn; + if (switchedOn) { + await channel.setOptions( + await ably.RealtimeChannelOptions.withCipherKey( + keyFromPassword(Constants.examplePasswordForEncryptedChannel), + ), + ); + } else { + await channel.setOptions(const ably.RealtimeChannelOptions()); + } + }, + value: isEnabled.value, + ), + ], + ); @override Widget build(BuildContext context) { - final connectionState = - useState(realtime.connection.state); + final connectionState = useState( + realtime.connection.state, + ); final connectionId = useState(realtime.connection.id); final recoveryKey = useState(''); final channelState = useState(channel.state); final latestMessage = useState(null); - final channelSubscription = - useState?>(null); + final channelSubscription = useState?>( + null, + ); final realtimeTime = useState(null); final useEncryption = useState(false); @@ -209,12 +211,8 @@ class RealtimeSliver extends HookWidget { buildEncryptionSwitch(useEncryption), Row( children: [ - Expanded( - child: buildConnectButton(), - ), - Expanded( - child: buildDisconnectButton(connectionState.value), - ) + Expanded(child: buildConnectButton()), + Expanded(child: buildDisconnectButton(connectionState.value)), ], ), const Text( @@ -225,94 +223,109 @@ class RealtimeSliver extends HookWidget { Row( children: [ Expanded( - child: buildChannelAttachButton( - connectionState.value, channelState.value)), + child: buildChannelAttachButton( + connectionState.value, + channelState.value, + ), + ), Expanded(child: buildChannelDetachButton(channelState.value)), Expanded( - child: buildReleaseRealtimeChannelButton( - connectionState, channelState, connectionId, recoveryKey)), + child: buildReleaseRealtimeChannelButton( + connectionState, + channelState, + connectionId, + recoveryKey, + ), + ), ], ), Row( children: [ Expanded( - child: buildChannelSubscribeButton( - channelState.value, latestMessage, channelSubscription)), + child: buildChannelSubscribeButton( + channelState.value, + latestMessage, + channelSubscription, + ), + ), Expanded(child: buildChannelPublishButton(channelState.value)), Expanded(child: buildChannelUnsubscribeButton(channelSubscription)), ], ), TextRow( - 'Latest message received', latestMessage.value?.data.toString()), + 'Latest message received', + latestMessage.value?.data.toString(), + ), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const TextRow('Next message to be published:', null), TextRow(' Name', 'Message $realtimePubCounter'), TextRow( - ' Data', - _messagesToPublish[ - realtimePubCounter % _messagesToPublish.length] - .toString()), + ' Data', + _messagesToPublish[realtimePubCounter % _messagesToPublish.length] + .toString(), + ), ], ), - RealtimePresenceSliver( - realtime: realtime, - channel: channel, - ), + RealtimePresenceSliver(realtime: realtime, channel: channel), PaginatedResultViewer( - title: 'History', - subtitle: const Column( - children: [ - TextRow( - 'Hint', - 'Use realtime history as a way to get messages that were' - ' published before you are attached to the channel.'), - TextRow( - 'Warning', - 'If you are already attached to the channel, you must' - ' detach and re-attach to get the latest messages ' - 'published on the channel to get history whilst ' - 'connected to a realtime channel, use ' - 'RestChannel.history instead.'), - ], - ), - query: () => channel.history( - ably.RealtimeHistoryParams( - limit: 10, - untilAttach: true, - ), - ), - builder: (context, message, _) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TextRow('Name', message.name), - TextRow('Data', message.data.toString()), - ], - )), + title: 'History', + subtitle: const Column( + children: [ + TextRow( + 'Hint', + 'Use realtime history as a way to get messages that were' + ' published before you are attached to the channel.', + ), + TextRow( + 'Warning', + 'If you are already attached to the channel, you must' + ' detach and re-attach to get the latest messages ' + 'published on the channel to get history whilst ' + 'connected to a realtime channel, use ' + 'RestChannel.history instead.', + ), + ], + ), + query: () => channel.history( + ably.RealtimeHistoryParams(limit: 10, untilAttach: true), + ), + builder: (context, message, _) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextRow('Name', message.name), + TextRow('Data', message.data.toString()), + ], + ), + ), ], ); } void setupListeners( - ValueNotifier connectionState, - ValueNotifier channelState, - ValueNotifier connectionId, - ValueNotifier recoveryKey) { + ValueNotifier connectionState, + ValueNotifier channelState, + ValueNotifier connectionId, + ValueNotifier recoveryKey, + ) { dispose(); - final connectionSubscription = - realtime.connection.on().listen((connectionStateChange) { + final connectionSubscription = realtime.connection.on().listen(( + connectionStateChange, + ) { if (connectionStateChange.current == ably.ConnectionState.failed) { logAndDisplayError(connectionStateChange.reason); } connectionState.value = connectionStateChange.current; connectionId.value = realtime.connection.id; - realtime.connection - .createRecoveryKey() - .then((value) => {recoveryKey.value = value}); - print('${DateTime.now()}:' - ' ConnectionStateChange event: ${connectionStateChange.event}' - '\nReason: ${connectionStateChange.reason}'); + realtime.connection.createRecoveryKey().then( + (value) => {recoveryKey.value = value}, + ); + print( + '${DateTime.now()}:' + ' ConnectionStateChange event: ${connectionStateChange.event}' + '\nReason: ${connectionStateChange.reason}', + ); }); _subscriptions.add(connectionSubscription); final channelSubscription = channel.on().listen((stateChange) { @@ -329,8 +342,8 @@ List _messagesToPublish = [ 'I am': null, 'and': { 'also': 'nested', - 'too': {'deep': true} - } + 'too': {'deep': true}, + }, }, [ 42, @@ -341,8 +354,8 @@ List _messagesToPublish = [ 'I am': null, 'and': { 'also': 'nested', - 'too': {'deep': true} - } - } - ] + 'too': {'deep': true}, + }, + }, + ], ]; diff --git a/example/lib/ui/rest_sliver.dart b/example/lib/ui/rest_sliver.dart index 3776057a9..95ad91039 100644 --- a/example/lib/ui/rest_sliver.dart +++ b/example/lib/ui/rest_sliver.dart @@ -16,51 +16,52 @@ class RestSliver extends HookWidget { } Widget buildPublishButton( - ValueNotifier messageCount, String messageName) => - TextButton( - onPressed: () async { - try { - await channel.publish( - name: messageName, data: 'Some data for $messageName'); - messageCount.value += 1; - } on ably.AblyException catch (e) { - print('Rest message sending failed:: $e :: ${e.errorInfo}'); - } - }, - child: const Text('Publish'), - ); + ValueNotifier messageCount, + String messageName, + ) => TextButton( + onPressed: () async { + try { + await channel.publish( + name: messageName, + data: 'Some data for $messageName', + ); + messageCount.value += 1; + } on ably.AblyException catch (e) { + print('Rest message sending failed:: $e :: ${e.errorInfo}'); + } + }, + child: const Text('Publish'), + ); Widget buildReleaseChannelButton() => TextButton( - onPressed: () => rest.channels.release(Constants.channelName), - child: const Text('Release channel'), - ); + onPressed: () => rest.channels.release(Constants.channelName), + child: const Text('Release channel'), + ); Widget buildEncryptionSwitch(ValueNotifier isEnabled) => Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Enable encryption', - style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), - ), - Switch( - onChanged: (switchedOn) async { - isEnabled.value = switchedOn; - if (switchedOn) { - await channel.setOptions( - await ably.RestChannelOptions.withCipherKey( - keyFromPassword( - Constants.examplePasswordForEncryptedChannel, - ), - ), - ); - } else { - await channel.setOptions(ably.RestChannelOptions()); - } - }, - value: isEnabled.value, - ), - ], - ); + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Enable encryption', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + ), + Switch( + onChanged: (switchedOn) async { + isEnabled.value = switchedOn; + if (switchedOn) { + await channel.setOptions( + await ably.RestChannelOptions.withCipherKey( + keyFromPassword(Constants.examplePasswordForEncryptedChannel), + ), + ); + } else { + await channel.setOptions(ably.RestChannelOptions()); + } + }, + value: isEnabled.value, + ), + ], + ); @override Widget build(BuildContext context) { @@ -87,42 +88,46 @@ class RestSliver extends HookWidget { Row( children: [ Expanded( - child: buildPublishButton(messageCount, messageName.value)), + child: buildPublishButton(messageCount, messageName.value), + ), Expanded(child: buildReleaseChannelButton()), ], ), TextRow('Next message', messageName.value), PaginatedResultViewer( - title: 'History', - query: () => channel.history(ably.RestHistoryParams( - direction: 'forwards', - limit: 10, - )), - builder: (context, message, _) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TextRow('Name', message.name), - TextRow('Data', message.data.toString()), - ], - )), + title: 'History', + query: () => channel.history( + ably.RestHistoryParams(direction: 'forwards', limit: 10), + ), + builder: (context, message, _) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextRow('Name', message.name), + TextRow('Data', message.data.toString()), + ], + ), + ), PaginatedResultViewer( - title: 'Presence members', - query: () => - channel.presence.get(ably.RestPresenceParams(limit: 10)), - builder: (context, message, _) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TextRow('Message ID', '${message.id}'), - TextRow('Message client ID', '${message.clientId}'), - TextRow('Message data', '${message.data}'), - ], - )), + title: 'Presence members', + query: () => channel.presence.get(ably.RestPresenceParams(limit: 10)), + builder: (context, message, _) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextRow('Message ID', '${message.id}'), + TextRow('Message client ID', '${message.clientId}'), + TextRow('Message data', '${message.data}'), + ], + ), + ), PaginatedResultViewer( - title: 'Presence history', - query: () => - channel.presence.history(ably.RestHistoryParams(limit: 10)), - builder: (context, message, _) => TextRow('Message name', - '${message.id}:${message.clientId}:${message.data}')), + title: 'Presence history', + query: () => + channel.presence.history(ably.RestHistoryParams(limit: 10)), + builder: (context, message, _) => TextRow( + 'Message name', + '${message.id}:${message.clientId}:${message.data}', + ), + ), ], ); } diff --git a/example/lib/ui/system_details_sliver.dart b/example/lib/ui/system_details_sliver.dart index eabe0ad88..99dab4ab5 100644 --- a/example/lib/ui/system_details_sliver.dart +++ b/example/lib/ui/system_details_sliver.dart @@ -9,10 +9,8 @@ import 'package:flutter_hooks/flutter_hooks.dart'; class SystemDetailsSliver extends HookWidget { ApiKeyProvision apiKeyProvision; - SystemDetailsSliver({ - required this.apiKeyProvision, - Key? key, - }) : super(key: key); + SystemDetailsSliver({required this.apiKeyProvision, Key? key}) + : super(key: key); @override Widget build(BuildContext context) { @@ -39,19 +37,24 @@ class SystemDetailsSliver extends HookWidget { if (apiKeyProvision.source != ApiKeySource.env) RichText( text: const TextSpan( - style: TextStyle(color: Colors.black), - children: [ - TextSpan( - text: 'Warning: ', - style: TextStyle( - color: Colors.red, fontWeight: FontWeight.bold)), - TextSpan( - text: 'Ably API key is not configured! Application uses ' - 'auto-provisioned sandbox key. Please follow ' - 'instructions in the repository Readme file to ' - 'setup the sample with your API key.', - ) - ]), + style: TextStyle(color: Colors.black), + children: [ + TextSpan( + text: 'Warning: ', + style: TextStyle( + color: Colors.red, + fontWeight: FontWeight.bold, + ), + ), + TextSpan( + text: + 'Ably API key is not configured! Application uses ' + 'auto-provisioned sandbox key. Please follow ' + 'instructions in the repository Readme file to ' + 'setup the sample with your API key.', + ), + ], + ), ), ], ); diff --git a/example/lib/ui/text_row.dart b/example/lib/ui/text_row.dart index b70e7bf42..88da9fe45 100644 --- a/example/lib/ui/text_row.dart +++ b/example/lib/ui/text_row.dart @@ -10,8 +10,17 @@ class TextRow extends StatelessWidget { @override Widget build(BuildContext context) => RichText( - text: TextSpan(children: [ - TextSpan(text: '$label: ', style: const TextStyle(color: Colors.blue)), - TextSpan(text: text, style: const TextStyle(color: Colors.black)) - ])); + text: TextSpan( + children: [ + TextSpan( + text: '$label: ', + style: const TextStyle(color: Colors.blue), + ), + TextSpan( + text: text, + style: const TextStyle(color: Colors.black), + ), + ], + ), + ); } diff --git a/example/lib/ui/utilities.dart b/example/lib/ui/utilities.dart index c3926cfe6..76abc0c47 100644 --- a/example/lib/ui/utilities.dart +++ b/example/lib/ui/utilities.dart @@ -6,20 +6,24 @@ import 'package:crypto/crypto.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; -void logAndDisplayError(ably.ErrorInfo? errorInfo, - {String prefixMessage = ' '}) { +void logAndDisplayError( + ably.ErrorInfo? errorInfo, { + String prefixMessage = ' ', +}) { if (errorInfo == null) { return; } print(errorInfo.message); Fluttertoast.showToast( - msg: 'Error: $prefixMessage. ' - '${errorInfo.message ?? 'No error message provided'}', - toastLength: Toast.LENGTH_LONG, - gravity: ToastGravity.CENTER, - backgroundColor: Colors.red, - textColor: Colors.white, - fontSize: 16); + msg: + 'Error: $prefixMessage. ' + '${errorInfo.message ?? 'No error message provided'}', + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.CENTER, + backgroundColor: Colors.red, + textColor: Colors.white, + fontSize: 16, + ); } // This is a quick way to create a key from a password. In production, diff --git a/example/pubspec.lock b/example/pubspec.lock index 8e79682cc..77ff86524 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -28,10 +28,10 @@ packages: dependency: transitive description: name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" clock: dependency: transitive description: @@ -190,18 +190,18 @@ packages: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "0.13.0" meta: dependency: transitive description: name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + sha256: "307249ce4ff29d58a18e97f6345f539382eb9c9c29ecda628900f31de0443dd9" url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.19.0" path: dependency: transitive description: @@ -299,10 +299,10 @@ packages: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: f36f9f3be64c6198714492bb455c11056e33e2f85d9a0b676a48301e44fdcf47 url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.4.2" web: dependency: transitive description: @@ -344,5 +344,5 @@ packages: source: hosted version: "6.5.0" sdks: - dart: ">=3.7.0-0 <4.0.0" - flutter: ">=3.24.0" + dart: ">=3.12.0 <4.0.0" + flutter: ">=3.44.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index bedd473e4..6570a2316 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the Ably Flutter plugin. publish_to: "none" environment: - sdk: ">=3.3.0 <4.0.0" - flutter: "3.24.0" + sdk: ">=3.12.0 <4.0.0" + flutter: ">=3.44.0" dependencies: flutter: @@ -28,4 +28,10 @@ dev_dependencies: flutter_lints: ^1.0.4 flutter: + # Flutter 3.44 turns Swift Package Manager on by default, and building this + # app would migrate its Xcode project off CocoaPods on the spot. Hold that + # off so the migration can land as its own reviewable commit rather than as + # a side effect of a version bump. + config: + enable-swift-package-manager: false uses-material-design: true diff --git a/ios/ably_flutter.podspec b/ios/ably_flutter.podspec index 37f36835d..659909e0e 100644 --- a/ios/ably_flutter.podspec +++ b/ios/ably_flutter.podspec @@ -20,7 +20,8 @@ Pod::Spec.new do |s| s.dependency 'Flutter' s.dependency 'Ably', '1.2.53' s.platform = :ios - s.ios.deployment_target = '10.0' + # UIScene, and therefore `FlutterSceneLifeCycleDelegate`, is iOS 13+ only. + s.ios.deployment_target = '13.0' # Flutter 3.x ships both arm64 and x86_64 simulator slices; no arch restriction needed. s.pod_target_xcconfig = { diff --git a/lib/src/authentication/src/auth_options.dart b/lib/src/authentication/src/auth_options.dart index feb3bce91..ee59776ec 100644 --- a/lib/src/authentication/src/auth_options.dart +++ b/lib/src/authentication/src/auth_options.dart @@ -82,8 +82,8 @@ class AuthOptions { /// then the Ably Token issued is [anonymous](https://ably.com/docs/core-features/authentication#identified-clients). bool? useTokenAuth; -// TODO(tiholic) missing token attribute here -// see: https://docs.ably.com/client-lib-development-guide/features/#AO2h + // TODO(tiholic) missing token attribute here + // see: https://docs.ably.com/client-lib-development-guide/features/#AO2h /// @nodoc /// Initializes an instance without any defaults diff --git a/lib/src/authentication/src/client_options.dart b/lib/src/authentication/src/client_options.dart index a0bcf46cc..b0db956ac 100644 --- a/lib/src/authentication/src/client_options.dart +++ b/lib/src/authentication/src/client_options.dart @@ -199,16 +199,16 @@ class ClientOptions extends AuthOptions { bool? useBinaryProtocol, bool? useTokenAuth, }) : super( - authCallback: authCallback, - authUrl: authUrl, - authMethod: authMethod, - key: key, - tokenDetails: tokenDetails, - authHeaders: authHeaders, - authParams: authParams, - queryTime: queryTime, - useTokenAuth: useTokenAuth, - ) { + authCallback: authCallback, + authUrl: authUrl, + authMethod: authMethod, + key: key, + tokenDetails: tokenDetails, + authHeaders: authHeaders, + authParams: authParams, + queryTime: queryTime, + useTokenAuth: useTokenAuth, + ) { /// @nodoc /// These default value assignments are only required until /// [ClientOptions.fromKey] is removed, because then defaults can be set @@ -236,16 +236,17 @@ class ClientOptions extends AuthOptions { /// /// See [AuthOptions.fromKey] for more details @Deprecated( - "Use ClientOptions constructor with named 'key' parameter instead") + "Use ClientOptions constructor with named 'key' parameter instead", + ) ClientOptions.fromKey(String key) : super.fromKey(key); -// TODO(tiholic) unimplemented: -// -// (TO3m) logExceptionReportingUrl -// (TO3l6) httpMaxRetryDuration -// (TO3l8) maxMessageSize -// (TO3l9) maxFrameSize -// (TO3o) plugins -// (TO3p) addRequestIds -// (DF1a) connectionStateTtl + // TODO(tiholic) unimplemented: + // + // (TO3m) logExceptionReportingUrl + // (TO3l6) httpMaxRetryDuration + // (TO3l8) maxMessageSize + // (TO3l9) maxFrameSize + // (TO3o) plugins + // (TO3p) addRequestIds + // (DF1a) connectionStateTtl } diff --git a/lib/src/authentication/src/token_details.dart b/lib/src/authentication/src/token_details.dart index b5f2c4f5b..e73bdc59c 100644 --- a/lib/src/authentication/src/token_details.dart +++ b/lib/src/authentication/src/token_details.dart @@ -56,9 +56,9 @@ class TokenDetails { /// Ably ensures that all fields are consistently serialized and deserialized /// across platforms. TokenDetails.fromMap(Map map) - : capability = map['capability'] as String?, - clientId = map['clientId'] as String?, - expires = map['expires'] as int?, - issued = map['issued'] as int?, - token = map['token'] as String?; + : capability = map['capability'] as String?, + clientId = map['clientId'] as String?, + expires = map['expires'] as int?, + issued = map['issued'] as int?, + token = map['token'] as String?; } diff --git a/lib/src/authentication/src/token_request.dart b/lib/src/authentication/src/token_request.dart index fdb1cae65..c2ac8d84f 100644 --- a/lib/src/authentication/src/token_request.dart +++ b/lib/src/authentication/src/token_request.dart @@ -67,12 +67,11 @@ class TokenRequest { /// Ably ensures that all fields are consistently serialized and deserialized /// across platforms. TokenRequest.fromMap(Map map) - : capability = map['capability'] as String?, - clientId = map['clientId'] as String?, - mac = map['mac'] as String?, - nonce = map['nonce'] as String?, - timestamp = - DateTime.fromMillisecondsSinceEpoch(map['timestamp'] as int), - ttl = map['ttl'] as int?, - keyName = map['keyName'] as String?; + : capability = map['capability'] as String?, + clientId = map['clientId'] as String?, + mac = map['mac'] as String?, + nonce = map['nonce'] as String?, + timestamp = DateTime.fromMillisecondsSinceEpoch(map['timestamp'] as int), + ttl = map['ttl'] as int?, + keyName = map['keyName'] as String?; } diff --git a/lib/src/crypto/src/crypto.dart b/lib/src/crypto/src/crypto.dart index e0b619b80..11fb59908 100644 --- a/lib/src/crypto/src/crypto.dart +++ b/lib/src/crypto/src/crypto.dart @@ -34,17 +34,17 @@ class Crypto { } else if (key is Uint8List) { ensureSupportedKeyLength(key); } else { - throw AblyException( - message: 'key must be a String or Uint8List.', - ); + throw AblyException(message: 'key must be a String or Uint8List.'); } return Platform().invokePlatformMethodNonNull( PlatformMethod.cryptoGetParams, - AblyMessage(message: { - TxCryptoGetParams.algorithm: defaultAlgorithm, - TxCryptoGetParams.key: key, - }), + AblyMessage( + message: { + TxCryptoGetParams.algorithm: defaultAlgorithm, + TxCryptoGetParams.key: key, + }, + ), ); } @@ -54,9 +54,7 @@ class Crypto { static void ensureSupportedKeyLength(Uint8List key) { if (key.length != keyLength256bits / 8 && key.length != keyLength128bits / 8) { - throw AblyException( - message: 'Key must be 256 bits or 128 bits long.', - ); + throw AblyException(message: 'Key must be 256 bits or 128 bits long.'); } } @@ -68,11 +66,8 @@ class Crypto { /// default algorithm: for AES this is 256 bits. static Future generateRandomKey({ int keyLength = defaultKeyLengthInBits, - }) => - Platform().invokePlatformMethodNonNull( - PlatformMethod.cryptoGenerateRandomKey, - AblyMessage(message: { - TxCryptoGenerateRandomKey.keyLength: keyLength, - }), - ); + }) => Platform().invokePlatformMethodNonNull( + PlatformMethod.cryptoGenerateRandomKey, + AblyMessage(message: {TxCryptoGenerateRandomKey.keyLength: keyLength}), + ); } diff --git a/lib/src/error/src/ably_exception.dart b/lib/src/error/src/ably_exception.dart index 99cb21a45..a90cd1241 100644 --- a/lib/src/error/src/ably_exception.dart +++ b/lib/src/error/src/ably_exception.dart @@ -17,17 +17,13 @@ class AblyException implements Exception { final ErrorInfo? errorInfo; /// initializes with no defaults - AblyException({ - this.code, - this.errorInfo, - this.message, - }); + AblyException({this.code, this.errorInfo, this.message}); /// create AblyException from [PlatformException] AblyException.fromPlatformException(PlatformException exception) - : code = exception.code, - errorInfo = exception.details as ErrorInfo?, - message = exception.message; + : code = exception.code, + errorInfo = exception.details as ErrorInfo?, + message = exception.message; @override String toString() { diff --git a/lib/src/error/src/error_info.dart b/lib/src/error/src/error_info.dart index c5686b90c..190ba5897 100644 --- a/lib/src/error/src/error_info.dart +++ b/lib/src/error/src/error_info.dart @@ -36,7 +36,8 @@ class ErrorInfo { }); @override - String toString() => 'ErrorInfo' + String toString() => + 'ErrorInfo' ' message=$message' ' code=$code' ' statusCode=$statusCode' diff --git a/lib/src/logging/src/log_handler.dart b/lib/src/logging/src/log_handler.dart index 2b4d003e9..6f5602235 100644 --- a/lib/src/logging/src/log_handler.dart +++ b/lib/src/logging/src/log_handler.dart @@ -10,7 +10,4 @@ import 'package:ably_flutter/ably_flutter.dart'; 'All usages of this type are marked as deprecated ' 'so it will be removed in a future release.', ) -typedef LogHandler = void Function({ - String? msg, - AblyException? exception, -}); +typedef LogHandler = void Function({String? msg, AblyException? exception}); diff --git a/lib/src/message/src/delta_extras.dart b/lib/src/message/src/delta_extras.dart index 12ddeceb3..2d44dc839 100644 --- a/lib/src/message/src/delta_extras.dart +++ b/lib/src/message/src/delta_extras.dart @@ -17,16 +17,13 @@ class DeltaExtras with ObjectHash { /// create instance from a map @protected DeltaExtras.fromMap(Map value) - : format = value[TxDeltaExtras.format] as String?, - from = value[TxDeltaExtras.from] as String?; + : format = value[TxDeltaExtras.format] as String?, + from = value[TxDeltaExtras.from] as String?; @override bool operator ==(Object other) => other is DeltaExtras && other.from == from && other.format == format; @override - int get hashCode => objectHash([ - from, - format, - ]); + int get hashCode => objectHash([from, format]); } diff --git a/lib/src/message/src/message.dart b/lib/src/message/src/message.dart index d63cae59a..8beded649 100644 --- a/lib/src/message/src/message.dart +++ b/lib/src/message/src/message.dart @@ -61,15 +61,15 @@ class Message with ObjectHash { @override int get hashCode => objectHash([ - id, - name, - encoding, - clientId, - timestamp, - connectionId, - data, - extras, - ]); + id, + name, + encoding, + clientId, + timestamp, + connectionId, + data, + extras, + ]); // https://docs.ably.com/client-lib-development-guide/features/#TM3 // @@ -84,22 +84,20 @@ class Message with ObjectHash { Message.fromEncoded( Map jsonObject, [ RestChannelOptions? channelOptions, - ]) : clientId = jsonObject['clientId'] as String?, - connectionId = jsonObject['connectionId'] as String?, - _data = MessageData.fromValue(jsonObject['data']), - encoding = jsonObject['encoding'] as String?, - extras = MessageExtras.fromMap( - Map.castFrom( - jsonObject['extras'] as Map, - ), - ), - id = jsonObject['id'] as String?, - name = jsonObject['name'] as String?, - timestamp = jsonObject['timestamp'] != null - ? DateTime.fromMillisecondsSinceEpoch( - jsonObject['timestamp'] as int, - ) - : null; + ]) : clientId = jsonObject['clientId'] as String?, + connectionId = jsonObject['connectionId'] as String?, + _data = MessageData.fromValue(jsonObject['data']), + encoding = jsonObject['encoding'] as String?, + extras = MessageExtras.fromMap( + Map.castFrom( + jsonObject['extras'] as Map, + ), + ), + id = jsonObject['id'] as String?, + name = jsonObject['name'] as String?, + timestamp = jsonObject['timestamp'] != null + ? DateTime.fromMillisecondsSinceEpoch(jsonObject['timestamp'] as int) + : null; /// A static factory method to create an array of Message objects from an /// [jsonArray] of deserialized Message-like object encoded using Ably's wire @@ -108,11 +106,11 @@ class Message with ObjectHash { static List fromEncodedArray( List> jsonArray, [ RestChannelOptions? channelOptions, - ]) => - jsonArray.map((e) => Message.fromEncoded(e, channelOptions)).toList(); + ]) => jsonArray.map((e) => Message.fromEncoded(e, channelOptions)).toList(); @override - String toString() => 'Message' + String toString() => + 'Message' ' id=$id' ' name=$name' ' data=$data' @@ -122,5 +120,5 @@ class Message with ObjectHash { ' timestamp=$timestamp' ' connectionId=$connectionId'; -// TODO(tiholic) add support for fromEncoded and fromEncodedArray (TM3) + // TODO(tiholic) add support for fromEncoded and fromEncodedArray (TM3) } diff --git a/lib/src/message/src/message_data.dart b/lib/src/message/src/message_data.dart index 327e81ce3..e6ffdfadc 100644 --- a/lib/src/message/src/message_data.dart +++ b/lib/src/message/src/message_data.dart @@ -8,7 +8,7 @@ class MessageData { /// /// Only Map, List, string and Buffer types are supported. MessageData(this._data) - : assert(T == Map || T == List || T == String || T == Uint8List); + : assert(T == Map || T == List || T == String || T == Uint8List); /// A getter for the [_data] object. T get data => _data; diff --git a/lib/src/message/src/message_extras.dart b/lib/src/message/src/message_extras.dart index 59c139047..d04237778 100644 --- a/lib/src/message/src/message_extras.dart +++ b/lib/src/message/src/message_extras.dart @@ -37,10 +37,7 @@ class MessageExtras with ObjectHash { ? null : DeltaExtras.fromMap(Map.from(deltaMap)); - return MessageExtras._withDelta( - mutableExtrasMap, - deltaExtras, - ); + return MessageExtras._withDelta(mutableExtrasMap, deltaExtras); } @override @@ -53,8 +50,5 @@ class MessageExtras with ObjectHash { other.delta == delta; @override - int get hashCode => objectHash([ - map, - delta, - ]); + int get hashCode => objectHash([map, delta]); } diff --git a/lib/src/message/src/presence_message.dart b/lib/src/message/src/presence_message.dart index e7b25c526..31a4a1a10 100644 --- a/lib/src/message/src/presence_message.dart +++ b/lib/src/message/src/presence_message.dart @@ -68,15 +68,15 @@ class PresenceMessage with ObjectHash { @override int get hashCode => objectHash([ - id, - encoding, - clientId, - timestamp, - connectionId, - data, - action, - extras, - ]); + id, + encoding, + clientId, + timestamp, + connectionId, + data, + action, + extras, + ]); // https://docs.ably.com/client-lib-development-guide/features/#TP4 // @@ -93,23 +93,22 @@ class PresenceMessage with ObjectHash { PresenceMessage.fromEncoded( Map jsonObject, [ RestChannelOptions? channelOptions, - ]) : id = jsonObject['id'] as String?, - action = PresenceAction.values.firstWhere((e) => - e.toString().split('.')[1] == jsonObject['action'] as String?), - clientId = jsonObject['clientId'] as String?, - connectionId = jsonObject['connectionId'] as String?, - _data = MessageData.fromValue(jsonObject['data']), - encoding = jsonObject['encoding'] as String?, - extras = MessageExtras.fromMap( - Map.castFrom( - jsonObject['extras'] as Map, - ), - ), - timestamp = jsonObject['timestamp'] != null - ? DateTime.fromMillisecondsSinceEpoch( - jsonObject['timestamp'] as int, - ) - : null; + ]) : id = jsonObject['id'] as String?, + action = PresenceAction.values.firstWhere( + (e) => e.toString().split('.')[1] == jsonObject['action'] as String?, + ), + clientId = jsonObject['clientId'] as String?, + connectionId = jsonObject['connectionId'] as String?, + _data = MessageData.fromValue(jsonObject['data']), + encoding = jsonObject['encoding'] as String?, + extras = MessageExtras.fromMap( + Map.castFrom( + jsonObject['extras'] as Map, + ), + ), + timestamp = jsonObject['timestamp'] != null + ? DateTime.fromMillisecondsSinceEpoch(jsonObject['timestamp'] as int) + : null; /// Decodes and decrypts a [jsonArray] of deserialized PresenceMessage-like /// object using the cipher in [channelOptions]. @@ -121,16 +120,15 @@ class PresenceMessage with ObjectHash { static List fromEncodedArray( List> jsonArray, [ RestChannelOptions? channelOptions, - ]) => - jsonArray - .map((jsonObject) => PresenceMessage.fromEncoded( - jsonObject, - channelOptions, - )) - .toList(); + ]) => jsonArray + .map( + (jsonObject) => PresenceMessage.fromEncoded(jsonObject, channelOptions), + ) + .toList(); @override - String toString() => 'PresenceMessage' + String toString() => + 'PresenceMessage' ' id=$id' ' data=$data' ' action=$action' diff --git a/lib/src/platform/src/ably_event_message.dart b/lib/src/platform/src/ably_event_message.dart index 607233642..4086c76fb 100644 --- a/lib/src/platform/src/ably_event_message.dart +++ b/lib/src/platform/src/ably_event_message.dart @@ -16,8 +16,5 @@ class AblyEventMessage { /// creates an instance with non-nul [eventName] /// /// [message] is optional - const AblyEventMessage({ - required this.eventName, - this.message, - }); + const AblyEventMessage({required this.eventName, this.message}); } diff --git a/lib/src/platform/src/ably_message.dart b/lib/src/platform/src/ably_message.dart index 6588d80ba..4cc7531e2 100644 --- a/lib/src/platform/src/ably_message.dart +++ b/lib/src/platform/src/ably_message.dart @@ -21,31 +21,20 @@ class AblyMessage { /// creates instance with a non-null [message] /// /// [handle] and [type] are optional - const AblyMessage({ - required this.message, - this.handle, - this.type, - }); + const AblyMessage({required this.message, this.handle, this.type}); /// @nodoc /// creates instance with [message] set to empty map /// /// [handle] and [type] are optional - static AblyMessage> empty({ - int? handle, - int? type, - }) => - AblyMessage( - message: const {}, - handle: handle, - type: type, - ); + static AblyMessage> empty({int? handle, int? type}) => + AblyMessage(message: const {}, handle: handle, type: type); /// @nodoc /// Cast ably message from [G] to [T] static AblyMessage castFrom(AblyMessage source) => AblyMessage( - message: source.message as T, - handle: source.handle, - type: source.type, - ); + message: source.message as T, + handle: source.handle, + type: source.type, + ); } diff --git a/lib/src/platform/src/background_android_isolate_platform.dart b/lib/src/platform/src/background_android_isolate_platform.dart index cf743b3b5..f8cf6cc58 100644 --- a/lib/src/platform/src/background_android_isolate_platform.dart +++ b/lib/src/platform/src/background_android_isolate_platform.dart @@ -23,7 +23,9 @@ class BackgroundIsolateAndroidPlatform { return _onPushBackgroundMessage(call.arguments as RemoteMessage); default: throw PlatformException( - code: 'invalid_method', message: 'No such method ${call.method}'); + code: 'invalid_method', + message: 'No such method ${call.method}', + ); } }); } @@ -40,7 +42,9 @@ class BackgroundIsolateAndroidPlatform { /// we explicitly launched when a RemoteMessage is received. /// Used only on Android. final MethodChannel _methodChannel = MethodChannel( - 'io.ably.flutter.plugin.background', StandardMethodCodec(Codec())); + 'io.ably.flutter.plugin.background', + StandardMethodCodec(Codec()), + ); final PushNotificationEventsInternal _pushNotificationEvents = Push.notificationEvents as PushNotificationEventsInternal; diff --git a/lib/src/platform/src/cipher_params_internal.dart b/lib/src/platform/src/cipher_params_internal.dart index 6543a864e..cb2695a98 100644 --- a/lib/src/platform/src/cipher_params_internal.dart +++ b/lib/src/platform/src/cipher_params_internal.dart @@ -33,18 +33,14 @@ class CipherParamsInternal implements CipherParams { /// @nodoc /// Create a Dart side representation of CipherParams for iOS devices - CipherParamsInternal.forIOS({ - required this.algorithm, - required this.key, - }) { + CipherParamsInternal.forIOS({required this.algorithm, required this.key}) { if (!io.Platform.isIOS) { - throw AblyException( - message: 'This method is for iOS platforms only', - ); + throw AblyException(message: 'This method is for iOS platforms only'); } if (key == null) { throw AblyException( - message: 'CipherParamsNative on iOS must have a key, as ' + message: + 'CipherParamsNative on iOS must have a key, as ' 'this key is used to regenerate the ARTCipherParams on the ' 'iOS side.', ); @@ -53,15 +49,14 @@ class CipherParamsInternal implements CipherParams { /// @nodoc /// Create a Dart side representation of CipherParams for Android devices - CipherParamsInternal.forAndroid({ - required this.androidHandle, - }) { + CipherParamsInternal.forAndroid({required this.androidHandle}) { if (!io.Platform.isAndroid) { throw AblyException(message: 'This method is for Android platforms only'); } if (androidHandle == null) { throw AblyException( - message: 'CipherParamsNative on Android must have a handle, ' + message: + 'CipherParamsNative on Android must have a handle, ' 'as this key is used to get the previously generated ' 'CipherParams on the Android side', ); diff --git a/lib/src/platform/src/codec.dart b/lib/src/platform/src/codec.dart index 953d7d5b7..09518e63c 100644 --- a/lib/src/platform/src/codec.dart +++ b/lib/src/platform/src/codec.dart @@ -27,12 +27,10 @@ class _CodecPair { /// This method will throw an [AblyException] if encoder is null. Map? encode(final Object? value) { if (_encoder == null) { - throw AblyException( - message: 'Codec encoder is null', - ); + throw AblyException(message: 'Codec encoder is null'); } if (value == null) return null; - return _encoder!(value as T); + return _encoder(value as T); } /// @nodoc @@ -41,12 +39,10 @@ class _CodecPair { /// This method will throw an [AblyException] if decoder is null. T? decode(Map? jsonMap) { if (_decoder == null) { - throw AblyException( - message: 'Codec decoder is null', - ); + throw AblyException(message: 'Codec decoder is null'); } if (jsonMap == null) return null; - return _decoder!(jsonMap); + return _decoder(jsonMap); } } @@ -66,52 +62,84 @@ class Codec extends StandardMessageCodec { codecMap = { // Ably flutter plugin protocol message CodecTypes.ablyMessage: _CodecPair>( - _encodeAblyMessage, _decodeAblyMessage), - CodecTypes.ablyEventMessage: - _CodecPair(_encodeAblyEventMessage, null), + _encodeAblyMessage, + _decodeAblyMessage, + ), + CodecTypes.ablyEventMessage: _CodecPair( + _encodeAblyEventMessage, + null, + ), // Other ably objects - CodecTypes.clientOptions: - _CodecPair(_encodeClientOptions, _decodeClientOptions), - CodecTypes.tokenParams: - _CodecPair(_encodeTokenParams, _decodeTokenParams), - CodecTypes.tokenDetails: - _CodecPair(_encodeTokenDetails, _decodeTokenDetails), - CodecTypes.tokenRequest: - _CodecPair(_encodeTokenRequest, _decodeTokenRequest), - CodecTypes.restChannelOptions: - _CodecPair(_encodeRestChannelOptions, null), + CodecTypes.clientOptions: _CodecPair( + _encodeClientOptions, + _decodeClientOptions, + ), + CodecTypes.tokenParams: _CodecPair( + _encodeTokenParams, + _decodeTokenParams, + ), + CodecTypes.tokenDetails: _CodecPair( + _encodeTokenDetails, + _decodeTokenDetails, + ), + CodecTypes.tokenRequest: _CodecPair( + _encodeTokenRequest, + _decodeTokenRequest, + ), + CodecTypes.restChannelOptions: _CodecPair( + _encodeRestChannelOptions, + null, + ), CodecTypes.realtimeChannelOptions: _CodecPair( _encodeRealtimeChannelOptions, null, ), CodecTypes.authOptions: _CodecPair(_encodeAuthOptions, null), - CodecTypes.paginatedResult: - _CodecPair>(null, _decodePaginatedResult), - CodecTypes.realtimeHistoryParams: - _CodecPair(_encodeRealtimeHistoryParams, null), - CodecTypes.restHistoryParams: - _CodecPair(_encodeRestHistoryParams, null), - CodecTypes.restPresenceParams: - _CodecPair(_encodeRestPresenceParams, null), + CodecTypes.paginatedResult: _CodecPair>( + null, + _decodePaginatedResult, + ), + CodecTypes.realtimeHistoryParams: _CodecPair( + _encodeRealtimeHistoryParams, + null, + ), + CodecTypes.restHistoryParams: _CodecPair( + _encodeRestHistoryParams, + null, + ), + CodecTypes.restPresenceParams: _CodecPair( + _encodeRestPresenceParams, + null, + ), CodecTypes.realtimePresenceParams: _CodecPair( _encodeRealtimePresenceParams, null, ), // Push Notifications - CodecTypes.deviceDetails: - _CodecPair(null, _decodeDeviceDetails), + CodecTypes.deviceDetails: _CodecPair( + null, + _decodeDeviceDetails, + ), CodecTypes.localDevice: _CodecPair(null, _decodeLocalDevice), CodecTypes.pushChannelSubscription: _CodecPair( - null, _decodePushChannelSubscription), + null, + _decodePushChannelSubscription, + ), CodecTypes.unNotificationSettings: _CodecPair( - null, _decodeUNNotificationSettings), - CodecTypes.remoteMessage: - _CodecPair(null, _decodeRemoteMessage), + null, + _decodeUNNotificationSettings, + ), + CodecTypes.remoteMessage: _CodecPair( + null, + _decodeRemoteMessage, + ), - CodecTypes.errorInfo: - _CodecPair(_encodeErrorInfo, _decodeErrorInfo), + CodecTypes.errorInfo: _CodecPair( + _encodeErrorInfo, + _decodeErrorInfo, + ), CodecTypes.messageData: _CodecPair?>( _encodeChannelMessageData, _decodeChannelMessageData, @@ -120,23 +148,33 @@ class Codec extends StandardMessageCodec { _encodeChannelMessageExtras, _decodeChannelMessageExtras, ), - CodecTypes.message: - _CodecPair(_encodeChannelMessage, _decodeChannelMessage), - CodecTypes.presenceMessage: - _CodecPair(null, _decodePresenceMessage), + CodecTypes.message: _CodecPair( + _encodeChannelMessage, + _decodeChannelMessage, + ), + CodecTypes.presenceMessage: _CodecPair( + null, + _decodePresenceMessage, + ), // Events - Connection CodecTypes.connectionStateChange: _CodecPair( - null, _decodeConnectionStateChange), + null, + _decodeConnectionStateChange, + ), // Events - Channel - CodecTypes.channelStateChange: - _CodecPair(null, _decodeChannelStateChange), + CodecTypes.channelStateChange: _CodecPair( + null, + _decodeChannelStateChange, + ), // Encryption - CodecTypes.cipherParams: - _CodecPair(_encodeCipherParams, _decodeCipherParams), + CodecTypes.cipherParams: _CodecPair( + _encodeCipherParams, + _decodeCipherParams, + ), }; } @@ -248,8 +286,11 @@ class Codec extends StandardMessageCodec { _writeToJson(jsonMap, TxClientOptions.authUrl, v.authUrl); _writeToJson(jsonMap, TxClientOptions.authMethod, v.authMethod); _writeToJson(jsonMap, TxClientOptions.key, v.key); - _writeToJson(jsonMap, TxClientOptions.tokenDetails, - _encodeTokenDetails(v.tokenDetails)); + _writeToJson( + jsonMap, + TxClientOptions.tokenDetails, + _encodeTokenDetails(v.tokenDetails), + ); _writeToJson(jsonMap, TxClientOptions.authHeaders, v.authHeaders); _writeToJson(jsonMap, TxClientOptions.authParams, v.authParams); _writeToJson(jsonMap, TxClientOptions.queryTime, v.queryTime); @@ -259,7 +300,10 @@ class Codec extends StandardMessageCodec { // ClientOptions _writeToJson(jsonMap, TxClientOptions.clientId, v.clientId); _writeToJson( - jsonMap, TxClientOptions.logLevel, _encodeLogLevel(v.logLevel)); + jsonMap, + TxClientOptions.logLevel, + _encodeLogLevel(v.logLevel), + ); //TODO handle logHandler _writeToJson(jsonMap, TxClientOptions.tls, v.tls); _writeToJson(jsonMap, TxClientOptions.restHost, v.restHost); @@ -268,32 +312,57 @@ class Codec extends StandardMessageCodec { _writeToJson(jsonMap, TxClientOptions.tlsPort, v.tlsPort); _writeToJson(jsonMap, TxClientOptions.autoConnect, v.autoConnect); _writeToJson( - jsonMap, TxClientOptions.useBinaryProtocol, v.useBinaryProtocol); + jsonMap, + TxClientOptions.useBinaryProtocol, + v.useBinaryProtocol, + ); _writeToJson(jsonMap, TxClientOptions.queueMessages, v.queueMessages); _writeToJson(jsonMap, TxClientOptions.echoMessages, v.echoMessages); _writeToJson(jsonMap, TxClientOptions.recover, v.recover); _writeToJson(jsonMap, TxClientOptions.environment, v.environment); - _writeToJson(jsonMap, TxClientOptions.idempotentRestPublishing, - v.idempotentRestPublishing); + _writeToJson( + jsonMap, + TxClientOptions.idempotentRestPublishing, + v.idempotentRestPublishing, + ); _writeToJson(jsonMap, TxClientOptions.httpOpenTimeout, v.httpOpenTimeout); _writeToJson( - jsonMap, TxClientOptions.httpRequestTimeout, v.httpRequestTimeout); + jsonMap, + TxClientOptions.httpRequestTimeout, + v.httpRequestTimeout, + ); + _writeToJson( + jsonMap, + TxClientOptions.httpMaxRetryCount, + v.httpMaxRetryCount, + ); _writeToJson( - jsonMap, TxClientOptions.httpMaxRetryCount, v.httpMaxRetryCount); - _writeToJson(jsonMap, TxClientOptions.realtimeRequestTimeout, - v.realtimeRequestTimeout); + jsonMap, + TxClientOptions.realtimeRequestTimeout, + v.realtimeRequestTimeout, + ); _writeToJson(jsonMap, TxClientOptions.fallbackHosts, v.fallbackHosts); _writeToJson( - jsonMap, - TxClientOptions.fallbackHostsUseDefault, - // ignore: deprecated_member_use_from_same_package - v.fallbackHostsUseDefault); + jsonMap, + TxClientOptions.fallbackHostsUseDefault, + // ignore: deprecated_member_use_from_same_package + v.fallbackHostsUseDefault, + ); _writeToJson( - jsonMap, TxClientOptions.fallbackRetryTimeout, v.fallbackRetryTimeout); - _writeToJson(jsonMap, TxClientOptions.defaultTokenParams, - _encodeTokenParams(v.defaultTokenParams)); + jsonMap, + TxClientOptions.fallbackRetryTimeout, + v.fallbackRetryTimeout, + ); + _writeToJson( + jsonMap, + TxClientOptions.defaultTokenParams, + _encodeTokenParams(v.defaultTokenParams), + ); _writeToJson( - jsonMap, TxClientOptions.channelRetryTimeout, v.channelRetryTimeout); + jsonMap, + TxClientOptions.channelRetryTimeout, + v.channelRetryTimeout, + ); _writeToJson(jsonMap, TxClientOptions.transportParams, v.transportParams); _writeToJson(jsonMap, TxClientOptions.dartVersion, dartVersion()); return jsonMap; @@ -338,7 +407,10 @@ class Codec extends StandardMessageCodec { _writeToJson(jsonMap, TxTokenRequest.mac, v.mac); _writeToJson(jsonMap, TxTokenRequest.nonce, v.nonce); _writeToJson( - jsonMap, TxTokenRequest.timestamp, v.timestamp?.millisecondsSinceEpoch); + jsonMap, + TxTokenRequest.timestamp, + v.timestamp?.millisecondsSinceEpoch, + ); _writeToJson(jsonMap, TxTokenRequest.ttl, v.ttl); return jsonMap; } @@ -348,8 +420,9 @@ class Codec extends StandardMessageCodec { /// returns null if [v] is null Map _encodeRestChannelOptions(final RestChannelOptions v) { final jsonMap = {}; - jsonMap[TxRestChannelOptions.cipherParams] = - _encodeCipherParams(v.cipherParams); + jsonMap[TxRestChannelOptions.cipherParams] = _encodeCipherParams( + v.cipherParams, + ); return jsonMap; } @@ -372,10 +445,12 @@ class Codec extends StandardMessageCodec { /// Encodes [RealtimeChannelOptions] to a Map /// returns null if [v] is null Map _encodeRealtimeChannelOptions( - final RealtimeChannelOptions v) { + final RealtimeChannelOptions v, + ) { final jsonMap = {}; - jsonMap[TxRealtimeChannelOptions.cipherParams] = - _encodeCipherParams(v.cipherParams); + jsonMap[TxRealtimeChannelOptions.cipherParams] = _encodeCipherParams( + v.cipherParams, + ); _writeToJson(jsonMap, TxRealtimeChannelOptions.params, v.params); _writeToJson( jsonMap, @@ -387,8 +462,9 @@ class Codec extends StandardMessageCodec { Map _encodeAuthOptions(final AuthOptions authOptions) { final jsonMap = {}; - jsonMap[TxAuthOptions.tokenDetails] = - _encodeTokenDetails(authOptions.tokenDetails); + jsonMap[TxAuthOptions.tokenDetails] = _encodeTokenDetails( + authOptions.tokenDetails, + ); jsonMap[TxAuthOptions.authUrl] = authOptions.authUrl; jsonMap[TxAuthOptions.authMethod] = authOptions.authMethod; jsonMap[TxAuthOptions.key] = authOptions.key; @@ -418,20 +494,13 @@ class Codec extends StandardMessageCodec { CipherParams _decodeCipherParams(final Map jsonMap) { if (io.Platform.isAndroid) { final cipherParamsHandle = jsonMap[TxCipherParams.androidHandle] as int; - return CipherParamsInternal.forAndroid( - androidHandle: cipherParamsHandle, - ); + return CipherParamsInternal.forAndroid(androidHandle: cipherParamsHandle); } else if (io.Platform.isIOS) { final algorithm = jsonMap[TxCipherParams.iosAlgorithm] as String; final key = jsonMap[TxCipherParams.iosKey] as Uint8List; - return CipherParamsInternal.forIOS( - algorithm: algorithm, - key: key, - ); + return CipherParamsInternal.forIOS(algorithm: algorithm, key: key); } else { - throw AblyException( - message: 'Unsupported platform', - ); + throw AblyException(message: 'Unsupported platform'); } } @@ -441,9 +510,15 @@ class Codec extends StandardMessageCodec { Map _encodeRestHistoryParams(final RestHistoryParams v) { final jsonMap = {}; _writeToJson( - jsonMap, TxRestHistoryParams.start, v.start.millisecondsSinceEpoch); + jsonMap, + TxRestHistoryParams.start, + v.start.millisecondsSinceEpoch, + ); _writeToJson( - jsonMap, TxRestHistoryParams.end, v.end.millisecondsSinceEpoch); + jsonMap, + TxRestHistoryParams.end, + v.end.millisecondsSinceEpoch, + ); _writeToJson(jsonMap, TxRestHistoryParams.direction, v.direction); _writeToJson(jsonMap, TxRestHistoryParams.limit, v.limit); return jsonMap; @@ -461,12 +536,16 @@ class Codec extends StandardMessageCodec { } Map _encodeRealtimePresenceParams( - final RealtimePresenceParams v) { + final RealtimePresenceParams v, + ) { final jsonMap = {}; _writeToJson(jsonMap, TxRealtimePresenceParams.waitForSync, v.waitForSync); _writeToJson(jsonMap, TxRealtimePresenceParams.clientId, v.clientId); _writeToJson( - jsonMap, TxRealtimePresenceParams.connectionId, v.connectionId); + jsonMap, + TxRealtimePresenceParams.connectionId, + v.connectionId, + ); return jsonMap; } @@ -516,8 +595,8 @@ class Codec extends StandardMessageCodec { final message = (v.message == null) ? null : (codecType == null) - ? v.message - : codecMap[codecType]!.encode(v.message); + ? v.message + : codecMap[codecType]!.encode(v.message); final jsonMap = {}; _writeToJson(jsonMap, TxAblyEventMessage.eventName, v.eventName); _writeToJson(jsonMap, TxAblyEventMessage.type, codecType); @@ -592,30 +671,26 @@ class Codec extends StandardMessageCodec { /// Decodes value [jsonMap] to [ClientOptions] /// returns null if [jsonMap] is null ClientOptions _decodeClientOptions(Map jsonMap) { - final tokenDetails = toJsonMap(_readFromJson>( - jsonMap, - TxClientOptions.tokenDetails, - )); - final tokenParams = toJsonMap(_readFromJson>( - jsonMap, - TxClientOptions.defaultTokenParams, - )); - final clientOptions = ClientOptions( - // AuthOptions (super class of ClientOptions) - authUrl: _readFromJson( + final tokenDetails = toJsonMap( + _readFromJson>( jsonMap, - TxClientOptions.authUrl, + TxClientOptions.tokenDetails, ), - authMethod: _readFromJson( - jsonMap, - TxClientOptions.authMethod, - ), - key: _readFromJson( + ); + final tokenParams = toJsonMap( + _readFromJson>( jsonMap, - TxClientOptions.key, + TxClientOptions.defaultTokenParams, ), - tokenDetails: - (tokenDetails == null) ? null : _decodeTokenDetails(tokenDetails), + ); + final clientOptions = ClientOptions( + // AuthOptions (super class of ClientOptions) + authUrl: _readFromJson(jsonMap, TxClientOptions.authUrl), + authMethod: _readFromJson(jsonMap, TxClientOptions.authMethod), + key: _readFromJson(jsonMap, TxClientOptions.key), + tokenDetails: (tokenDetails == null) + ? null + : _decodeTokenDetails(tokenDetails), authHeaders: _readFromJson>( jsonMap, TxClientOptions.authHeaders, @@ -624,51 +699,27 @@ class Codec extends StandardMessageCodec { jsonMap, TxClientOptions.authParams, ), - queryTime: _readFromJson( - jsonMap, - TxClientOptions.queryTime, - ), - useTokenAuth: _readFromJson( - jsonMap, - TxClientOptions.useTokenAuth, - ), + queryTime: _readFromJson(jsonMap, TxClientOptions.queryTime), + useTokenAuth: _readFromJson(jsonMap, TxClientOptions.useTokenAuth), // ClientOptions - clientId: _readFromJson( - jsonMap, - TxClientOptions.clientId, - ), + clientId: _readFromJson(jsonMap, TxClientOptions.clientId), logLevel: _decodeLogLevel(jsonMap[TxClientOptions.logLevel] as String?), //TODO handle logHandler tls: jsonMap[TxClientOptions.tls] as bool, - restHost: _readFromJson( - jsonMap, - TxClientOptions.restHost, - ), + restHost: _readFromJson(jsonMap, TxClientOptions.restHost), realtimeHost: _readFromJson( jsonMap, TxClientOptions.realtimeHost, ), - port: _readFromJson( - jsonMap, - TxClientOptions.port, - ), - tlsPort: _readFromJson( - jsonMap, - TxClientOptions.tlsPort, - ), + port: _readFromJson(jsonMap, TxClientOptions.port), + tlsPort: _readFromJson(jsonMap, TxClientOptions.tlsPort), autoConnect: jsonMap[TxClientOptions.autoConnect] as bool, useBinaryProtocol: jsonMap[TxClientOptions.useBinaryProtocol] as bool, queueMessages: jsonMap[TxClientOptions.queueMessages] as bool, echoMessages: jsonMap[TxClientOptions.echoMessages] as bool, - recover: _readFromJson( - jsonMap, - TxClientOptions.recover, - ), - environment: _readFromJson( - jsonMap, - TxClientOptions.environment, - ), + recover: _readFromJson(jsonMap, TxClientOptions.recover), + environment: _readFromJson(jsonMap, TxClientOptions.environment), idempotentRestPublishing: _readFromJson( jsonMap, TxClientOptions.idempotentRestPublishing, @@ -688,8 +739,9 @@ class Codec extends StandardMessageCodec { ), fallbackRetryTimeout: jsonMap[TxClientOptions.fallbackRetryTimeout] as int, - defaultTokenParams: - (tokenParams == null) ? null : _decodeTokenParams(tokenParams), + defaultTokenParams: (tokenParams == null) + ? null + : _decodeTokenParams(tokenParams), channelRetryTimeout: jsonMap[TxClientOptions.channelRetryTimeout] as int, transportParams: _readFromJson>( jsonMap, @@ -753,12 +805,16 @@ class Codec extends StandardMessageCodec { final type = _readFromJson(jsonMap, TxAblyMessage.type); var message = jsonMap[TxAblyMessage.message] as Object; if (type != null) { - message = codecMap[type]!.decode( - toJsonMap(_readFromJson>( - jsonMap, - TxAblyMessage.message, - )), - ) as Object; + message = + codecMap[type]!.decode( + toJsonMap( + _readFromJson>( + jsonMap, + TxAblyMessage.message, + ), + ), + ) + as Object; } return AblyMessage( message: message, @@ -769,19 +825,23 @@ class Codec extends StandardMessageCodec { DeviceDetails _decodeDeviceDetails(Map jsonMap) { final formFactor = _decodeFormFactor( - _readFromJson(jsonMap, TxDeviceDetails.formFactor)); + _readFromJson(jsonMap, TxDeviceDetails.formFactor), + ); return DeviceDetails( id: jsonMap[TxDeviceDetails.id] as String?, clientId: jsonMap[TxDeviceDetails.clientId] as String?, - platform: - _decodeDevicePlatform(jsonMap[TxDeviceDetails.platform] as String), + platform: _decodeDevicePlatform( + jsonMap[TxDeviceDetails.platform] as String, + ), formFactor: formFactor, metadata: toTypedJsonMap( - jsonMap[TxDeviceDetails.metadata] as Map?), + jsonMap[TxDeviceDetails.metadata] as Map?, + ), push: _decodeDevicePushDetails( - Map.from(jsonMap[TxDeviceDetails.devicePushDetails] - as Map), + Map.from( + jsonMap[TxDeviceDetails.devicePushDetails] as Map, + ), ), ); } @@ -794,10 +854,12 @@ class Codec extends StandardMessageCodec { jsonMap[TxDevicePushDetails.recipient] as Map?; return DevicePushDetails( - recipient: - (recipient != null) ? Map.from(recipient) : null, - state: - _decodeDevicePushState(jsonMap[TxDevicePushDetails.state] as String?), + recipient: (recipient != null) + ? Map.from(recipient) + : null, + state: _decodeDevicePushState( + jsonMap[TxDevicePushDetails.state] as String?, + ), errorReason: (jsonMapErrorReason != null) ? _decodeErrorInfo(Map.from(jsonMapErrorReason)) : null, @@ -805,11 +867,10 @@ class Codec extends StandardMessageCodec { } LocalDevice _decodeLocalDevice(Map jsonMap) => LocalDevice( - deviceDetails: _decodeDeviceDetails(jsonMap), - deviceSecret: jsonMap[TxLocalDevice.deviceSecret] as String?, - deviceIdentityToken: - jsonMap[TxLocalDevice.deviceIdentityToken] as String?, - ); + deviceDetails: _decodeDeviceDetails(jsonMap), + deviceSecret: jsonMap[TxLocalDevice.deviceSecret] as String?, + deviceIdentityToken: jsonMap[TxLocalDevice.deviceIdentityToken] as String?, + ); FormFactor _decodeFormFactor(String? enumValue) { switch (enumValue) { @@ -865,46 +926,56 @@ class Codec extends StandardMessageCodec { } PushChannelSubscription _decodePushChannelSubscription( - Map jsonMap) => - PushChannelSubscription( - channel: jsonMap[TxPushChannelSubscription.channel] as String, - clientId: jsonMap[TxPushChannelSubscription.clientId] as String?, - deviceId: jsonMap[TxPushChannelSubscription.deviceId] as String?, - ); + Map jsonMap, + ) => PushChannelSubscription( + channel: jsonMap[TxPushChannelSubscription.channel] as String, + clientId: jsonMap[TxPushChannelSubscription.clientId] as String?, + deviceId: jsonMap[TxPushChannelSubscription.deviceId] as String?, + ); UNNotificationSettings _decodeUNNotificationSettings( - Map jsonMap) => - UNNotificationSettings( - authorizationStatus: _decodeUNAuthorizationStatus( - jsonMap[TxUNNotificationSettings.authorizationStatus] as String), - soundSetting: _decodeUNNotificationSetting( - jsonMap[TxUNNotificationSettings.soundSetting] as String), - badgeSetting: _decodeUNNotificationSetting( - jsonMap[TxUNNotificationSettings.badgeSetting] as String), - alertSetting: _decodeUNNotificationSetting( - jsonMap[TxUNNotificationSettings.alertSetting] as String), - notificationCenterSetting: _decodeUNNotificationSetting( - jsonMap[TxUNNotificationSettings.notificationCenterSetting] - as String), - lockScreenSetting: _decodeUNNotificationSetting( - jsonMap[TxUNNotificationSettings.lockScreenSetting] as String), - carPlaySetting: _decodeUNNotificationSetting( - jsonMap[TxUNNotificationSettings.carPlaySetting] as String), - alertStyle: _decodeUNAlertStyle( - jsonMap[TxUNNotificationSettings.alertStyle] as String), - showPreviewsSetting: _decodeUNShowPreviewsSetting( - jsonMap[TxUNNotificationSettings.showPreviewsSetting] as String), - criticalAlertSetting: _decodeUNNotificationSetting( - jsonMap[TxUNNotificationSettings.criticalAlertSetting] as String), - providesAppNotificationSettings: - jsonMap[TxUNNotificationSettings.providesAppNotificationSettings] - as bool, - announcementSetting: _decodeUNNotificationSetting( - jsonMap[TxUNNotificationSettings.announcementSetting] as String), - scheduledDeliverySetting: _decodeUNNotificationSetting( - jsonMap[TxUNNotificationSettings.scheduledDeliverySetting] - as String), - ); + Map jsonMap, + ) => UNNotificationSettings( + authorizationStatus: _decodeUNAuthorizationStatus( + jsonMap[TxUNNotificationSettings.authorizationStatus] as String, + ), + soundSetting: _decodeUNNotificationSetting( + jsonMap[TxUNNotificationSettings.soundSetting] as String, + ), + badgeSetting: _decodeUNNotificationSetting( + jsonMap[TxUNNotificationSettings.badgeSetting] as String, + ), + alertSetting: _decodeUNNotificationSetting( + jsonMap[TxUNNotificationSettings.alertSetting] as String, + ), + notificationCenterSetting: _decodeUNNotificationSetting( + jsonMap[TxUNNotificationSettings.notificationCenterSetting] as String, + ), + lockScreenSetting: _decodeUNNotificationSetting( + jsonMap[TxUNNotificationSettings.lockScreenSetting] as String, + ), + carPlaySetting: _decodeUNNotificationSetting( + jsonMap[TxUNNotificationSettings.carPlaySetting] as String, + ), + alertStyle: _decodeUNAlertStyle( + jsonMap[TxUNNotificationSettings.alertStyle] as String, + ), + showPreviewsSetting: _decodeUNShowPreviewsSetting( + jsonMap[TxUNNotificationSettings.showPreviewsSetting] as String, + ), + criticalAlertSetting: _decodeUNNotificationSetting( + jsonMap[TxUNNotificationSettings.criticalAlertSetting] as String, + ), + providesAppNotificationSettings: + jsonMap[TxUNNotificationSettings.providesAppNotificationSettings] + as bool, + announcementSetting: _decodeUNNotificationSetting( + jsonMap[TxUNNotificationSettings.announcementSetting] as String, + ), + scheduledDeliverySetting: _decodeUNNotificationSetting( + jsonMap[TxUNNotificationSettings.scheduledDeliverySetting] as String, + ), + ); UNShowPreviewsSetting _decodeUNShowPreviewsSetting(String setting) { switch (setting) { @@ -916,7 +987,8 @@ class Codec extends StandardMessageCodec { return UNShowPreviewsSetting.never; } throw AblyException( - message: 'Platform communication error. ' + message: + 'Platform communication error. ' 'UNShowPreviewsSetting is invalid: $setting', ); } @@ -931,7 +1003,8 @@ class Codec extends StandardMessageCodec { return UNAlertStyle.none; } throw AblyException( - message: 'Platform communication error. ' + message: + 'Platform communication error. ' 'UNAlertStyle is invalid: $style', ); } @@ -950,7 +1023,8 @@ class Codec extends StandardMessageCodec { return UNAuthorizationStatus.ephemeral; } throw AblyException( - message: 'Platform communication error. ' + message: + 'Platform communication error. ' 'UNAuthorizationStatus is invalid: $status', ); } @@ -965,7 +1039,8 @@ class Codec extends StandardMessageCodec { return UNNotificationSetting.notSupported; } throw AblyException( - message: 'Platform communication error. ' + message: + 'Platform communication error. ' 'UNNotificationSetting is invalid: $setting', ); } @@ -977,13 +1052,13 @@ class Codec extends StandardMessageCodec { /// Decodes value [jsonMap] to [ErrorInfo] /// returns null if [jsonMap] is null ErrorInfo _decodeErrorInfo(Map jsonMap) => ErrorInfo( - code: jsonMap[TxErrorInfo.code] as int?, - message: jsonMap[TxErrorInfo.message] as String?, - statusCode: jsonMap[TxErrorInfo.statusCode] as int?, - href: jsonMap[TxErrorInfo.href] as String?, - requestId: jsonMap[TxErrorInfo.requestId] as String?, - cause: jsonMap[TxErrorInfo.cause] as ErrorInfo?, - ); + code: jsonMap[TxErrorInfo.code] as int?, + message: jsonMap[TxErrorInfo.message] as String?, + statusCode: jsonMap[TxErrorInfo.statusCode] as int?, + href: jsonMap[TxErrorInfo.href] as String?, + requestId: jsonMap[TxErrorInfo.requestId] as String?, + cause: jsonMap[TxErrorInfo.cause] as ErrorInfo?, + ); /// @nodoc /// Decodes [eventName] to [ConnectionEvent] enum if not null @@ -1009,7 +1084,8 @@ class Codec extends StandardMessageCodec { return ConnectionEvent.update; } throw AblyException( - message: 'Platform communication error. ' + message: + 'Platform communication error. ' 'Connection event is invalid: $eventName', ); } @@ -1098,23 +1174,34 @@ class Codec extends StandardMessageCodec { EnrichedConnectionStateChange _decodeConnectionStateChange( Map jsonMap, ) { - final connectionId = - _readFromJson(jsonMap, TxConnectionStateChange.connectionId); - final connectionKey = - _readFromJson(jsonMap, TxConnectionStateChange.connectionKey); + final connectionId = _readFromJson( + jsonMap, + TxConnectionStateChange.connectionId, + ); + final connectionKey = _readFromJson( + jsonMap, + TxConnectionStateChange.connectionKey, + ); final current = _decodeConnectionState( - _readFromJson(jsonMap, TxConnectionStateChange.current)); + _readFromJson(jsonMap, TxConnectionStateChange.current), + ); final previous = _decodeConnectionState( - _readFromJson(jsonMap, TxConnectionStateChange.previous)); + _readFromJson(jsonMap, TxConnectionStateChange.previous), + ); final event = _decodeConnectionEvent( - _readFromJson(jsonMap, TxConnectionStateChange.event)); - final retryIn = - _readFromJson(jsonMap, TxConnectionStateChange.retryIn); - final errorInfo = toJsonMap(_readFromJson>( + _readFromJson(jsonMap, TxConnectionStateChange.event), + ); + final retryIn = _readFromJson( jsonMap, - TxConnectionStateChange.reason, - )); + TxConnectionStateChange.retryIn, + ); + final errorInfo = toJsonMap( + _readFromJson>( + jsonMap, + TxConnectionStateChange.reason, + ), + ); final reason = (errorInfo == null) ? null : _decodeErrorInfo(errorInfo); return EnrichedConnectionStateChange( stateChange: ConnectionStateChange( @@ -1134,16 +1221,21 @@ class Codec extends StandardMessageCodec { /// returns null if [jsonMap] is null ChannelStateChange _decodeChannelStateChange(Map jsonMap) { final current = _decodeChannelState( - _readFromJson(jsonMap, TxChannelStateChange.current)); + _readFromJson(jsonMap, TxChannelStateChange.current), + ); final previous = _decodeChannelState( - _readFromJson(jsonMap, TxChannelStateChange.previous)); + _readFromJson(jsonMap, TxChannelStateChange.previous), + ); final event = _decodeChannelEvent( - _readFromJson(jsonMap, TxChannelStateChange.event)); + _readFromJson(jsonMap, TxChannelStateChange.event), + ); final resumed = _readFromJson(jsonMap, TxChannelStateChange.resumed)!; - final errorInfo = toJsonMap(_readFromJson>( - jsonMap, - TxChannelStateChange.reason, - )); + final errorInfo = toJsonMap( + _readFromJson>( + jsonMap, + TxChannelStateChange.reason, + ), + ); final reason = (errorInfo == null) ? null : _decodeErrorInfo(errorInfo); return ChannelStateChange( current: current, @@ -1219,14 +1311,15 @@ class Codec extends StandardMessageCodec { final timestamp = _readFromJson(jsonMap, TxPresenceMessage.timestamp); return PresenceMessage( id: _readFromJson(jsonMap, TxPresenceMessage.id), - action: _decodePresenceAction(_readFromJson( - jsonMap, - TxPresenceMessage.action, - )), + action: _decodePresenceAction( + _readFromJson(jsonMap, TxPresenceMessage.action), + ), clientId: _readFromJson(jsonMap, TxPresenceMessage.clientId), data: _readFromJson(jsonMap, TxPresenceMessage.data), - connectionId: - _readFromJson(jsonMap, TxPresenceMessage.connectionId), + connectionId: _readFromJson( + jsonMap, + TxPresenceMessage.connectionId, + ), encoding: _readFromJson(jsonMap, TxPresenceMessage.encoding), extras: _readFromJson(jsonMap, TxPresenceMessage.extras), timestamp: (timestamp == null) @@ -1240,7 +1333,8 @@ class Codec extends StandardMessageCodec { /// returns null if [jsonMap] is null PaginatedResult _decodePaginatedResult(Map jsonMap) { final type = _readFromJson(jsonMap, TxPaginatedResult.type); - final items = _readFromJson>(jsonMap, TxPaginatedResult.items) + final items = + _readFromJson>(jsonMap, TxPaginatedResult.items) ?.map((e) => codecMap[type]?.decode(toJsonMap(e as Map)) as Object) .toList() ?? []; diff --git a/lib/src/platform/src/method_call_handler.dart b/lib/src/platform/src/method_call_handler.dart index ac05625d8..badf59130 100644 --- a/lib/src/platform/src/method_call_handler.dart +++ b/lib/src/platform/src/method_call_handler.dart @@ -26,16 +26,18 @@ class AblyMethodCallHandler { case PlatformMethod.pushOnBackgroundMessage: return _onPushBackgroundMessage(call.arguments as RemoteMessage); case PlatformMethod.pushOnShowNotificationInForeground: - return _pushNotificationEvents - .showNotificationInForeground(call.arguments as RemoteMessage); + return _pushNotificationEvents.showNotificationInForeground( + call.arguments as RemoteMessage, + ); case PlatformMethod.pushOnNotificationTap: return _onNotificationTap(call.arguments as RemoteMessage); case PlatformMethod.pushOpenSettingsFor: return _onOpenSettingsFor(); default: throw PlatformException( - code: 'Received invalid method channel call from Platform side', - message: 'No such method ${call.method}'); + code: 'Received invalid method channel call from Platform side', + message: 'No such method ${call.method}', + ); } }); } @@ -47,7 +49,8 @@ class AblyMethodCallHandler { final rest = restInstances[message.handle]; if (rest == null) { throw AblyException( - message: "AblyMethodCallHandler#onAuthCallback's " + message: + "AblyMethodCallHandler#onAuthCallback's " 'rest handle is ${message.handle}, and rest is $rest', ); } @@ -61,7 +64,8 @@ class AblyMethodCallHandler { final realtime = realtimeInstances[message.handle]; if (realtime == null) { throw AblyException( - message: "AblyMethodCallHandler#onRealtimeAuthCallback's " + message: + "AblyMethodCallHandler#onRealtimeAuthCallback's " 'realtime handle is ${message.handle}, and realtime is $realtime', ); } @@ -99,8 +103,9 @@ class AblyMethodCallHandler { } Future _onNotificationTap(RemoteMessage remoteMessage) async { - _pushNotificationEvents.onNotificationTapStreamController - .add(remoteMessage); + _pushNotificationEvents.onNotificationTapStreamController.add( + remoteMessage, + ); return null; } diff --git a/lib/src/platform/src/paginated_result.dart b/lib/src/platform/src/paginated_result.dart index 37b7d49b4..b9c88ce10 100644 --- a/lib/src/platform/src/paginated_result.dart +++ b/lib/src/platform/src/paginated_result.dart @@ -32,8 +32,8 @@ class PaginatedResult extends PlatformObject { /// Creates a PaginatedResult instance from items and a boolean indicating /// whether there is a next page PaginatedResult(this._items, {required bool hasNext}) - : _hasNext = hasNext, - super(fetchHandle: false); + : _hasNext = hasNext, + super(fetchHandle: false); /// @nodoc /// Instantiates by extracting result from [AblyMessage] returned from @@ -42,10 +42,10 @@ class PaginatedResult extends PlatformObject { /// Sets appropriate [_pageHandle] for identifying platform side of this /// result object so that [next] and [first] can be executed PaginatedResult.fromAblyMessage(AblyMessage> message) - : _hasNext = message.message.hasNext(), - _items = message.message.items.map((e) => e as T).toList(), - _pageHandle = message.handle, - super(fetchHandle: false); + : _hasNext = message.message.hasNext(), + _items = message.message.items.map((e) => e as T).toList(), + _pageHandle = message.handle, + super(fetchHandle: false); /// @nodoc @override @@ -57,8 +57,9 @@ class PaginatedResult extends PlatformObject { /// /// If there are no further pages, then null is returned. Future> next() async { - final message = - await invokeRequest>(PlatformMethod.nextPage); + final message = await invokeRequest>( + PlatformMethod.nextPage, + ); return PaginatedResult.fromAblyMessage( AblyMessage.castFrom>(message), ); @@ -68,8 +69,9 @@ class PaginatedResult extends PlatformObject { /// and presence history, stats, and REST presence requests, for the first /// page of results. Future> first() async { - final message = - await invokeRequest>(PlatformMethod.firstPage); + final message = await invokeRequest>( + PlatformMethod.firstPage, + ); return PaginatedResult.fromAblyMessage( AblyMessage.castFrom>(message), ); diff --git a/lib/src/platform/src/platform.dart b/lib/src/platform/src/platform.dart index 4f30f8d87..51df109d8 100644 --- a/lib/src/platform/src/platform.dart +++ b/lib/src/platform/src/platform.dart @@ -18,7 +18,8 @@ class Platform { AblyMethodCallHandler(_methodChannel!); BackgroundIsolateAndroidPlatform().setupCallHandler(); _ablyClientsResetFuture = _invokePlatformMethodWithoutResetCheck( - PlatformMethod.resetAblyClients); + PlatformMethod.resetAblyClients, + ); } static Platform? _platform; @@ -47,8 +48,10 @@ class Platform { /// @nodoc /// Call a platform method which may return null/void as a result and /// check that ably clients have successfully reset - Future invokePlatformMethod(String method, - [AblyMessage>? arguments]) async { + Future invokePlatformMethod( + String method, [ + AblyMessage>? arguments, + ]) async { // Check if ably clients have successfully reset // (to ensure platform method calls won't interfere // with each other after Platform singleton is reinitialized) @@ -58,13 +61,17 @@ class Platform { /// @nodoc /// Call a platform method which always provides a non-null result - Future invokePlatformMethodNonNull(String method, - [AblyMessage>? arguments]) async { + Future invokePlatformMethodNonNull( + String method, [ + AblyMessage>? arguments, + ]) async { final result = await invokePlatformMethod(method, arguments); if (result == null) { throw AblyException( - message: 'invokePlatformMethodNonNull("$method") platform ' - 'method unexpectedly returned a null value.'); + message: + 'invokePlatformMethodNonNull("$method") platform ' + 'method unexpectedly returned a null value.', + ); } else { return result; } @@ -72,8 +79,10 @@ class Platform { /// @nodoc /// Call a platform method which may return null/void as a result - Future _invokePlatformMethodWithoutResetCheck(String method, - [AblyMessage>? arguments]) async { + Future _invokePlatformMethodWithoutResetCheck( + String method, [ + AblyMessage>? arguments, + ]) async { try { // If argument is null, pass an empty [AblyMessage], because codec fails // if argument value is null @@ -92,15 +101,14 @@ class Platform { /// @nodoc /// Call a platform method which always provides an observable stream /// of data as a result - Stream receiveBroadcastStream(String methodName, int handle, - [final Object? payload]) => - _streamsChannel!.receiveBroadcastStream( - AblyMessage( - message: AblyEventMessage( - eventName: methodName, - message: payload, - ), - handle: handle, - ), - ); + Stream receiveBroadcastStream( + String methodName, + int handle, [ + final Object? payload, + ]) => _streamsChannel!.receiveBroadcastStream( + AblyMessage( + message: AblyEventMessage(eventName: methodName, message: payload), + handle: handle, + ), + ); } diff --git a/lib/src/platform/src/platform_object.dart b/lib/src/platform/src/platform_object.dart index 881f7be32..96d410582 100644 --- a/lib/src/platform/src/platform_object.dart +++ b/lib/src/platform/src/platform_object.dart @@ -44,20 +44,22 @@ abstract class PlatformObject { /// This method should be protected since it's only used to cover edge /// case for creating rest and realtime instances. @protected - Future invokeWithoutHandle(final String method, - [final Map? argument]) async { - final message = AblyMessage( - message: argument ?? {}, - ); + Future invokeWithoutHandle( + final String method, [ + final Map? argument, + ]) async { + final message = AblyMessage(message: argument ?? {}); return _platform.invokePlatformMethod(method, message); } /// @nodoc /// Invoke platform method channel with provided handle, or /// current handle if [externalHandle] is not provided. - Future invoke(final String method, - [final Map? arguments, - final int? externalHandle]) async { + Future invoke( + final String method, [ + final Map? arguments, + final int? externalHandle, + ]) async { final message = AblyMessage( message: arguments ?? {}, handle: externalHandle ?? await handle, @@ -69,8 +71,10 @@ abstract class PlatformObject { /// Invoke platform method channel with AblyMessage encapsulation. /// /// This is similar to [invoke], but ensures the response is not null. - Future invokeRequest(final String method, - [final Map? arguments]) async { + Future invokeRequest( + final String method, [ + final Map? arguments, + ]) async { final response = await invoke(method, arguments); if (response == null) { throw AblyException( @@ -89,8 +93,10 @@ abstract class PlatformObject { // ignore: close_sinks, will be closed by listener final controller = StreamController(); handle - .then((handle) => - _platform.receiveBroadcastStream(method, handle, payload)) + .then( + (handle) => + _platform.receiveBroadcastStream(method, handle, payload), + ) .then(controller.addStream); return controller.stream; } diff --git a/lib/src/platform/src/push_notification_events_internal.dart b/lib/src/platform/src/push_notification_events_internal.dart index a00e42193..3cbddb821 100644 --- a/lib/src/platform/src/push_notification_events_internal.dart +++ b/lib/src/platform/src/push_notification_events_internal.dart @@ -15,7 +15,7 @@ class PushNotificationEventsInternal implements PushNotificationEvents { /// @nodoc /// Invoked when pushOnShowNotificationInForeground platform method is called. Future Function(RemoteMessage message)? - onShowNotificationInForegroundHandler; + onShowNotificationInForegroundHandler; /// @nodoc /// Exposes stream of received [RemoteMessage] objects. @@ -34,7 +34,8 @@ class PushNotificationEventsInternal implements PushNotificationEvents { @override Future get notificationTapLaunchedAppFromTerminated => Platform().invokePlatformMethod( - PlatformMethod.pushNotificationTapLaunchedAppFromTerminated); + PlatformMethod.pushNotificationTapLaunchedAppFromTerminated, + ); @override Stream get onMessage => onMessageStreamController.stream; @@ -50,7 +51,8 @@ class PushNotificationEventsInternal implements PushNotificationEvents { @override void setOnShowNotificationInForeground( - Future Function(RemoteMessage message) callback) { + Future Function(RemoteMessage message) callback, + ) { onShowNotificationInForegroundHandler = callback; } @@ -91,10 +93,12 @@ class PushNotificationEventsInternal implements PushNotificationEvents { } } else { // ignore:avoid_print - print('Received RemoteMessage but no handler was set. ' - 'RemoteMessage.data: ${remoteMessage.data}. ' - 'RemoteMessage.notification: ${remoteMessage.notification}. ' - 'Set `ably.Push.notificationEvents.setOnBackgroundMessage()`.'); + print( + 'Received RemoteMessage but no handler was set. ' + 'RemoteMessage.data: ${remoteMessage.data}. ' + 'RemoteMessage.notification: ${remoteMessage.notification}. ' + 'Set `ably.Push.notificationEvents.setOnBackgroundMessage()`.', + ); } } diff --git a/lib/src/platform/src/realtime/connection.dart b/lib/src/platform/src/realtime/connection.dart index b1dce0142..0f748d2a3 100644 --- a/lib/src/platform/src/realtime/connection.dart +++ b/lib/src/platform/src/realtime/connection.dart @@ -22,9 +22,7 @@ class Connection extends PlatformObject { /// /// Sets default [state] to [ConnectionState.initialized] and starts listening /// for updates to the connection [state]. - Connection(this.realtime) - : _state = ConnectionState.initialized, - super() { + Connection(this.realtime) : _state = ConnectionState.initialized, super() { _onConnectionStateChange().listen((event) { _state = event.stateChange.current; _errorReason = event.stateChange.reason; @@ -92,10 +90,13 @@ class Connection extends PlatformObject { /// Stream of connection events with specified [ConnectionEvent] type. Stream on([ConnectionEvent? connectionEvent]) => - _onConnectionStateChange().map((event) => event.stateChange).where( - (connectionStateChange) => - connectionEvent == null || - connectionStateChange.event == connectionEvent); + _onConnectionStateChange() + .map((event) => event.stateChange) + .where( + (connectionStateChange) => + connectionEvent == null || + connectionStateChange.event == connectionEvent, + ); /// Causes the connection to close, entering the [ConnectionState.closing] /// state. diff --git a/lib/src/platform/src/realtime/presence.dart b/lib/src/platform/src/realtime/presence.dart index 25bc10cfa..782789d76 100644 --- a/lib/src/platform/src/realtime/presence.dart +++ b/lib/src/platform/src/realtime/presence.dart @@ -17,16 +17,12 @@ class RealtimePresence extends PlatformObject { /// Retrieves the current members present on the channel and the metadata for /// each member, such as their [PresenceAction] and ID, based on provided /// [params]. Returns an array of [PresenceMessage] objects. - Future> get([ - RealtimePresenceParams? params, - ]) async { - final presenceMessages = await invokeRequest>( - PlatformMethod.realtimePresenceGet, - { - TxTransportKeys.channelName: _channel.name, - if (params != null) TxTransportKeys.params: params - }, - ); + Future> get([RealtimePresenceParams? params]) async { + final presenceMessages = + await invokeRequest>(PlatformMethod.realtimePresenceGet, { + TxTransportKeys.channelName: _channel.name, + if (params != null) TxTransportKeys.params: params, + }); return presenceMessages .map((e) => e as PresenceMessage) .toList(); @@ -46,7 +42,7 @@ class RealtimePresence extends PlatformObject { PlatformMethod.realtimePresenceHistory, { TxTransportKeys.channelName: _channel.name, - if (params != null) TxTransportKeys.params: params + if (params != null) TxTransportKeys.params: params, }, ); return PaginatedResult.fromAblyMessage( @@ -144,7 +140,9 @@ class RealtimePresence extends PlatformObject { if (action != null) actions ??= [action]; return listen(PlatformMethod.onRealtimePresenceMessage, { TxTransportKeys.channelName: _channel.name, - }).where((presenceMessage) => - actions == null || actions.contains(presenceMessage.action)); + }).where( + (presenceMessage) => + actions == null || actions.contains(presenceMessage.action), + ); } } diff --git a/lib/src/platform/src/realtime/realtime.dart b/lib/src/platform/src/realtime/realtime.dart index d186dbdc7..2c0815c05 100644 --- a/lib/src/platform/src/realtime/realtime.dart +++ b/lib/src/platform/src/realtime/realtime.dart @@ -11,12 +11,10 @@ import 'package:ably_flutter/src/realtime/src/realtime_auth.dart'; class Realtime extends PlatformObject { /// Constructs a `Realtime` object using an Ably [options] object or /// the Ably API [key] or token string used to validate the client. - Realtime({ - ClientOptions? options, - final String? key, - }) : assert(options != null || key != null), - options = options ?? ClientOptions(key: key), - super() { + Realtime({ClientOptions? options, final String? key}) + : assert(options != null || key != null), + options = options ?? ClientOptions(key: key), + super() { _connection = Connection(this); _channels = RealtimeChannels(this); push = Push(realtime: this); @@ -31,10 +29,10 @@ class Realtime extends PlatformObject { ///@nodoc @override Future createPlatformInstance() async { - final handle = - await invokeWithoutHandle(PlatformMethod.createRealtime, { - TxTransportKeys.options: options, - }); + final handle = await invokeWithoutHandle( + PlatformMethod.createRealtime, + {TxTransportKeys.options: options}, + ); _realtimeInstances[handle] = this; if (io.Platform.isAndroid && options.autoConnect) { @@ -45,11 +43,7 @@ class Realtime extends PlatformObject { // to false, and call connect immediately once we get the handle. // This is also a specific case where it's required to pass the handle // value from external source - await invoke( - PlatformMethod.connectRealtime, - null, - handle, - ); + await invoke(PlatformMethod.connectRealtime, null, handle); } return handle; } diff --git a/lib/src/platform/src/realtime/realtime_channel.dart b/lib/src/platform/src/realtime/realtime_channel.dart index 309a95c9d..01021e88f 100644 --- a/lib/src/platform/src/realtime/realtime_channel.dart +++ b/lib/src/platform/src/realtime/realtime_channel.dart @@ -29,10 +29,10 @@ class RealtimeChannel extends PlatformObject { /// sets default [state] to [ChannelState.initialized] and start listening /// for updates to the channel [state]/ RealtimeChannel(Realtime realtime, String channelName) - : _realtime = realtime, - _channelName = channelName, - state = ChannelState.initialized, - super() { + : _realtime = realtime, + _channelName = channelName, + state = ChannelState.initialized, + super() { _presence = RealtimePresence(this); push = PushChannel(_channelName, realtime: _realtime); on().listen((event) => state = event.current); @@ -55,10 +55,12 @@ class RealtimeChannel extends PlatformObject { RealtimeHistoryParams? params, ]) async { final message = await invokeRequest>( - PlatformMethod.realtimeHistory, { - TxTransportKeys.channelName: _channelName, - if (params != null) TxTransportKeys.params: params, - }); + PlatformMethod.realtimeHistory, + { + TxTransportKeys.channelName: _channelName, + if (params != null) TxTransportKeys.params: params, + }, + ); return PaginatedResult.fromAblyMessage( AblyMessage.castFrom>(message), ); @@ -76,7 +78,7 @@ class RealtimeChannel extends PlatformObject { Object? data, }) async { messages ??= [ - if (message == null) Message(name: name, data: data) else message + if (message == null) Message(name: name, data: data) else message, ]; await invoke(PlatformMethod.publishRealtimeChannelMessage, { TxTransportKeys.channelName: _channelName, @@ -114,8 +116,8 @@ class RealtimeChannel extends PlatformObject { /// [RealtimePresence.subscribe] are called on the [RealtimePresence] object /// for this channel. Future attach() => invoke(PlatformMethod.attachRealtimeChannel, { - TxTransportKeys.channelName: _channelName, - }); + TxTransportKeys.channelName: _channelName, + }); /// Detach from this channel. Any resulting channel state change is emitted to /// any listeners registered using the [RealtimeChannel.on] stream. @@ -123,8 +125,8 @@ class RealtimeChannel extends PlatformObject { /// Once all clients globally have detached from the channel, the channel will /// be released in the Ably service within two minutes. Future detach() => invoke(PlatformMethod.detachRealtimeChannel, { - TxTransportKeys.channelName: _channelName, - }); + TxTransportKeys.channelName: _channelName, + }); /// Sets the [options] for the channel. Future setOptions(RealtimeChannelOptions options) => @@ -135,10 +137,9 @@ class RealtimeChannel extends PlatformObject { /// Stream of channel events with specified [ChannelEvent] type Stream on([ChannelEvent? channelEvent]) => - listen( - PlatformMethod.onRealtimeChannelStateChanged, - {TxTransportKeys.channelName: _channelName}, - ).where( + listen(PlatformMethod.onRealtimeChannelStateChanged, { + TxTransportKeys.channelName: _channelName, + }).where( (stateChange) => channelEvent == null || stateChange.event == channelEvent, ); @@ -156,8 +157,10 @@ class RealtimeChannel extends PlatformObject { final subscribedNames = {name, ...?names}.where((n) => n != null).toList(); return listen(PlatformMethod.onRealtimeChannelMessage, { TxTransportKeys.channelName: _channelName, - }).where((message) => - subscribedNames.isEmpty || - subscribedNames.any((n) => n == message.name)); + }).where( + (message) => + subscribedNames.isEmpty || + subscribedNames.any((n) => n == message.name), + ); } } diff --git a/lib/src/platform/src/rest/rest_channel.dart b/lib/src/platform/src/rest/rest_channel.dart index 906e9bcdf..0dff24415 100644 --- a/lib/src/platform/src/rest/rest_channel.dart +++ b/lib/src/platform/src/rest/rest_channel.dart @@ -40,16 +40,12 @@ class RestChannel extends PlatformObject { /// If the channel is configured to persist messages, then messages can be /// retrieved from history for up to 72 hours in the past. If not, messages /// can only be retrieved from history for up to two minutes in the past. - Future> history([ - RestHistoryParams? params, - ]) async { - final message = await invokeRequest>( - PlatformMethod.restHistory, - { - TxTransportKeys.channelName: name, - if (params != null) TxTransportKeys.params: params - }, - ); + Future> history([RestHistoryParams? params]) async { + final message = + await invokeRequest>(PlatformMethod.restHistory, { + TxTransportKeys.channelName: name, + if (params != null) TxTransportKeys.params: params, + }); return PaginatedResult.fromAblyMessage( AblyMessage.castFrom>(message), ); @@ -64,7 +60,7 @@ class RestChannel extends PlatformObject { Object? data, }) async { messages ??= [ - if (message == null) Message(name: name, data: data) else message + if (message == null) Message(name: name, data: data) else message, ]; await invoke(PlatformMethod.publish, { TxTransportKeys.channelName: this.name, @@ -73,9 +69,8 @@ class RestChannel extends PlatformObject { } /// Sets the [options] for the channel. - Future setOptions(RestChannelOptions options) => - invoke(PlatformMethod.setRestChannelOptions, { - TxTransportKeys.channelName: name, - TxTransportKeys.options: options, - }); + Future setOptions(RestChannelOptions options) => invoke( + PlatformMethod.setRestChannelOptions, + {TxTransportKeys.channelName: name, TxTransportKeys.options: options}, + ); } diff --git a/lib/src/platform/src/rest/rest_presence.dart b/lib/src/platform/src/rest/rest_presence.dart index 84835afbd..cb961d551 100644 --- a/lib/src/platform/src/rest/rest_presence.dart +++ b/lib/src/platform/src/rest/rest_presence.dart @@ -27,7 +27,7 @@ class RestPresence extends PlatformObject { PlatformMethod.restPresenceGet, { TxTransportKeys.channelName: _restChannel.name, - if (params != null) TxTransportKeys.params: params + if (params != null) TxTransportKeys.params: params, }, ); return PaginatedResult.fromAblyMessage( @@ -50,7 +50,7 @@ class RestPresence extends PlatformObject { PlatformMethod.restPresenceHistory, { TxTransportKeys.channelName: _restChannel.name, - if (params != null) TxTransportKeys.params: params + if (params != null) TxTransportKeys.params: params, }, ); return PaginatedResult.fromAblyMessage( diff --git a/lib/src/platform/src/streams_channel.dart b/lib/src/platform/src/streams_channel.dart index 45b156436..853b3725b 100644 --- a/lib/src/platform/src/streams_channel.dart +++ b/lib/src/platform/src/streams_channel.dart @@ -50,57 +50,70 @@ class StreamsChannel { final handlerName = '$name#$id'; late StreamController controller; - controller = StreamController.broadcast(onListen: () async { - // We need to keep this null-asserted for backwards compatibility with - // Flutter versions before 3.0.0 - // ignore: unnecessary_non_null_assertion - ServicesBinding.instance!.defaultBinaryMessenger - .setMessageHandler(handlerName, (reply) async { - if (reply == null) { - await controller.close(); - } else { - try { - controller.add(codec.decodeEnvelope(reply) as T); - } on PlatformException catch (pe) { - if (pe.details is ErrorInfo) { - throw AblyException.fromPlatformException(pe); + controller = StreamController.broadcast( + onListen: () async { + // We need to keep this null-asserted for backwards compatibility with + // Flutter versions before 3.0.0 + // ignore: unnecessary_non_null_assertion + ServicesBinding.instance!.defaultBinaryMessenger.setMessageHandler( + handlerName, + (reply) async { + if (reply == null) { + await controller.close(); } else { - controller.addError(pe); + try { + controller.add(codec.decodeEnvelope(reply) as T); + } on PlatformException catch (pe) { + if (pe.details is ErrorInfo) { + throw AblyException.fromPlatformException(pe); + } else { + controller.addError(pe); + } + } } - } - } - return reply; - }); - try { - await methodChannel.invokeMethod('listen#$id', arguments); - } on Exception catch (exception, stack) { - FlutterError.reportError(FlutterErrorDetails( - exception: exception, - stack: stack, - library: 'streams_channel', - context: DiagnosticsNode.message( - 'while activating platform stream on channel $name'), - )); - } - }, onCancel: () async { - // We need to keep this null-asserted for backwards compatibility with - // Flutter versions before 3.0.0 - // ignore: unnecessary_non_null_assertion - ServicesBinding.instance!.defaultBinaryMessenger - .setMessageHandler(handlerName, null); - try { - await methodChannel.invokeMethod('cancel#$id', arguments); - } on Exception catch (exception, stack) { - FlutterError.reportError(FlutterErrorDetails( - exception: exception, - stack: stack, - library: 'streams_channel', - context: DiagnosticsNode.message( - 'while de-activating platform stream on channel $name'), - )); - } - }); + return reply; + }, + ); + try { + await methodChannel.invokeMethod('listen#$id', arguments); + } on Exception catch (exception, stack) { + FlutterError.reportError( + FlutterErrorDetails( + exception: exception, + stack: stack, + library: 'streams_channel', + context: DiagnosticsNode.message( + 'while activating platform stream on channel $name', + ), + ), + ); + } + }, + onCancel: () async { + // We need to keep this null-asserted for backwards compatibility with + // Flutter versions before 3.0.0 + // ignore: unnecessary_non_null_assertion + ServicesBinding.instance!.defaultBinaryMessenger.setMessageHandler( + handlerName, + null, + ); + try { + await methodChannel.invokeMethod('cancel#$id', arguments); + } on Exception catch (exception, stack) { + FlutterError.reportError( + FlutterErrorDetails( + exception: exception, + stack: stack, + library: 'streams_channel', + context: DiagnosticsNode.message( + 'while de-activating platform stream on channel $name', + ), + ), + ); + } + }, + ); return controller.stream; } } diff --git a/lib/src/push_notifications/src/admin/push_device_registrations.dart b/lib/src/push_notifications/src/admin/push_device_registrations.dart index 3666c7d6a..90ba8bb66 100644 --- a/lib/src/push_notifications/src/admin/push_device_registrations.dart +++ b/lib/src/push_notifications/src/admin/push_device_registrations.dart @@ -5,17 +5,12 @@ abstract class PushDeviceRegistrations { /// Retrieves the [DeviceDetails] of a device registered /// to receive push notifications using the `id` property of a /// [DeviceDetails] object, or by directly using the unique [deviceId]. - Future get({ - DeviceDetails? deviceDetails, - String? deviceId, - }); + Future get({DeviceDetails? deviceDetails, String? deviceId}); /// Retrieves all devices matching the filter [params] provided. /// Returns a [PaginatedResult] object, containing an array of [DeviceDetails] /// objects. - Future> list( - DeviceRegistrationParams params, - ); + Future> list(DeviceRegistrationParams params); /// Registers or updates a [deviceDetails] object with Ably. Returns the new, /// or updated [DeviceDetails] object. @@ -24,10 +19,7 @@ abstract class PushDeviceRegistrations { /// Removes a device registered to receive push notifications from Ably using /// the id property of a [deviceDetails] object, or by directly using the /// unique [deviceId]. - Future remove({ - DeviceDetails? deviceDetails, - String? deviceId, - }); + Future remove({DeviceDetails? deviceDetails, String? deviceId}); /// Removes all devices registered to receive push notifications from Ably /// matching the filter [params] provided. diff --git a/lib/src/push_notifications/src/device_push_details.dart b/lib/src/push_notifications/src/device_push_details.dart index 761b8f1fb..f3ee57f7d 100644 --- a/lib/src/push_notifications/src/device_push_details.dart +++ b/lib/src/push_notifications/src/device_push_details.dart @@ -17,9 +17,5 @@ class DevicePushDetails { /// @nodoc /// Initializes an instance without any defaults - const DevicePushDetails({ - this.errorReason, - this.recipient, - this.state, - }); + const DevicePushDetails({this.errorReason, this.recipient, this.state}); } diff --git a/lib/src/push_notifications/src/ios_notification_settings.dart b/lib/src/push_notifications/src/ios_notification_settings.dart index a054ed0a2..cf5d1eb82 100644 --- a/lib/src/push_notifications/src/ios_notification_settings.dart +++ b/lib/src/push_notifications/src/ios_notification_settings.dart @@ -26,31 +26,19 @@ enum UNAuthorizationStatus { /// Constants indicating the presentation styles for alerts. /// /// [Apple docs](https://developer.apple.com/documentation/usernotifications/unalertstyle) -enum UNAlertStyle { - none, - banner, - alert, -} +enum UNAlertStyle { none, banner, alert } /// @nodoc /// Constants that indicate the current status of a notification setting. /// /// [Apple docs](https://developer.apple.com/documentation/usernotifications/unnotificationsetting) -enum UNNotificationSetting { - notSupported, - disabled, - enabled, -} +enum UNNotificationSetting { notSupported, disabled, enabled } /// @nodoc /// Constants indicating the style previewing a notification's content. /// /// [Apple docs](https://developer.apple.com/documentation/usernotifications/unshowpreviewssetting) -enum UNShowPreviewsSetting { - always, - whenAuthenticated, - never, -} +enum UNShowPreviewsSetting { always, whenAuthenticated, never } /// @nodoc /// The object for managing notification-related settings and the authorization diff --git a/lib/src/push_notifications/src/local_device.dart b/lib/src/push_notifications/src/local_device.dart index 8853ab13e..d48886072 100644 --- a/lib/src/push_notifications/src/local_device.dart +++ b/lib/src/push_notifications/src/local_device.dart @@ -19,11 +19,11 @@ class LocalDevice extends DeviceDetails { this.deviceIdentityToken, this.deviceSecret, }) : super( - clientId: deviceDetails.clientId, - formFactor: deviceDetails.formFactor, - id: deviceDetails.id, - metadata: deviceDetails.metadata, - platform: deviceDetails.platform, - push: deviceDetails.push, - ); + clientId: deviceDetails.clientId, + formFactor: deviceDetails.formFactor, + id: deviceDetails.id, + metadata: deviceDetails.metadata, + platform: deviceDetails.platform, + push: deviceDetails.push, + ); } diff --git a/lib/src/push_notifications/src/notification.dart b/lib/src/push_notifications/src/notification.dart index cfe0acfb2..88b2dfc99 100644 --- a/lib/src/push_notifications/src/notification.dart +++ b/lib/src/push_notifications/src/notification.dart @@ -17,15 +17,12 @@ class Notification { /// @nodoc /// Initializes an instance without any defaults. - const Notification({ - required this.title, - this.body, - }); + const Notification({required this.title, this.body}); /// @nodoc /// Creates an instance from the map. factory Notification.fromMap(Map map) => Notification( - body: map[TxNotification.body] as String?, - title: map[TxNotification.title] as String? ?? '', - ); + body: map[TxNotification.body] as String?, + title: map[TxNotification.title] as String? ?? '', + ); } diff --git a/lib/src/push_notifications/src/push.dart b/lib/src/push_notifications/src/push.dart index bd1db2d87..a9a5c6dc6 100644 --- a/lib/src/push_notifications/src/push.dart +++ b/lib/src/push_notifications/src/push.dart @@ -25,15 +25,13 @@ class Push extends PlatformObject { /// @nodoc /// Pass an Ably realtime or rest client. - Push({ - this.realtime, - this.rest, - }) : super() { + Push({this.realtime, this.rest}) : super() { final ablyClientNotPresent = rest == null && realtime == null; final moreThanOneAblyClientPresent = rest != null && realtime != null; if (ablyClientNotPresent || moreThanOneAblyClientPresent) { throw Exception( - 'Specify one Ably client when creating ${(Push).toString()}.'); + 'Specify one Ably client when creating ${(Push).toString()}.', + ); } } @@ -105,7 +103,8 @@ class Push extends PlatformObject { Future getNotificationSettings() async { if (io.Platform.isIOS) { return invokeRequest( - PlatformMethod.pushGetNotificationSettings); + PlatformMethod.pushGetNotificationSettings, + ); } else { throw UnsupportedError('getNotificationSettings is only valid on iOS.'); } diff --git a/lib/src/push_notifications/src/push_channel.dart b/lib/src/push_notifications/src/push_channel.dart index 2d134620d..5afe8641c 100644 --- a/lib/src/push_notifications/src/push_channel.dart +++ b/lib/src/push_notifications/src/push_channel.dart @@ -20,7 +20,8 @@ class PushChannel extends PlatformObject { final moreThanOneAblyClientPresent = rest != null && realtime != null; if (ablyClientNotPresent || moreThanOneAblyClientPresent) { throw Exception( - 'Specify one Ably client when creating ${(Push).toString()}.'); + 'Specify one Ably client when creating ${(Push).toString()}.', + ); } } @@ -31,24 +32,28 @@ class PushChannel extends PlatformObject { : (rest as Rest).handle; /// Subscribes the device to push notifications for the channel. - Future subscribeDevice() => invoke( - PlatformMethod.pushSubscribeDevice, {TxTransportKeys.channelName: _name}); + Future subscribeDevice() => invoke(PlatformMethod.pushSubscribeDevice, { + TxTransportKeys.channelName: _name, + }); /// Unsubscribes the device from receiving push notifications for the channel. Future unsubscribeDevice() => invoke( - PlatformMethod.pushUnsubscribeDevice, - {TxTransportKeys.channelName: _name}); + PlatformMethod.pushUnsubscribeDevice, + {TxTransportKeys.channelName: _name}, + ); /// Subscribes all devices associated with the current device's `clientId` to /// push notifications for the channel. - Future subscribeClient() => invoke( - PlatformMethod.pushSubscribeClient, {TxTransportKeys.channelName: _name}); + Future subscribeClient() => invoke(PlatformMethod.pushSubscribeClient, { + TxTransportKeys.channelName: _name, + }); /// Unsubscribes all devices associated with the current device's `clientId` /// from receiving push notifications for the channel. Future unsubscribeClient() => invoke( - PlatformMethod.pushUnsubscribeClient, - {TxTransportKeys.channelName: _name}); + PlatformMethod.pushUnsubscribeClient, + {TxTransportKeys.channelName: _name}, + ); /// Retrieves all push subscriptions for the channel. /// @@ -60,7 +65,8 @@ class PushChannel extends PlatformObject { /// Returns a [PaginatedResult] object containing a list of /// [PushChannelSubscription] objects. Future> listSubscriptions( - Map params) async { + Map params, + ) async { if (!params.containsKey('deviceId') && !params.containsKey('clientId') && !params.containsKey('deviceClientId') && @@ -68,7 +74,8 @@ class PushChannel extends PlatformObject { // This error only happen on Androids. They are thrown here // for both platforms (iOS/ Android) to make the API more consistent. throw AblyException( - message: "expected parameter 'deviceId', 'clientId', " + message: + "expected parameter 'deviceId', 'clientId', " "'deviceClientId', and/or 'channel'", ); } @@ -79,6 +86,7 @@ class PushChannel extends PlatformObject { ); return PaginatedResult.fromAblyMessage( - AblyMessage.castFrom>(message)); + AblyMessage.castFrom>(message), + ); } } diff --git a/lib/src/push_notifications/src/push_channel_subscriptions.dart b/lib/src/push_notifications/src/push_channel_subscriptions.dart index 0d1b3e8d3..bfea3dd85 100644 --- a/lib/src/push_notifications/src/push_channel_subscriptions.dart +++ b/lib/src/push_notifications/src/push_channel_subscriptions.dart @@ -13,9 +13,7 @@ abstract class PushChannelSubscriptions { /// notifications using a [params] object. /// /// Returns a [PaginatedResult] object, containing an array of channel names. - Future> listChannels( - PushChannelsParams params, - ); + Future> listChannels(PushChannelsParams params); /// Subscribes a device, or a group of devices sharing the same `clientId` to /// push notifications on a channel, using the [subscription] object. diff --git a/lib/src/push_notifications/src/push_notification_events.dart b/lib/src/push_notifications/src/push_notification_events.dart index f36ff76ea..db3ec5f39 100644 --- a/lib/src/push_notifications/src/push_notification_events.dart +++ b/lib/src/push_notifications/src/push_notification_events.dart @@ -21,7 +21,8 @@ abstract class PushNotificationEvents { /// notifications while the app is in the foreground, manually create one /// when a [onMessage] or [BackgroundMessageHandler] is called. void setOnShowNotificationInForeground( - Future Function(RemoteMessage message) callback); + Future Function(RemoteMessage message) callback, + ); /// A stream that emmits messages while the app is in the foreground. Stream get onMessage; diff --git a/lib/src/push_notifications/src/remote_message.dart b/lib/src/push_notifications/src/remote_message.dart index cb7e95f76..1b393b7cd 100644 --- a/lib/src/push_notifications/src/remote_message.dart +++ b/lib/src/push_notifications/src/remote_message.dart @@ -19,24 +19,23 @@ class RemoteMessage { /// @nodoc /// Initializes an instance with [data] set to empty map - RemoteMessage({ - Map? data, - this.notification, - }) : data = data ??= {}; + RemoteMessage({Map? data, this.notification}) + : data = data ??= {}; /// @nodoc /// Create instance from a map. factory RemoteMessage.fromMap(Map map) => RemoteMessage( - data: (map[TxRemoteMessage.data] == null) - ? {} - : Map.from( - map[TxRemoteMessage.data] as Map, - ), - notification: (map[TxRemoteMessage.notification] == null) - ? null - : Notification.fromMap( - Map.from( - map[TxRemoteMessage.notification] as Map), - ), - ); + data: (map[TxRemoteMessage.data] == null) + ? {} + : Map.from( + map[TxRemoteMessage.data] as Map, + ), + notification: (map[TxRemoteMessage.notification] == null) + ? null + : Notification.fromMap( + Map.from( + map[TxRemoteMessage.notification] as Map, + ), + ), + ); } diff --git a/lib/src/realtime/src/connection_state_change.dart b/lib/src/realtime/src/connection_state_change.dart index 06efd7b00..91a63ae5d 100644 --- a/lib/src/realtime/src/connection_state_change.dart +++ b/lib/src/realtime/src/connection_state_change.dart @@ -49,6 +49,9 @@ class EnrichedConnectionStateChange { final String? connectionKey; /// @nodoc - const EnrichedConnectionStateChange( - {required this.stateChange, this.connectionId, this.connectionKey}); + const EnrichedConnectionStateChange({ + required this.stateChange, + this.connectionId, + this.connectionKey, + }); } diff --git a/lib/src/realtime/src/realtime_auth.dart b/lib/src/realtime/src/realtime_auth.dart index c6366d27e..04fc5c5c9 100644 --- a/lib/src/realtime/src/realtime_auth.dart +++ b/lib/src/realtime/src/realtime_auth.dart @@ -9,33 +9,33 @@ class RealtimeAuth extends Auth { RealtimeAuth(this._realtime); @override - Future authorize( - {AuthOptions? authOptions, TokenParams? tokenParams}) => - _realtime.invokeRequest( - PlatformMethod.realtimeAuthAuthorize, { - TxTransportKeys.options: authOptions, - TxTransportKeys.params: tokenParams - }); + Future authorize({ + AuthOptions? authOptions, + TokenParams? tokenParams, + }) => _realtime.invokeRequest( + PlatformMethod.realtimeAuthAuthorize, + {TxTransportKeys.options: authOptions, TxTransportKeys.params: tokenParams}, + ); @override Future get clientId async => _realtime.invokeRequest(PlatformMethod.realtimeAuthGetClientId); @override - Future createTokenRequest( - {AuthOptions? authOptions, TokenParams? tokenParams}) => - _realtime.invokeRequest( - PlatformMethod.realtimeAuthCreateTokenRequest, { - TxTransportKeys.options: authOptions, - TxTransportKeys.params: tokenParams - }); + Future createTokenRequest({ + AuthOptions? authOptions, + TokenParams? tokenParams, + }) => _realtime.invokeRequest( + PlatformMethod.realtimeAuthCreateTokenRequest, + {TxTransportKeys.options: authOptions, TxTransportKeys.params: tokenParams}, + ); @override - Future requestToken( - {AuthOptions? authOptions, TokenParams? tokenParams}) => - _realtime.invokeRequest( - PlatformMethod.realtimeAuthRequestToken, { - TxTransportKeys.options: authOptions, - TxTransportKeys.params: tokenParams - }); + Future requestToken({ + AuthOptions? authOptions, + TokenParams? tokenParams, + }) => _realtime.invokeRequest( + PlatformMethod.realtimeAuthRequestToken, + {TxTransportKeys.options: authOptions, TxTransportKeys.params: tokenParams}, + ); } diff --git a/lib/src/realtime/src/realtime_channel_options.dart b/lib/src/realtime/src/realtime_channel_options.dart index db525c3aa..4848172c7 100644 --- a/lib/src/realtime/src/realtime_channel_options.dart +++ b/lib/src/realtime/src/realtime_channel_options.dart @@ -28,9 +28,5 @@ class RealtimeChannelOptions { /// If a [cipherParams] is set, messages will be encrypted with the cipher. /// /// https://docs.ably.com/client-lib-development-guide/features/#TB2 - const RealtimeChannelOptions({ - this.cipherParams, - this.modes, - this.params, - }); + const RealtimeChannelOptions({this.cipherParams, this.modes, this.params}); } diff --git a/lib/src/realtime/src/realtime_history_params.dart b/lib/src/realtime/src/realtime_history_params.dart index 7435e20c9..e8e743588 100644 --- a/lib/src/realtime/src/realtime_history_params.dart +++ b/lib/src/realtime/src/realtime_history_params.dart @@ -41,12 +41,13 @@ class RealtimeHistoryParams { this.limit = 100, DateTime? start, this.untilAttach, - }) : assert(direction == 'backwards' || direction == 'forwards'), - end = end ?? DateTime.now(), - start = start ?? DateTime.fromMillisecondsSinceEpoch(0); + }) : assert(direction == 'backwards' || direction == 'forwards'), + end = end ?? DateTime.now(), + start = start ?? DateTime.fromMillisecondsSinceEpoch(0); @override - String toString() => 'RealtimeHistoryParams:' + String toString() => + 'RealtimeHistoryParams:' ' start=$start' ' end=$end' ' direction=$direction' diff --git a/lib/src/rest/src/rest_auth.dart b/lib/src/rest/src/rest_auth.dart index d9d2897d1..88aae41ad 100644 --- a/lib/src/rest/src/rest_auth.dart +++ b/lib/src/rest/src/rest_auth.dart @@ -9,31 +9,33 @@ class RestAuth extends Auth { RestAuth(this._rest); @override - Future authorize( - {AuthOptions? authOptions, TokenParams? tokenParams}) => - _rest.invokeRequest(PlatformMethod.restAuthAuthorize, { - TxTransportKeys.options: authOptions, - TxTransportKeys.params: tokenParams - }); + Future authorize({ + AuthOptions? authOptions, + TokenParams? tokenParams, + }) => _rest.invokeRequest(PlatformMethod.restAuthAuthorize, { + TxTransportKeys.options: authOptions, + TxTransportKeys.params: tokenParams, + }); @override Future get clientId async => _rest.invoke(PlatformMethod.restAuthGetClientId); @override - Future createTokenRequest( - {AuthOptions? authOptions, TokenParams? tokenParams}) => - _rest.invokeRequest( - PlatformMethod.restAuthCreateTokenRequest, { - TxTransportKeys.options: authOptions, - TxTransportKeys.params: tokenParams - }); + Future createTokenRequest({ + AuthOptions? authOptions, + TokenParams? tokenParams, + }) => _rest.invokeRequest( + PlatformMethod.restAuthCreateTokenRequest, + {TxTransportKeys.options: authOptions, TxTransportKeys.params: tokenParams}, + ); @override - Future requestToken( - {AuthOptions? authOptions, TokenParams? tokenParams}) => - _rest.invokeRequest(PlatformMethod.restAuthRequestToken, { - TxTransportKeys.options: authOptions, - TxTransportKeys.params: tokenParams - }); + Future requestToken({ + AuthOptions? authOptions, + TokenParams? tokenParams, + }) => _rest.invokeRequest(PlatformMethod.restAuthRequestToken, { + TxTransportKeys.options: authOptions, + TxTransportKeys.params: tokenParams, + }); } diff --git a/lib/src/rest/src/rest_history_params.dart b/lib/src/rest/src/rest_history_params.dart index 51575895f..ecae09cf4 100644 --- a/lib/src/rest/src/rest_history_params.dart +++ b/lib/src/rest/src/rest_history_params.dart @@ -30,12 +30,13 @@ class RestHistoryParams { DateTime? end, this.limit = 100, DateTime? start, - }) : assert(direction == 'backwards' || direction == 'forwards'), - end = end ?? DateTime.now(), - start = start ?? DateTime.fromMillisecondsSinceEpoch(0); + }) : assert(direction == 'backwards' || direction == 'forwards'), + end = end ?? DateTime.now(), + start = start ?? DateTime.fromMillisecondsSinceEpoch(0); @override - String toString() => 'RestHistoryParams:' + String toString() => + 'RestHistoryParams:' ' start=$start' ' end=$end' ' direction=$direction' diff --git a/lib/src/rest/src/rest_presence_params.dart b/lib/src/rest/src/rest_presence_params.dart index 3c082ef0e..48bec7ab3 100644 --- a/lib/src/rest/src/rest_presence_params.dart +++ b/lib/src/rest/src/rest_presence_params.dart @@ -17,9 +17,5 @@ class RestPresenceParams { /// @nodoc /// initializes with default [limit] set to 100 - RestPresenceParams({ - this.clientId, - this.connectionId, - this.limit = 100, - }); + RestPresenceParams({this.clientId, this.connectionId, this.limit = 100}); } diff --git a/pubspec.lock b/pubspec.lock index e7d20b3e8..0144121b7 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -21,34 +21,34 @@ packages: dependency: transitive description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.1" clock: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" collection: dependency: "direct main" description: name: collection - sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" url: "https://pub.dev" source: hosted - version: "1.19.0" + version: "1.19.1" fake_async: dependency: "direct dev" description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.3" flutter: dependency: "direct main" description: flutter @@ -71,26 +71,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.7" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.8" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: @@ -103,34 +103,34 @@ packages: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd" url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.20" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "0.13.0" meta: dependency: "direct main" description: name: meta - sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 + sha256: "307249ce4ff29d58a18e97f6345f539382eb9c9c29ecda628900f31de0443dd9" url: "https://pub.dev" source: hosted - version: "1.15.0" + version: "1.19.0" path: dependency: transitive description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" sky_engine: dependency: transitive description: flutter @@ -148,18 +148,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" string_scanner: dependency: transitive description: @@ -180,18 +180,18 @@ packages: dependency: transitive description: name: test_api - sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11" url: "https://pub.dev" source: hosted - version: "0.7.3" + version: "0.7.12" vector_math: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: f36f9f3be64c6198714492bb455c11056e33e2f85d9a0b676a48301e44fdcf47 url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.4.2" vm_service: dependency: transitive description: @@ -201,5 +201,5 @@ packages: source: hosted version: "14.3.0" sdks: - dart: ">=3.4.0 <4.0.0" - flutter: ">=3.18.0-18.0.pre.54" + dart: ">=3.12.0 <4.0.0" + flutter: ">=3.44.0" diff --git a/pubspec.yaml b/pubspec.yaml index 8974c9cab..73024fc7d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,8 +4,17 @@ version: 1.2.44 repository: https://github.com/ably/ably-pubsub-flutter environment: - sdk: ">=2.14.0 <4.0.0" - flutter: ">=2.5.0" + # Two iOS floors meet at Flutter 3.44: + # + # - The UIScene plugin APIs the iOS side relies on + # (`FlutterSceneLifeCycleDelegate` and + # `FlutterPluginRegistrar.addSceneDelegate:`) first shipped in 3.38. See + # PushNotifications.md. + # - 3.44 is the first release where Swift Package Manager is the default + # dependency manager rather than an opt-in experiment, which is what lets + # this plugin ship a SwiftPM manifest and retire its podspec. + sdk: ">=3.12.0 <4.0.0" + flutter: ">=3.44.0" dependencies: collection: ^1.15.0 diff --git a/test/ably_event_listener_test.dart b/test/ably_event_listener_test.dart index 3f1fb0f25..b99898292 100644 --- a/test/ably_event_listener_test.dart +++ b/test/ably_event_listener_test.dart @@ -69,8 +69,9 @@ void main() { //Checking if data received by stream is same as expected expect( - const ListEquality().equals(resultsDefault, emitter.injectables), - true); + const ListEquality().equals(resultsDefault, emitter.injectables), + true, + ); expect(const ListEquality().equals(resultsNestedPre, [1, 2]), true); expect(const ListEquality().equals(resultsNestedPost, [1]), true); }); diff --git a/test/ably_flutter_plugin_test.dart b/test/ably_flutter_plugin_test.dart index 9fd9cc46d..3b9775469 100644 --- a/test/ably_flutter_plugin_test.dart +++ b/test/ably_flutter_plugin_test.dart @@ -4,8 +4,10 @@ import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { - final channel = - MethodChannel('io.ably.flutter.plugin', StandardMethodCodec(Codec())); + final channel = MethodChannel( + 'io.ably.flutter.plugin', + StandardMethodCodec(Codec()), + ); TestWidgetsFlutterBinding.ensureInitialized(); var counter = 0; @@ -17,25 +19,25 @@ void main() { setUp(() { TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger .setMockMethodCallHandler(channel, (methodCall) async { - switch (methodCall.method) { - case PlatformMethod.resetAblyClients: - return true; + switch (methodCall.method) { + case PlatformMethod.resetAblyClients: + return true; - case PlatformMethod.getPlatformVersion: - return _platformVersion; - case PlatformMethod.getVersion: - return _nativeLibraryVersion; + case PlatformMethod.getPlatformVersion: + return _platformVersion; + case PlatformMethod.getVersion: + return _nativeLibraryVersion; - case PlatformMethod.createRest: - case PlatformMethod.createRealtime: - return ++counter; + case PlatformMethod.createRest: + case PlatformMethod.createRealtime: + return ++counter; - case PlatformMethod.publish: - case PlatformMethod.connectRealtime: - default: - return null; - } - }); + case PlatformMethod.publish: + case PlatformMethod.connectRealtime: + default: + return null; + } + }); Platform(methodChannel: channel); }); @@ -54,9 +56,7 @@ void main() { test(PlatformMethod.createRest, () async { const host = 'http://rest.ably.io/'; - final o = ClientOptions( - restHost: host, - ); + final o = ClientOptions(restHost: host); final rest = Rest(options: o); expect(await rest.handle, counter); expect(rest.options.restHost, host); diff --git a/test/mock_method_call_manager.dart b/test/mock_method_call_manager.dart index 57860137b..f9165b4f2 100644 --- a/test/mock_method_call_manager.dart +++ b/test/mock_method_call_manager.dart @@ -12,8 +12,10 @@ class MockMethodCallManager { final publishedMessages = >[]; MockMethodCallManager() { - final channel = - MethodChannel('io.ably.flutter.plugin', StandardMethodCodec(Codec())); + final channel = MethodChannel( + 'io.ably.flutter.plugin', + StandardMethodCodec(Codec()), + ); TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger .setMockMethodCallHandler(channel, handler); Platform(methodChannel: channel); @@ -23,8 +25,10 @@ class MockMethodCallManager { channels.clear(); publishedMessages.clear(); handleCounter = 0; - final channel = - MethodChannel('io.ably.flutter.plugin', StandardMethodCodec(Codec())); + final channel = MethodChannel( + 'io.ably.flutter.plugin', + StandardMethodCodec(Codec()), + ); TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger .setMockMethodCallHandler(channel, handler); Platform(methodChannel: channel); @@ -54,7 +58,9 @@ class MockMethodCallManager { // PlatformChannel. if (!isAuthenticated && clientOptions.authUrl == 'hasAuthCallback') { final channel = MethodChannel( - 'io.ably.flutter.plugin', StandardMethodCodec(Codec())); + 'io.ably.flutter.plugin', + StandardMethodCodec(Codec()), + ); await AblyMethodCallHandler(channel).onAuthCallback( AblyMessage( message: TokenParams(timestamp: DateTime.now()), @@ -75,12 +81,12 @@ class MockMethodCallManager { // PlatformChannel. if (!isAuthenticated && clientOptions.authUrl == 'hasAuthCallback') { final channel = MethodChannel( - 'io.ably.flutter.plugin', StandardMethodCodec(Codec())); + 'io.ably.flutter.plugin', + StandardMethodCodec(Codec()), + ); await AblyMethodCallHandler(channel).onRealtimeAuthCallback( AblyMessage( - message: TokenParams( - timestamp: DateTime.now(), - ), + message: TokenParams(timestamp: DateTime.now()), handle: ablyMessage.handle, ), ); @@ -95,8 +101,10 @@ class MockMethodCallManager { return null; default: - return throw Exception('Unexpected method call: ${methodCall.method}' - ' args: ${methodCall.arguments}'); + return throw Exception( + 'Unexpected method call: ${methodCall.method}' + ' args: ${methodCall.arguments}', + ); } } } diff --git a/test/models/message_test.dart b/test/models/message_test.dart index 2e683e911..9b9b54ff3 100644 --- a/test/models/message_test.dart +++ b/test/models/message_test.dart @@ -8,12 +8,12 @@ void main() { const connectionId = 'connection-id'; const data = { 'a': 'b', - 'c': [1, 2, 3] + 'c': [1, 2, 3], }; const encoding = 'msgpack'; const extras = { 'a': 'b', - 'c': [1, 2, 3] + 'c': [1, 2, 3], }; final timestamp = DateTime.now(); @@ -77,21 +77,23 @@ void main() { expect(message.hashCode == message2.hashCode, true); }); - test("#== is false and hashes don't match when attributes are not same", - () { - final message2 = Message( - id: messageId, - name: 'other-name', - clientId: clientId, - connectionId: connectionId, - data: data, - encoding: encoding, - extras: const MessageExtras(extras), - timestamp: timestamp, - ); - expect(message == message2, false); - expect(message.hashCode == message2.hashCode, false); - }); + test( + "#== is false and hashes don't match when attributes are not same", + () { + final message2 = Message( + id: messageId, + name: 'other-name', + clientId: clientId, + connectionId: connectionId, + data: data, + encoding: encoding, + extras: const MessageExtras(extras), + timestamp: timestamp, + ); + expect(message == message2, false); + expect(message.hashCode == message2.hashCode, false); + }, + ); test("#== is false and hashes don't match for different classes", () { final object = Object(); @@ -139,7 +141,7 @@ void main() { 'encoding': encoding, 'extras': extras, 'timestamp': timestamp.millisecondsSinceEpoch, - } + }, ]); final message = messages[0]; expect(message.id, messageId); @@ -167,8 +169,9 @@ void main() { expect(message.extras, null); }); test('a map of extras is allowed', () { - final message = - Message(extras: const MessageExtras({'key': 'value'})); + final message = Message( + extras: const MessageExtras({'key': 'value'}), + ); expect(message.extras!.map, const {'key': 'value'}); }); }); diff --git a/test/models/presence_message_test.dart b/test/models/presence_message_test.dart index 9c1fccf76..db4a0fa7d 100644 --- a/test/models/presence_message_test.dart +++ b/test/models/presence_message_test.dart @@ -9,12 +9,12 @@ void main() { const connectionId = 'connection-id'; const data = { 'a': 'b', - 'c': [1, 2, 3] + 'c': [1, 2, 3], }; const encoding = 'msgpack'; const extras = { 'a': 'b', - 'c': [1, 2, 3] + 'c': [1, 2, 3], }; final timestamp = DateTime.now(); group('Behaves like a model', () { @@ -68,21 +68,23 @@ void main() { expect(presenceMessage.hashCode == presenceMessage2.hashCode, true); }); - test("#== is false and hashes don't match when attributes are not same", - () { - final presenceMessage2 = PresenceMessage( - id: '123', - action: action, - clientId: clientId, - connectionId: connectionId, - data: data, - encoding: encoding, - extras: const MessageExtras(extras), - timestamp: timestamp, - ); - expect(presenceMessage == presenceMessage2, false); - expect(presenceMessage.hashCode == presenceMessage2.hashCode, false); - }); + test( + "#== is false and hashes don't match when attributes are not same", + () { + final presenceMessage2 = PresenceMessage( + id: '123', + action: action, + clientId: clientId, + connectionId: connectionId, + data: data, + encoding: encoding, + extras: const MessageExtras(extras), + timestamp: timestamp, + ); + expect(presenceMessage == presenceMessage2, false); + expect(presenceMessage.hashCode == presenceMessage2.hashCode, false); + }, + ); test("#== is false and hashes don't match for different classes", () { final object = Object(); @@ -93,22 +95,32 @@ void main() { group('memberKey attribute', () { test('is connectionId:clientId', () { - final presenceMessage = - PresenceMessage(clientId: clientId, connectionId: connectionId); + final presenceMessage = PresenceMessage( + clientId: clientId, + connectionId: connectionId, + ); expect(presenceMessage.memberKey, '$connectionId:$clientId'); }); test('is unique with the same client id across multiple connections', () { - final presenceMessage = - PresenceMessage(clientId: clientId, connectionId: connectionId); - final presenceMessage2 = - PresenceMessage(clientId: clientId, connectionId: 'different'); + final presenceMessage = PresenceMessage( + clientId: clientId, + connectionId: connectionId, + ); + final presenceMessage2 = PresenceMessage( + clientId: clientId, + connectionId: 'different', + ); expect(presenceMessage.memberKey == presenceMessage2.memberKey, false); }); test('is unique with a single connection and different client_ids', () { - final presenceMessage = - PresenceMessage(clientId: clientId, connectionId: connectionId); - final presenceMessage2 = - PresenceMessage(clientId: 'different', connectionId: connectionId); + final presenceMessage = PresenceMessage( + clientId: clientId, + connectionId: connectionId, + ); + final presenceMessage2 = PresenceMessage( + clientId: 'different', + connectionId: connectionId, + ); expect(presenceMessage.memberKey == presenceMessage2.memberKey, false); }); }); @@ -123,7 +135,7 @@ void main() { 'data': data, 'encoding': encoding, 'extras': extras, - 'timestamp': timestamp.millisecondsSinceEpoch + 'timestamp': timestamp.millisecondsSinceEpoch, }); expect(presenceMessage.id, messageId); expect(presenceMessage.action, action); @@ -151,7 +163,7 @@ void main() { 'encoding': encoding, 'extras': extras, 'timestamp': timestamp.millisecondsSinceEpoch, - } + }, ]); final presenceMessage = presenceMessages[0]; expect(presenceMessage.id, messageId); diff --git a/test/realtime/channel_test.dart b/test/realtime/channel_test.dart index 23c1844e8..08c3da772 100644 --- a/test/realtime/channel_test.dart +++ b/test/realtime/channel_test.dart @@ -25,8 +25,12 @@ void main() { // exercise await channel.publish(name: 'name', data: 'data1'); - await channel.publish(message: Message(name: 'name', data: 'data')); - await channel.publish(messages: [Message(name: 'name', data: 'data')]); + await channel.publish( + message: Message(name: 'name', data: 'data'), + ); + await channel.publish( + messages: [Message(name: 'name', data: 'data')], + ); // verification expect(manager.publishedMessages.length, 3); @@ -34,8 +38,9 @@ void main() { final messageData = firstMessage.message as Map; expect(messageData[TxTransportKeys.channelName], 'test'); expect(messageData[TxTransportKeys.messages], isA>()); - final messages = - List.from(messageData[TxTransportKeys.messages] as List); + final messages = List.from( + messageData[TxTransportKeys.messages] as List, + ); expect(messages[0].name, 'name'); expect(messages[0].data, 'data1'); }); @@ -62,8 +67,9 @@ void main() { final messageData = firstMessage.message as Map; expect(messageData[TxTransportKeys.channelName], 'test'); expect(messageData[TxTransportKeys.messages], isA>()); - final messages = - List.from(messageData[TxTransportKeys.messages] as List); + final messages = List.from( + messageData[TxTransportKeys.messages] as List, + ); expect(messages[0].name, 'name'); expect(messages[0].data, 'data2'); }); @@ -97,8 +103,9 @@ void main() { final messageData = firstMessage.message as Map; expect(messageData[TxTransportKeys.channelName], 'test'); expect(messageData[TxTransportKeys.messages], isA>()); - final messages = - List.from(messageData[TxTransportKeys.messages] as List); + final messages = List.from( + messageData[TxTransportKeys.messages] as List, + ); expect(messages[0].name, 'name'); expect(messages[0].data, 'data3-1'); }); @@ -124,8 +131,9 @@ void main() { final messageData0 = message0.message as Map; expect(messageData0[TxTransportKeys.channelName], 'test'); expect(messageData0[TxTransportKeys.messages], isA>()); - final messages = - List.from(messageData0[TxTransportKeys.messages] as List); + final messages = List.from( + messageData0[TxTransportKeys.messages] as List, + ); expect(messages[0].name, 'name'); expect(messages[0].data, 'data4'); @@ -133,8 +141,9 @@ void main() { final messageData1 = message1.message as Map; expect(messageData1[TxTransportKeys.channelName], 'test'); expect(messageData1[TxTransportKeys.messages], isA>()); - final messages1 = - List.from(messageData1[TxTransportKeys.messages] as List); + final messages1 = List.from( + messageData1[TxTransportKeys.messages] as List, + ); expect(messages1[0].name, 'name'); expect(messages1[0].data, 'data5'); }, timeout: Timeout.none); diff --git a/test/rest/channel_test.dart b/test/rest/channel_test.dart index 01a00ead1..a6b5f76be 100644 --- a/test/rest/channel_test.dart +++ b/test/rest/channel_test.dart @@ -32,8 +32,9 @@ void main() { final messageData = firstMessage.message as Map; expect(messageData[TxTransportKeys.channelName], 'test'); expect(messageData[TxTransportKeys.messages], isA>()); - final messages = - List.from(messageData[TxTransportKeys.messages] as List); + final messages = List.from( + messageData[TxTransportKeys.messages] as List, + ); expect(messages[0].name, 'name'); expect(messages[0].data, 'data1'); }); @@ -59,8 +60,9 @@ void main() { final messageData = firstMessage.message as Map; expect(messageData[TxTransportKeys.channelName], 'test'); expect(messageData[TxTransportKeys.messages], isA>()); - final messages = - List.from(messageData[TxTransportKeys.messages] as List); + final messages = List.from( + messageData[TxTransportKeys.messages] as List, + ); expect(messages[0].name, 'name'); expect(messages[0].data, 'data2'); }); @@ -95,8 +97,9 @@ void main() { final messageData = firstMessage.message as Map; expect(messageData[TxTransportKeys.channelName], 'test'); expect(messageData[TxTransportKeys.messages], isA>()); - final messages = - List.from(messageData[TxTransportKeys.messages] as List); + final messages = List.from( + messageData[TxTransportKeys.messages] as List, + ); expect(messages[0].name, 'name'); expect(messages[0].data, 'data3-1'); }); @@ -122,8 +125,9 @@ void main() { final messageData0 = message0.message as Map; expect(messageData0[TxTransportKeys.channelName], 'test'); expect(messageData0[TxTransportKeys.messages], isA>()); - final messages = - List.from(messageData0[TxTransportKeys.messages] as List); + final messages = List.from( + messageData0[TxTransportKeys.messages] as List, + ); expect(messages[0].name, 'name'); expect(messages[0].data, 'data4'); @@ -131,8 +135,9 @@ void main() { final messageData1 = message1.message as Map; expect(messageData1[TxTransportKeys.channelName], 'test'); expect(messageData1[TxTransportKeys.messages], isA>()); - final messages2 = - List.from(messageData1[TxTransportKeys.messages] as List); + final messages2 = List.from( + messageData1[TxTransportKeys.messages] as List, + ); expect(messages2[0].name, 'name'); expect(messages2[0].data, 'data5'); }, timeout: Timeout.none); diff --git a/test/rest/channels_test.dart b/test/rest/channels_test.dart index fa3c16d1d..e1a15bdf2 100644 --- a/test/rest/channels_test.dart +++ b/test/rest/channels_test.dart @@ -64,10 +64,7 @@ void main() { expect( channels.where((e) => e.name.endsWith('3')).map((e) => e.name).toList(), - orderedEquals(const [ - 'channel-3', - 'channel-33', - ]), + orderedEquals(const ['channel-3', 'channel-33']), ); }); @@ -86,8 +83,7 @@ void main() { }); group('#release', () { - test( - '(RSN4a) Takes one argument, the channel name,' + test('(RSN4a) Takes one argument, the channel name,' ' and releases the corresponding channel entity', () { channels ..get('channel-1') @@ -98,8 +94,7 @@ void main() { expect(channels.exists('channel-1'), false); }); - test( - '(RSN4b) Calling release() with a channel name' + test('(RSN4b) Calling release() with a channel name' ' that does not correspond to an extant channel' ' entity must return without error', () { channels diff --git a/test_integration/ios/.gitignore b/test_integration/ios/.gitignore index e96ef602b..eb5573aef 100644 --- a/test_integration/ios/.gitignore +++ b/test_integration/ios/.gitignore @@ -20,6 +20,7 @@ Flutter/Flutter.podspec Flutter/Generated.xcconfig Flutter/app.flx Flutter/app.zip +Flutter/ephemeral/ Flutter/flutter_assets/ Flutter/flutter_export_environment.sh ServiceDefinitions.json diff --git a/test_integration/ios/Flutter/AppFrameworkInfo.plist b/test_integration/ios/Flutter/AppFrameworkInfo.plist index 8c6e56146..ab8e063fe 100644 --- a/test_integration/ios/Flutter/AppFrameworkInfo.plist +++ b/test_integration/ios/Flutter/AppFrameworkInfo.plist @@ -20,7 +20,5 @@ ???? CFBundleVersion 1.0 - MinimumOSVersion - 12.0 diff --git a/test_integration/ios/Podfile b/test_integration/ios/Podfile index 2c068c404..10f3c9b47 100644 --- a/test_integration/ios/Podfile +++ b/test_integration/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '12.0' +platform :ios, '13.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/test_integration/ios/Podfile.lock b/test_integration/ios/Podfile.lock index 9b1ef0c69..16743f678 100644 --- a/test_integration/ios/Podfile.lock +++ b/test_integration/ios/Podfile.lock @@ -27,11 +27,11 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: Ably: 1756d6590a572809c10fc4bcc32e05fe9e7867d7 - ably_flutter: 95785161fc2858c7be524af4334925d30682b3b0 + ably_flutter: 03c57b59bcbf92ba2bd6910f10ed4e155bced176 AblyDeltaCodec: add5d06a756b3581b12aab5b5500a320b8c55bea - Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 msgpack: c85f6251873059738472ae136951cec5f30f3251 -PODFILE CHECKSUM: 4e8f8b2be68aeea4c0d5beb6ff1e79fface1d048 +PODFILE CHECKSUM: cc1f88378b4bfcf93a6ce00d2c587857c6008d3b COCOAPODS: 1.16.2 diff --git a/test_integration/ios/Runner.xcodeproj/project.pbxproj b/test_integration/ios/Runner.xcodeproj/project.pbxproj index b2609ce9a..2006eada7 100644 --- a/test_integration/ios/Runner.xcodeproj/project.pbxproj +++ b/test_integration/ios/Runner.xcodeproj/project.pbxproj @@ -342,7 +342,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -428,7 +428,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -477,7 +477,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/test_integration/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/test_integration/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 4f746537f..fc5ae0316 100644 --- a/test_integration/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/test_integration/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -26,6 +26,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" shouldUseLaunchSchemeArgsEnv = "YES"> @@ -45,6 +46,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/test_integration/lib/app_provisioning.dart b/test_integration/lib/app_provisioning.dart index 652ccfb12..f47e0712c 100644 --- a/test_integration/lib/app_provisioning.dart +++ b/test_integration/lib/app_provisioning.dart @@ -66,30 +66,27 @@ class AppProvisioning { /// A set of base headers for HTTP requests Map get _requestHeaders => { - 'Content-Type': 'application/json', - 'Accept': 'application/json', - }; + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }; /// App spec used to provision the app /// /// See: https://docs.ably.com/client-lib-development-guide/test-api Map> get _appSpec => { - 'namespaces': [ - { - 'id': 'pushenabled', - 'pushEnabled': pushEnabled, - } - ], - 'keys': [ - { - // The need to use jsonEncode here is a requirement of the - // Sandbox Test API. The capability map has to be JSON encoded - // as a string and then appropriately escaped in order for - // presentation within a string value. - 'capability': jsonEncode(keyCapabilities), - }, - ], - }; + 'namespaces': [ + {'id': 'pushenabled', 'pushEnabled': pushEnabled}, + ], + 'keys': [ + { + // The need to use jsonEncode here is a requirement of the + // Sandbox Test API. The capability map has to be JSON encoded + // as a string and then appropriately escaped in order for + // presentation within a string value. + 'capability': jsonEncode(keyCapabilities), + }, + ], + }; /// Makes request to configured Ably provisioning URL and returns a /// new key for test application instance @@ -102,8 +99,10 @@ class AppProvisioning { if (response.statusCode != HttpStatus.created) { log("Server didn't return success. ${response.body}"); - throw HttpException("Server didn't return success." - ' Status: ${response.statusCode} : ${response.body}'); + throw HttpException( + "Server didn't return success." + ' Status: ${response.statusCode} : ${response.body}', + ); } final responseBody = jsonDecode(response.body) as Map; @@ -121,8 +120,10 @@ class AppProvisioning { if (response.statusCode != HttpStatus.ok) { log("Server didn't return success. ${response.body}"); - throw HttpException("Server didn't return success." - ' Status: ${response.statusCode} : ${response.body}'); + throw HttpException( + "Server didn't return success." + ' Status: ${response.statusCode} : ${response.body}', + ); } return Map.castFrom( diff --git a/test_integration/lib/config/test_factory.dart b/test_integration/lib/config/test_factory.dart index d86dc8bba..a38b1e2a5 100644 --- a/test_integration/lib/config/test_factory.dart +++ b/test_integration/lib/config/test_factory.dart @@ -36,10 +36,11 @@ import 'package:ably_flutter_integration_test/test/rest/rest_publish_with_auth_c import 'package:ably_flutter_integration_test/test/rest/rest_request_token_test.dart'; import 'package:ably_flutter_integration_test/test/rest/rest_time_test.dart'; -typedef TestFactory = Future> Function({ - required Reporter reporter, - Map? payload, -}); +typedef TestFactory = + Future> Function({ + required Reporter reporter, + Map? payload, + }); final testFactory = { // platform and app key tests diff --git a/test_integration/lib/driver_data_handler.dart b/test_integration/lib/driver_data_handler.dart index 6f4d14830..0943c8e6d 100644 --- a/test_integration/lib/driver_data_handler.dart +++ b/test_integration/lib/driver_data_handler.dart @@ -17,10 +17,7 @@ Future requestDataForTest( /// Used to encode and decode messages between driver test and test widget. class TestControlMessage { - const TestControlMessage( - this.testName, { - this.payload, - }); + const TestControlMessage(this.testName, {this.payload}); static const testNameKey = 'testName'; static const payloadKey = 'payload'; @@ -39,10 +36,7 @@ class TestControlMessage { payload: jsonValue[payloadKey] as Map?, ); - Map toJson() => { - testNameKey: testName, - payloadKey: payload, - }; + Map toJson() => {testNameKey: testName, payloadKey: payload}; String toJsonEncoded() => json.encode(toJson()); @@ -79,10 +73,10 @@ class TestControlResponseMessage { ); Map toJson() => { - testNameKey: testName, - payloadKey: payload, - logKey: log, - }; + testNameKey: testName, + payloadKey: payload, + logKey: log, + }; String toJsonEncoded() => json.encode(toJson()); diff --git a/test_integration/lib/factory/error_handler.dart b/test_integration/lib/factory/error_handler.dart index 73494efe1..b39a7dfe8 100644 --- a/test_integration/lib/factory/error_handler.dart +++ b/test_integration/lib/factory/error_handler.dart @@ -4,9 +4,11 @@ import 'package:flutter/foundation.dart'; /// to the test driver. class ErrorHandler { static Map encodeFlutterError(FlutterErrorDetails details) { - print('Caught FlutterError::\n' - 'exception: ${details.exception}\n' - 'stack: ${details.stack}'); + print( + 'Caught FlutterError::\n' + 'exception: ${details.exception}\n' + 'stack: ${details.stack}', + ); return { 'exceptionType': '${details.exception.runtimeType}', @@ -20,9 +22,11 @@ class ErrorHandler { static Map encodeException(Object error, StackTrace stack) { print(error); print(stack); - print('Caught Exception::\n' - 'error: $error\n' - 'stack: $stack'); + print( + 'Caught Exception::\n' + 'error: $error\n' + 'stack: $stack', + ); return { 'exceptionType': '${error.runtimeType}', diff --git a/test_integration/lib/factory/reporter.dart b/test_integration/lib/factory/reporter.dart index 112eb513d..469ff12ef 100644 --- a/test_integration/lib/factory/reporter.dart +++ b/test_integration/lib/factory/reporter.dart @@ -8,10 +8,8 @@ class Reporter { final DispatcherController controller; final Completer response; - Reporter( - this.message, - this.controller, - ) : response = Completer(); + Reporter(this.message, this.controller) + : response = Completer(); String get testName => message.testName; diff --git a/test_integration/lib/test/basic_test.dart b/test_integration/lib/test/basic_test.dart index e34593744..22c4a69a8 100644 --- a/test_integration/lib/test/basic_test.dart +++ b/test_integration/lib/test/basic_test.dart @@ -21,8 +21,5 @@ Future> testPlatformAndAblyVersion({ final _platformVersion = await platformVersion(); final _ablyVersion = await version(); - return { - 'platformVersion': _platformVersion, - 'ablyVersion': _ablyVersion, - }; + return {'platformVersion': _platformVersion, 'ablyVersion': _ablyVersion}; } diff --git a/test_integration/lib/test/crypto/crypto_ensure_supported_key_length_test.dart b/test_integration/lib/test/crypto/crypto_ensure_supported_key_length_test.dart index df168a881..1309871ea 100644 --- a/test_integration/lib/test/crypto/crypto_ensure_supported_key_length_test.dart +++ b/test_integration/lib/test/crypto/crypto_ensure_supported_key_length_test.dart @@ -36,8 +36,9 @@ Future> testCryptoEnsureSupportedKeyLength({ } try { - final keyWith127BitLength = - Uint8List.fromList(List.generate(127, (index) => index)); + final keyWith127BitLength = Uint8List.fromList( + List.generate(127, (index) => index), + ); Crypto.ensureSupportedKeyLength(keyWith127BitLength); } on AblyException catch (exception) { keyWith127BitLengthException = encodeAblyException(exception); diff --git a/test_integration/lib/test/crypto/crypto_get_default_params.dart b/test_integration/lib/test/crypto/crypto_get_default_params.dart index 8f116537c..e582646a0 100644 --- a/test_integration/lib/test/crypto/crypto_get_default_params.dart +++ b/test_integration/lib/test/crypto/crypto_get_default_params.dart @@ -13,8 +13,9 @@ Future> testCryptoGetDefaultParams({ final keyWithDefaultLength = await Crypto.generateRandomKey(); - final keyWith127BitLength = - Uint8List.fromList(List.generate(127, (index) => index)); + final keyWith127BitLength = Uint8List.fromList( + List.generate(127, (index) => index), + ); try { await Crypto.getDefaultParams(key: keyWith127BitLength); diff --git a/test_integration/lib/test/realtime/realtime_auth_client_id_test.dart b/test_integration/lib/test/realtime/realtime_auth_client_id_test.dart index 9575bc6d4..4e23a235b 100644 --- a/test_integration/lib/test/realtime/realtime_auth_client_id_test.dart +++ b/test_integration/lib/test/realtime/realtime_auth_client_id_test.dart @@ -16,19 +16,18 @@ Future> testRealtimeAuthClientId({ logLevel: LogLevel.error, ); - final ablyForToken = Rest( - options: clientOptionsForToken, - ); + final ablyForToken = Rest(options: clientOptionsForToken); /* get first token */ final firstToken = await ablyForToken.auth.requestToken(); final clientOptions = ClientOptions( - key: appKey, - environment: 'sandbox', - useTokenAuth: true, - autoConnect: false, - clientId: 'testClientId', - tokenDetails: firstToken); + key: appKey, + environment: 'sandbox', + useTokenAuth: true, + autoConnect: false, + clientId: 'testClientId', + tokenDetails: firstToken, + ); final realtime = Realtime(options: clientOptions); await realtime.connect(); diff --git a/test_integration/lib/test/realtime/realtime_auth_url_test.dart b/test_integration/lib/test/realtime/realtime_auth_url_test.dart index cea621364..2c55515ce 100644 --- a/test_integration/lib/test/realtime/realtime_auth_url_test.dart +++ b/test_integration/lib/test/realtime/realtime_auth_url_test.dart @@ -20,19 +20,18 @@ Future> testCreateRealtimeWithAuthUrl({ fallbackHosts: ['a.ably-realtime.com', 'b.ably-realtime.com'], ); - final ablyForToken = Rest( - options: clientOptionsForToken, - ); + final ablyForToken = Rest(options: clientOptionsForToken); final tokenDetails = await ablyForToken.auth.requestToken(); final authUrl = 'https://echo.ably.io/?body=${Uri.encodeComponent(tokenDetails.token!)}'; final options = ClientOptions( - authUrl: authUrl, - environment: 'sandbox', - useTokenAuth: true, - autoConnect: false, - logLevel: LogLevel.error); + authUrl: authUrl, + environment: 'sandbox', + useTokenAuth: true, + autoConnect: false, + logLevel: LogLevel.error, + ); final realtime = Realtime(options: options); final completer = Completer(); realtime.connection.on().listen((stateChange) { @@ -45,8 +44,10 @@ Future> testCreateRealtimeWithAuthUrl({ throw Error(); } - await completer.future - .timeout(const Duration(seconds: 30), onTimeout: _onTimeout); + await completer.future.timeout( + const Duration(seconds: 30), + onTimeout: _onTimeout, + ); return {'handle': await realtime.handle}; } diff --git a/test_integration/lib/test/realtime/realtime_authorize_test.dart b/test_integration/lib/test/realtime/realtime_authorize_test.dart index c7497c16c..f152833e7 100644 --- a/test_integration/lib/test/realtime/realtime_authorize_test.dart +++ b/test_integration/lib/test/realtime/realtime_authorize_test.dart @@ -16,32 +16,33 @@ Future> testRealtimeAuthroize({ logLevel: LogLevel.error, ); - final ablyForToken = Rest( - options: clientOptionsForToken, - ); + final ablyForToken = Rest(options: clientOptionsForToken); /* get first token */ final firstToken = await ablyForToken.auth.requestToken(); final clientOptions = ClientOptions( - key: appKey, - environment: 'sandbox', - useTokenAuth: true, - autoConnect: false, - tokenDetails: firstToken); + key: appKey, + environment: 'sandbox', + useTokenAuth: true, + autoConnect: false, + tokenDetails: firstToken, + ); final realtime = Realtime(options: clientOptions); await realtime.connect(); const tokenParams = TokenParams(ttl: 20000); - Future authCallback(params) async => TokenRequest.fromMap( - await AppProvisioning().getTokenRequest(), - ); + Future authCallback(params) async => + TokenRequest.fromMap(await AppProvisioning().getTokenRequest()); final authOptions = AuthOptions( - key: appKey, - useTokenAuth: true, - authCallback: authCallback, - authMethod: 'GET'); - final refreshedToken = await realtime.auth - .authorize(authOptions: authOptions, tokenParams: tokenParams); + key: appKey, + useTokenAuth: true, + authCallback: authCallback, + authMethod: 'GET', + ); + final refreshedToken = await realtime.auth.authorize( + authOptions: authOptions, + tokenParams: tokenParams, + ); //tokens must be different if (refreshedToken == firstToken) { throw Error(); diff --git a/test_integration/lib/test/realtime/realtime_encrypted_publish_test.dart b/test_integration/lib/test/realtime/realtime_encrypted_publish_test.dart index dee384131..d8c800414 100644 --- a/test_integration/lib/test/realtime/realtime_encrypted_publish_test.dart +++ b/test_integration/lib/test/realtime/realtime_encrypted_publish_test.dart @@ -12,8 +12,9 @@ Future> testRealtimeEncryptedPublish({ reporter.reportLog('init start'); final appKey = await AppProvisioning().provisionApp(); - final cipherParams = - await Crypto.getDefaultParams(key: TestConstants.encryptedChannelKey); + final cipherParams = await Crypto.getDefaultParams( + key: TestConstants.encryptedChannelKey, + ); final channelOptions = RealtimeChannelOptions(cipherParams: cipherParams); @@ -29,9 +30,7 @@ Future> testRealtimeEncryptedPublish({ await channel.setOptions(channelOptions); await publishMessages(channel); - return { - 'handle': await realtime.handle, - }; + return {'handle': await realtime.handle}; } Future> testRealtimeEncryptedPublishSpec({ @@ -41,8 +40,9 @@ Future> testRealtimeEncryptedPublishSpec({ const clientId = 'clientId'; final appKey = await AppProvisioning().provisionApp(); - final cipherParams = - await Crypto.getDefaultParams(key: TestConstants.encryptedChannelKey); + final cipherParams = await Crypto.getDefaultParams( + key: TestConstants.encryptedChannelKey, + ); final channelOptions = RealtimeChannelOptions(cipherParams: cipherParams); @@ -69,18 +69,17 @@ Future> testRealtimeEncryptedPublishSpec({ // Send single message object await encryptedChannel.publish( - message: Message( - name: 'single-message-name', - data: 'single-message-data', - ), + message: Message(name: 'single-message-name', data: 'single-message-data'), ); await Future.delayed(TestConstants.publishToHistoryDelay); // Send multiple message objects at once - await encryptedChannel.publish(messages: [ - Message(name: 'multi-message-name-1', data: 'multi-message-data-1'), - Message(name: 'multi-message-name-2', data: 'multi-message-data-2'), - ]); + await encryptedChannel.publish( + messages: [ + Message(name: 'multi-message-name-1', data: 'multi-message-data-1'), + Message(name: 'multi-message-name-2', data: 'multi-message-data-2'), + ], + ); await Future.delayed(TestConstants.publishToHistoryDelay); // Send message with [clientId] defined @@ -100,8 +99,9 @@ Future> testRealtimeEncryptedPublishSpec({ ); // Create encrypted channel with push capability - final encryptedPushEnabledChannel = - realtimeWithClientId.channels.get('pushenabled:test:extras'); + final encryptedPushEnabledChannel = realtimeWithClientId.channels.get( + 'pushenabled:test:extras', + ); await encryptedPushEnabledChannel.setOptions(channelOptions); // Send message with extras to encrypted push-enabled channel @@ -114,8 +114,9 @@ Future> testRealtimeEncryptedPublishSpec({ ); // Retrieve history of push-enabled channels - final historyOfEncryptedPushEnabledChannel = - await getHistory(encryptedPushEnabledChannel); + final historyOfEncryptedPushEnabledChannel = await getHistory( + encryptedPushEnabledChannel, + ); // Retreive plaintext history of encrypted channel await encryptedChannel.setOptions(const RealtimeChannelOptions()); @@ -124,8 +125,9 @@ Future> testRealtimeEncryptedPublishSpec({ RealtimeHistoryParams(direction: 'forwards'), ); await encryptedPushEnabledChannel.setOptions(const RealtimeChannelOptions()); - final historyOfPlaintextPushEnabledChannel = - await getHistory(encryptedPushEnabledChannel); + final historyOfPlaintextPushEnabledChannel = await getHistory( + encryptedPushEnabledChannel, + ); return { 'handle': await realtimeWithClientId.handle, diff --git a/test_integration/lib/test/realtime/realtime_events_test.dart b/test_integration/lib/test/realtime/realtime_events_test.dart index c98921adb..f596c46f8 100644 --- a/test_integration/lib/test/realtime/realtime_events_test.dart +++ b/test_integration/lib/test/realtime/realtime_events_test.dart @@ -31,11 +31,14 @@ Future> testRealtimeEvents({ connectionStates.add(enumValueToString(realtime.connection.state)); recordConnectionState(); //connection: initialized + realtime.connection.on().listen( + (e) => connectionStateChanges.add(encodeConnectionEvent(e)), + ); realtime.connection - .on() - .listen((e) => connectionStateChanges.add(encodeConnectionEvent(e))); - realtime.connection.on(ConnectionEvent.connected).listen( - (e) => filteredConnectionStateChanges.add(encodeConnectionEvent(e))); + .on(ConnectionEvent.connected) + .listen( + (e) => filteredConnectionStateChanges.add(encodeConnectionEvent(e)), + ); reporter.reportLog({'before realtime.connect': ''}); recordConnectionState(); //connection: initialized diff --git a/test_integration/lib/test/realtime/realtime_history_with_auth_callback_test.dart b/test_integration/lib/test/realtime/realtime_history_with_auth_callback_test.dart index 4bfe35013..c2af805f8 100644 --- a/test_integration/lib/test/realtime/realtime_history_with_auth_callback_test.dart +++ b/test_integration/lib/test/realtime/realtime_history_with_auth_callback_test.dart @@ -16,9 +16,7 @@ Future> testRealtimeHistoryWithAuthCallback({ logLevel: LogLevel.error, authCallback: (params) async { authCallbackInvoked = true; - return TokenRequest.fromMap( - await AppProvisioning().getTokenRequest(), - ); + return TokenRequest.fromMap(await AppProvisioning().getTokenRequest()); }, ), ); diff --git a/test_integration/lib/test/realtime/realtime_presence_enter_update_leave.dart b/test_integration/lib/test/realtime/realtime_presence_enter_update_leave.dart index 94b8699cf..4034f24a4 100644 --- a/test_integration/lib/test/realtime/realtime_presence_enter_update_leave.dart +++ b/test_integration/lib/test/realtime/realtime_presence_enter_update_leave.dart @@ -9,13 +9,12 @@ final logMessages = >[]; ClientOptions getClientOptions( String appKey, [ String? clientId = 'someClientId', -]) => - ClientOptions( - key: appKey, - environment: 'sandbox', - clientId: clientId, - logLevel: LogLevel.error, - ); +]) => ClientOptions( + key: appKey, + environment: 'sandbox', + clientId: clientId, + logLevel: LogLevel.error, +); Future> testRealtimePresenceEnterUpdateLeave({ required Reporter reporter, @@ -27,10 +26,9 @@ Future> testRealtimePresenceEnterUpdateLeave({ final clientIds = [null, 'client-1', 'client-2']; final clientIDClashMatrix = >[]; for (final clientId in clientIds) { - final presence = Realtime(options: getClientOptions(appKey, clientId)) - .channels - .get('test') - .presence; + final presence = Realtime( + options: getClientOptions(appKey, clientId), + ).channels.get('test').presence; for (final clientId2 in clientIds) { final result = { 'realtimeClientId': clientId, @@ -102,11 +100,9 @@ Future> testRealtimePresenceEnterUpdateLeave({ // Interact with different types of data. final actionMatrix = >[]; - final realtimePresence = - Realtime(options: getClientOptions(appKey, 'test-client')) - .channels - .get('test') - .presence; + final realtimePresence = Realtime( + options: getClientOptions(appKey, 'test-client'), + ).channels.get('test').presence; for (final message in messagesToPublish) { final action = {'data': message}; try { diff --git a/test_integration/lib/test/realtime/realtime_presence_get.dart b/test_integration/lib/test/realtime/realtime_presence_get.dart index 95adb8cd7..2dba0b88f 100644 --- a/test_integration/lib/test/realtime/realtime_presence_get.dart +++ b/test_integration/lib/test/realtime/realtime_presence_get.dart @@ -10,13 +10,12 @@ final logMessages = >[]; ClientOptions getClientOptions( String appKey, [ String clientId = 'someClientId', -]) => - ClientOptions( - key: appKey, - environment: 'sandbox', - clientId: clientId, - logLevel: LogLevel.error, - ); +]) => ClientOptions( + key: appKey, + environment: 'sandbox', + clientId: clientId, + logLevel: LogLevel.error, +); Future> testRealtimePresenceGet({ required Reporter reporter, diff --git a/test_integration/lib/test/realtime/realtime_presence_subscribe.dart b/test_integration/lib/test/realtime/realtime_presence_subscribe.dart index c8842bffa..b5a4e1c03 100644 --- a/test_integration/lib/test/realtime/realtime_presence_subscribe.dart +++ b/test_integration/lib/test/realtime/realtime_presence_subscribe.dart @@ -36,14 +36,14 @@ Future> testRealtimePresenceSubscribe({ .listen(enterMessages.add); final enterUpdateMessages = []; - final enterUpdateMessagesSubscription = presence.subscribe(actions: [ - PresenceAction.enter, - PresenceAction.update - ]).listen(enterUpdateMessages.add); + final enterUpdateMessagesSubscription = presence + .subscribe(actions: [PresenceAction.enter, PresenceAction.update]) + .listen(enterUpdateMessages.add); final partialMessages = []; - final partialMessagesSubscription = - presence.subscribe().listen(partialMessages.add); + final partialMessagesSubscription = presence.subscribe().listen( + partialMessages.add, + ); // enter-update-leave sequence with different data types to check if // data received by listeners is intact diff --git a/test_integration/lib/test/realtime/realtime_publish_test.dart b/test_integration/lib/test/realtime/realtime_publish_test.dart index 14ed51ea7..a9ca7f873 100644 --- a/test_integration/lib/test/realtime/realtime_publish_test.dart +++ b/test_integration/lib/test/realtime/realtime_publish_test.dart @@ -23,10 +23,7 @@ Future> testRealtimePublish({ ); await publishMessages(realtime.channels.get('test')); await realtime.close(); - return { - 'handle': await realtime.handle, - 'log': logMessages, - }; + return {'handle': await realtime.handle, 'log': logMessages}; } Future> testRealtimePublishSpec({ @@ -53,10 +50,12 @@ Future> testRealtimePublishSpec({ message: Message(name: 'message-name1', data: 'message-data1'), ); await Future.delayed(TestConstants.publishToHistoryDelay); - await channel.publish(messages: [ - Message(name: 'messages-name1', data: 'messages-data1'), - Message(name: 'messages-name2', data: 'messages-data2'), - ]); + await channel.publish( + messages: [ + Message(name: 'messages-name1', data: 'messages-data1'), + Message(name: 'messages-name2', data: 'messages-data2'), + ], + ); await Future.delayed(TestConstants.publishToHistoryDelay); await channel.publish( message: Message( @@ -71,7 +70,8 @@ Future> testRealtimePublishSpec({ Map? exception; try { await channel.publish( - message: Message(name: 'name', clientId: 'client-id')); + message: Message(name: 'name', clientId: 'client-id'), + ); } on AblyException catch (e) { exception = encodeAblyException(e); } @@ -82,10 +82,7 @@ Future> testRealtimePublishSpec({ // client options - no client id, message has client id final realtime2 = Realtime( - options: ClientOptions( - key: appKey, - environment: 'sandbox', - ), + options: ClientOptions(key: appKey, environment: 'sandbox'), ); final channel2 = realtime2.channels.get('test2'); diff --git a/test_integration/lib/test/realtime/realtime_publish_with_auth_callback_test.dart b/test_integration/lib/test/realtime/realtime_publish_with_auth_callback_test.dart index 669994bbe..5020f1906 100644 --- a/test_integration/lib/test/realtime/realtime_publish_with_auth_callback_test.dart +++ b/test_integration/lib/test/realtime/realtime_publish_with_auth_callback_test.dart @@ -13,9 +13,7 @@ Future> testRealtimePublishWithAuthCallback({ logLevel: LogLevel.error, authCallback: (params) async { authCallbackInvoked = true; - return TokenRequest.fromMap( - await AppProvisioning().getTokenRequest(), - ); + return TokenRequest.fromMap(await AppProvisioning().getTokenRequest()); }, ), ); diff --git a/test_integration/lib/test/realtime/realtime_subscribe.dart b/test_integration/lib/test/realtime/realtime_subscribe.dart index d81f7d1e4..b6a6e5ce8 100644 --- a/test_integration/lib/test/realtime/realtime_subscribe.dart +++ b/test_integration/lib/test/realtime/realtime_subscribe.dart @@ -31,8 +31,8 @@ Future>> _getAllMessages( final subscription = channel .subscribe(name: messageName, names: messageNames) .listen((message) { - messages.add(encodeMessage(message)); - }); + messages.add(encodeMessage(message)); + }); await publishMessages(channel); await subscription.cancel(); return messages; diff --git a/test_integration/lib/test/rest/rest_auth_client_id_test.dart b/test_integration/lib/test/rest/rest_auth_client_id_test.dart index 3cfcafea8..1d00ff5d9 100644 --- a/test_integration/lib/test/rest/rest_auth_client_id_test.dart +++ b/test_integration/lib/test/rest/rest_auth_client_id_test.dart @@ -16,19 +16,18 @@ Future> testRestAuthClientId({ logLevel: LogLevel.error, ); - final ablyForToken = Rest( - options: clientOptionsForToken, - ); + final ablyForToken = Rest(options: clientOptionsForToken); /* get first token */ final firstToken = await ablyForToken.auth.requestToken(); final clientOptions = ClientOptions( - key: appKey, - environment: 'sandbox', - useTokenAuth: true, - autoConnect: false, - clientId: 'testClientId', - tokenDetails: firstToken); + key: appKey, + environment: 'sandbox', + useTokenAuth: true, + autoConnect: false, + clientId: 'testClientId', + tokenDetails: firstToken, + ); final rest = Rest(options: clientOptions); final clientId = await rest.auth.clientId; diff --git a/test_integration/lib/test/rest/rest_authorize_test.dart b/test_integration/lib/test/rest/rest_authorize_test.dart index 44621ff21..7821a51a1 100644 --- a/test_integration/lib/test/rest/rest_authorize_test.dart +++ b/test_integration/lib/test/rest/rest_authorize_test.dart @@ -16,31 +16,32 @@ Future> testRestAuthorize({ logLevel: LogLevel.error, ); - final ablyForToken = Rest( - options: clientOptionsForToken, - ); + final ablyForToken = Rest(options: clientOptionsForToken); /* get first token */ final firstToken = await ablyForToken.auth.requestToken(); final clientOptions = ClientOptions( - key: appKey, - environment: 'sandbox', - useTokenAuth: true, - autoConnect: false, - tokenDetails: firstToken); + key: appKey, + environment: 'sandbox', + useTokenAuth: true, + autoConnect: false, + tokenDetails: firstToken, + ); final rest = Rest(options: clientOptions); const tokenParams = TokenParams(ttl: 20000); - Future authCallback(params) async => TokenRequest.fromMap( - await AppProvisioning().getTokenRequest(), - ); + Future authCallback(params) async => + TokenRequest.fromMap(await AppProvisioning().getTokenRequest()); final authOptions = AuthOptions( - key: appKey, - useTokenAuth: true, - authCallback: authCallback, - authMethod: 'GET'); - final refreshedToken = await rest.auth - .authorize(authOptions: authOptions, tokenParams: tokenParams); + key: appKey, + useTokenAuth: true, + authCallback: authCallback, + authMethod: 'GET', + ); + final refreshedToken = await rest.auth.authorize( + authOptions: authOptions, + tokenParams: tokenParams, + ); //tokens must be different if (refreshedToken == firstToken) { throw Error(); diff --git a/test_integration/lib/test/rest/rest_capability_test.dart b/test_integration/lib/test/rest/rest_capability_test.dart index cb4a49097..4d8de76e1 100644 --- a/test_integration/lib/test/rest/rest_capability_test.dart +++ b/test_integration/lib/test/rest/rest_capability_test.dart @@ -9,15 +9,18 @@ Future> testRestCapabilities({ Map? payload, }) async { final capabilitySpec = >{}; - final combinations = getAllSubsets(['publish', 'history', 'subscribe']) - .where((spec) => spec.isNotEmpty) - .toList(); + final combinations = getAllSubsets([ + 'publish', + 'history', + 'subscribe', + ]).where((spec) => spec.isNotEmpty).toList(); for (var i = 0; i < combinations.length; i++) { capabilitySpec['channel-$i'] = combinations[i]; } - final appKey = - await AppProvisioning(keyCapabilities: capabilitySpec).provisionApp(); + final appKey = await AppProvisioning( + keyCapabilities: capabilitySpec, + ).provisionApp(); final rest = Rest( options: ClientOptions( diff --git a/test_integration/lib/test/rest/rest_create_token_request_test.dart b/test_integration/lib/test/rest/rest_create_token_request_test.dart index 38d106b8d..31bd8ecd1 100644 --- a/test_integration/lib/test/rest/rest_create_token_request_test.dart +++ b/test_integration/lib/test/rest/rest_create_token_request_test.dart @@ -15,30 +15,30 @@ Future> testRestCreateTokenRequest({ logLevel: LogLevel.error, ); - final rest = Rest( - options: clientOptionsForToken, - ); + final rest = Rest(options: clientOptionsForToken); const tokenParams = TokenParams( - ttl: 20000, - capability: '{"testchannel":["publish"]}', - clientId: 'testclient'); + ttl: 20000, + capability: '{"testchannel":["publish"]}', + clientId: 'testclient', + ); final authOptions = AuthOptions( - key: appKey, - useTokenAuth: true, - authMethod: 'GET', - authHeaders: {'heardkey': 'headervalue'}, - authUrl: 'bogus', - authParams: {'paramkey': 'paramvalue'}); - final request = await rest.auth - .createTokenRequest(authOptions: authOptions, tokenParams: tokenParams); + key: appKey, + useTokenAuth: true, + authMethod: 'GET', + authHeaders: {'heardkey': 'headervalue'}, + authUrl: 'bogus', + authParams: {'paramkey': 'paramvalue'}, + ); + final request = await rest.auth.createTokenRequest( + authOptions: authOptions, + tokenParams: tokenParams, + ); if (request.ttl != tokenParams.ttl || request.clientId != tokenParams.clientId || request.capability != tokenParams.capability) { throw Error(); } - return { - 'handle': await rest.handle, - }; + return {'handle': await rest.handle}; } diff --git a/test_integration/lib/test/rest/rest_encrypted_publish_test.dart b/test_integration/lib/test/rest/rest_encrypted_publish_test.dart index 44500d32e..96c0f109d 100644 --- a/test_integration/lib/test/rest/rest_encrypted_publish_test.dart +++ b/test_integration/lib/test/rest/rest_encrypted_publish_test.dart @@ -12,8 +12,9 @@ Future> testRestEncryptedPublish({ reporter.reportLog('init start'); final appKey = await AppProvisioning().provisionApp(); - final cipherParams = - await Crypto.getDefaultParams(key: TestConstants.encryptedChannelKey); + final cipherParams = await Crypto.getDefaultParams( + key: TestConstants.encryptedChannelKey, + ); final channelOptions = RestChannelOptions(cipherParams: cipherParams); @@ -30,9 +31,7 @@ Future> testRestEncryptedPublish({ await channel.setOptions(channelOptions); await publishMessages(channel); - return { - 'handle': await rest.handle, - }; + return {'handle': await rest.handle}; } Future> testRestEncryptedPublishSpec({ @@ -42,8 +41,9 @@ Future> testRestEncryptedPublishSpec({ const clientId = 'clientId'; final appKey = await AppProvisioning().provisionApp(); - final cipherParams = - await Crypto.getDefaultParams(key: TestConstants.encryptedChannelKey); + final cipherParams = await Crypto.getDefaultParams( + key: TestConstants.encryptedChannelKey, + ); final channelOptions = RestChannelOptions(cipherParams: cipherParams); @@ -70,18 +70,17 @@ Future> testRestEncryptedPublishSpec({ // Send single message object await encryptedChannel.publish( - message: Message( - name: 'single-message-name', - data: 'single-message-data', - ), + message: Message(name: 'single-message-name', data: 'single-message-data'), ); await Future.delayed(TestConstants.publishToHistoryDelay); // Send multiple message objects at once - await encryptedChannel.publish(messages: [ - Message(name: 'multi-message-name-1', data: 'multi-message-data-1'), - Message(name: 'multi-message-name-2', data: 'multi-message-data-2'), - ]); + await encryptedChannel.publish( + messages: [ + Message(name: 'multi-message-name-1', data: 'multi-message-data-1'), + Message(name: 'multi-message-name-2', data: 'multi-message-data-2'), + ], + ); await Future.delayed(TestConstants.publishToHistoryDelay); // Send message with [clientId] defined @@ -101,8 +100,9 @@ Future> testRestEncryptedPublishSpec({ ); // Create encrypted channel with push capability - final encryptedPushEnabledChannel = - restWithClientId.channels.get('pushenabled:test:extras'); + final encryptedPushEnabledChannel = restWithClientId.channels.get( + 'pushenabled:test:extras', + ); await encryptedPushEnabledChannel.setOptions(channelOptions); // Send message with extras to encrypted push-enabled channel @@ -115,8 +115,9 @@ Future> testRestEncryptedPublishSpec({ ); // Retrieve history of push-enabled channels - final historyOfEncryptedPushEnabledChannel = - await getHistory(encryptedPushEnabledChannel); + final historyOfEncryptedPushEnabledChannel = await getHistory( + encryptedPushEnabledChannel, + ); // Retreive plaintext history of encrypted channel await encryptedChannel.setOptions(RestChannelOptions()); @@ -125,8 +126,9 @@ Future> testRestEncryptedPublishSpec({ RestHistoryParams(direction: 'forwards'), ); await encryptedPushEnabledChannel.setOptions(RestChannelOptions()); - final historyOfPlaintextPushEnabledChannel = - await getHistory(encryptedPushEnabledChannel); + final historyOfPlaintextPushEnabledChannel = await getHistory( + encryptedPushEnabledChannel, + ); return { 'handle': await restWithClientId.handle, diff --git a/test_integration/lib/test/rest/rest_history_test.dart b/test_integration/lib/test/rest/rest_history_test.dart index b84c0511c..41295e1c7 100644 --- a/test_integration/lib/test/rest/rest_history_test.dart +++ b/test_integration/lib/test/rest/rest_history_test.dart @@ -34,7 +34,9 @@ Future> testRestHistory({ await Future.delayed(TestConstants.publishToHistoryDelay); final historyForwardLimit4 = await getHistory( - channel, RestHistoryParams(direction: 'forwards', limit: 4)); + channel, + RestHistoryParams(direction: 'forwards', limit: 4), + ); await Future.delayed(TestConstants.publishToHistoryDelay); final time1 = DateTime.now(); @@ -51,10 +53,14 @@ Future> testRestHistory({ await channel.publish(name: 'history', data: 'test2'); await Future.delayed(TestConstants.publishToHistoryDelay); - final historyWithStart = - await getHistory(channel, RestHistoryParams(start: time1)); - final historyWithStartAndEnd = - await getHistory(channel, RestHistoryParams(start: time1, end: time2)); + final historyWithStart = await getHistory( + channel, + RestHistoryParams(start: time1), + ); + final historyWithStartAndEnd = await getHistory( + channel, + RestHistoryParams(start: time1, end: time2), + ); final historyAll = await getHistory(channel); return { 'handle': await rest.handle, diff --git a/test_integration/lib/test/rest/rest_history_with_auth_callback_test.dart b/test_integration/lib/test/rest/rest_history_with_auth_callback_test.dart index c5bed7103..1235c34d3 100644 --- a/test_integration/lib/test/rest/rest_history_with_auth_callback_test.dart +++ b/test_integration/lib/test/rest/rest_history_with_auth_callback_test.dart @@ -16,9 +16,7 @@ Future> testRestHistoryWithAuthCallback({ logLevel: LogLevel.error, authCallback: (params) async { authCallbackInvoked = true; - return TokenRequest.fromMap( - await AppProvisioning().getTokenRequest(), - ); + return TokenRequest.fromMap(await AppProvisioning().getTokenRequest()); }, ), ); @@ -31,6 +29,6 @@ Future> testRestHistoryWithAuthCallback({ return { 'handle': await rest.handle, - 'authCallbackInvoked': authCallbackInvoked + 'authCallbackInvoked': authCallbackInvoked, }; } diff --git a/test_integration/lib/test/rest/rest_presence_get_test.dart b/test_integration/lib/test/rest/rest_presence_get_test.dart index f9ce698fe..43d60b97f 100644 --- a/test_integration/lib/test/rest/rest_presence_get_test.dart +++ b/test_integration/lib/test/rest/rest_presence_get_test.dart @@ -10,13 +10,12 @@ final logMessages = >[]; ClientOptions getClientOptions( String appKey, [ String clientId = 'someClientId', -]) => - ClientOptions( - key: appKey, - environment: 'sandbox', - clientId: clientId, - logLevel: LogLevel.error, - ); +]) => ClientOptions( + key: appKey, + environment: 'sandbox', + clientId: clientId, + logLevel: LogLevel.error, +); Future> testRestPresenceGet({ required Reporter reporter, diff --git a/test_integration/lib/test/rest/rest_presence_history_test.dart b/test_integration/lib/test/rest/rest_presence_history_test.dart index 41b8895c3..b40bbcecb 100644 --- a/test_integration/lib/test/rest/rest_presence_history_test.dart +++ b/test_integration/lib/test/rest/rest_presence_history_test.dart @@ -26,8 +26,9 @@ Future> testRestPresenceHistory({ final historyInitial = await getPresenceHistory(channel); // creating presence history on channel - final realtimePresence = - Realtime(options: options).channels.get('test').presence; + final realtimePresence = Realtime( + options: options, + ).channels.get('test').presence; // single client enters channel await realtimePresence.enter(messagesToPublish.first[1]); // updates, multiple times with different messages diff --git a/test_integration/lib/test/rest/rest_publish_test.dart b/test_integration/lib/test/rest/rest_publish_test.dart index ef2cb78c9..77c6bfc98 100644 --- a/test_integration/lib/test/rest/rest_publish_test.dart +++ b/test_integration/lib/test/rest/rest_publish_test.dart @@ -23,10 +23,7 @@ Future> testRestPublish({ ), ); await publishMessages(rest.channels.get('test')); - return { - 'handle': await rest.handle, - 'log': logMessages, - }; + return {'handle': await rest.handle, 'log': logMessages}; } Future> testRestPublishSpec({ @@ -53,10 +50,12 @@ Future> testRestPublishSpec({ message: Message(name: 'message-name1', data: 'message-data1'), ); await Future.delayed(TestConstants.publishToHistoryDelay); - await channel.publish(messages: [ - Message(name: 'messages-name1', data: 'messages-data1'), - Message(name: 'messages-name2', data: 'messages-data2'), - ]); + await channel.publish( + messages: [ + Message(name: 'messages-name1', data: 'messages-data1'), + Message(name: 'messages-name2', data: 'messages-data2'), + ], + ); await Future.delayed(TestConstants.publishToHistoryDelay); await channel.publish( message: Message( @@ -71,7 +70,8 @@ Future> testRestPublishSpec({ Map? exception; try { await channel.publish( - message: Message(name: 'name', clientId: 'client-id')); + message: Message(name: 'name', clientId: 'client-id'), + ); } on AblyException catch (e) { exception = encodeAblyException(e); } @@ -82,10 +82,7 @@ Future> testRestPublishSpec({ // client options - no client id, message has client id final rest2 = Rest( - options: ClientOptions( - key: appKey, - environment: 'sandbox', - ), + options: ClientOptions(key: appKey, environment: 'sandbox'), ); final channel2 = rest2.channels.get('test2'); diff --git a/test_integration/lib/test/rest/rest_publish_with_auth_callback_test.dart b/test_integration/lib/test/rest/rest_publish_with_auth_callback_test.dart index 5ad52f173..3ae80896b 100644 --- a/test_integration/lib/test/rest/rest_publish_with_auth_callback_test.dart +++ b/test_integration/lib/test/rest/rest_publish_with_auth_callback_test.dart @@ -15,15 +15,13 @@ Future> testRestPublishWithAuthCallback({ logLevel: LogLevel.error, authCallback: (params) async { authCallbackInvoked = true; - return TokenRequest.fromMap( - await AppProvisioning().getTokenRequest(), - ); + return TokenRequest.fromMap(await AppProvisioning().getTokenRequest()); }, ), ); await publishMessages(rest.channels.get('test')); return { 'handle': await rest.handle, - 'authCallbackInvoked': authCallbackInvoked + 'authCallbackInvoked': authCallbackInvoked, }; } diff --git a/test_integration/lib/test/rest/rest_request_token_test.dart b/test_integration/lib/test/rest/rest_request_token_test.dart index b6c804efd..deb0592fc 100644 --- a/test_integration/lib/test/rest/rest_request_token_test.dart +++ b/test_integration/lib/test/rest/rest_request_token_test.dart @@ -17,14 +17,15 @@ Future> testRestRequestToken({ logLevel: LogLevel.error, ); - final restForToken = Rest( - options: clientOptionsForToken, - ); + final restForToken = Rest(options: clientOptionsForToken); final token = await restForToken.auth.requestToken(); final clientOptions = ClientOptions( - tokenDetails: token, environment: 'sandbox', logLevel: LogLevel.error); + tokenDetails: token, + environment: 'sandbox', + logLevel: LogLevel.error, + ); final tokenedRest = Rest(options: clientOptions); await publishMessages(tokenedRest.channels.get('test')); diff --git a/test_integration/lib/test/rest/rest_time_test.dart b/test_integration/lib/test/rest/rest_time_test.dart index 4d840dddb..b033fbc02 100644 --- a/test_integration/lib/test/rest/rest_time_test.dart +++ b/test_integration/lib/test/rest/rest_time_test.dart @@ -20,8 +20,5 @@ Future> testRestTime({ final restTime = await rest.time(); - return { - 'handle': await rest.handle, - 'time': restTime.toIso8601String(), - }; + return {'handle': await rest.handle, 'time': restTime.toIso8601String()}; } diff --git a/test_integration/lib/test_dispatcher.dart b/test_integration/lib/test_dispatcher.dart index c7f6f6c0b..a1b9e3bfe 100644 --- a/test_integration/lib/test_dispatcher.dart +++ b/test_integration/lib/test_dispatcher.dart @@ -66,14 +66,18 @@ class _TestDispatcherState extends State { }); final testFunction = widget.testFactory[reporter.testName]!; await testFunction( - reporter: reporter, - payload: reporter.message.payload, - ).then(reporter.reportTestCompletion).catchError( + reporter: reporter, + payload: reporter.message.payload, + ) + .then(reporter.reportTestCompletion) + .catchError( (Object error, StackTrace stack) => reporter.reportTestCompletion({ - TestControlMessage.errorKey: - ErrorHandler.encodeException(error, stack), - }), + TestControlMessage.errorKey: ErrorHandler.encodeException( + error, + stack, + ), + }), ); } } else if (reporter.testName == TestName.getFlutterErrors) { @@ -83,7 +87,7 @@ class _TestDispatcherState extends State { // report error otherwise reporter.reportTestCompletion({ TestControlMessage.errorKey: - 'Test ${reporter.testName} is not implemented' + 'Test ${reporter.testName} is not implemented', }); } setState(() {}); @@ -151,67 +155,65 @@ class _TestDispatcherState extends State { } Widget getTestRow(BuildContext context, String testName) => Row( - children: [ - Expanded( - child: Text( - testName, - style: TextStyle(color: _getColor(testName), fontSize: 16), + children: [ + Expanded( + child: Text( + testName, + style: TextStyle(color: _getColor(testName), fontSize: 16), + ), + ), + _getAction(testName), + _getStatus(testName), + IconButton( + icon: const Icon(Icons.remove_red_eye), + color: Colors.white, + onPressed: () { + showDialog( + context: context, + builder: (context) => AlertDialog( + contentPadding: const EdgeInsets.all(4), + insetPadding: const EdgeInsets.symmetric(vertical: 24), + content: SingleChildScrollView( + child: Text(_testResults[testName] ?? 'No result yet'), + ), ), - ), - _getAction(testName), - _getStatus(testName), - IconButton( - icon: const Icon(Icons.remove_red_eye), - color: Colors.white, - onPressed: () { - showDialog( - context: context, - builder: (context) => AlertDialog( - contentPadding: const EdgeInsets.all(4), - insetPadding: const EdgeInsets.symmetric(vertical: 24), - content: SingleChildScrollView( - child: Text( - _testResults[testName] ?? 'No result yet', - ), - ), - ), - ); - }, - ), - ], - ); + ); + }, + ), + ], + ); @override Widget build(BuildContext context) => MaterialApp( - theme: ThemeData(scaffoldBackgroundColor: Colors.black), - home: Scaffold( - appBar: AppBar( - title: const Text('Test dispatcher'), - ), - body: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Center( - child: Text( - _reporters.isEmpty - ? '-' - : 'running ${_reporters.length}' - ' (${_reporters.keys.toList().toString()}) tests', - style: const TextStyle(color: Colors.white)), + theme: ThemeData(scaffoldBackgroundColor: Colors.black), + home: Scaffold( + appBar: AppBar(title: const Text('Test dispatcher')), + body: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Center( + child: Text( + _reporters.isEmpty + ? '-' + : 'running ${_reporters.length}' + ' (${_reporters.keys.toList().toString()}) tests', + style: const TextStyle(color: Colors.white), ), - Expanded( - child: ListView.builder( - itemCount: _testResults.keys.length, - itemBuilder: (context, idx) { - final testName = _testResults.keys.toList()[idx]; - return ListTile(subtitle: getTestRow(context, testName)); - }, - ), + ), + Expanded( + child: ListView.builder( + itemCount: _testResults.keys.length, + itemBuilder: (context, idx) { + final testName = _testResults.keys.toList()[idx]; + return ListTile(subtitle: getTestRow(context, testName)); + }, ), - ], - ), - )); + ), + ], + ), + ), + ); void renderResponse(TestControlResponseMessage message) { final testName = message.testName; @@ -220,8 +222,8 @@ class _TestDispatcherState extends State { _reporters.remove(testName); _testStatuses[testName] = message.payload.containsKey(TestControlMessage.errorKey) - ? _TestStatus.error - : _TestStatus.success; + ? _TestStatus.error + : _TestStatus.success; }); } } diff --git a/test_integration/lib/utils/data.dart b/test_integration/lib/utils/data.dart index 62b44b6fa..4f2b1fdd5 100644 --- a/test_integration/lib/utils/data.dart +++ b/test_integration/lib/utils/data.dart @@ -7,27 +7,27 @@ final messagesToPublish = [ ['name1', 'Ably'], //message is a string [ 'name2', - [1, 2, 3] + [1, 2, 3], ], //message is a numeric list [ 'name2', - ['hello', 'ably'] + ['hello', 'ably'], ], //message is a string list [ 'name3', { 'hello': 'ably', - 'items': ['1', 2.2, true] - } + 'items': ['1', 2.2, true], + }, ], //message is a map [ 'name3', [ {'hello': 'ably'}, 'ably', - 'realtime' - ] - ] //message is a complex list + 'realtime', + ], + ], //message is a complex list ]; const _chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890'; @@ -35,21 +35,23 @@ Random _rnd = Random(); /// get random alpha numeric string of given length String getRandomString(int length) => String.fromCharCodes( - Iterable.generate( - length, - (_) => _chars.codeUnitAt(_rnd.nextInt(_chars.length)), - ), - ); + Iterable.generate( + length, + (_) => _chars.codeUnitAt(_rnd.nextInt(_chars.length)), + ), +); /// returns subsets of all entries in a list List> getAllSubsets(List l) => l.fold>>( [[]], (subLists, element) => subLists - .map((subList) => [ - subList, - subList + [element] - ]) + .map( + (subList) => [ + subList, + subList + [element], + ], + ) .expand((element) => element) .toList(), ); @@ -58,8 +60,8 @@ const pushPayload = { 'push': { 'notification': { 'title': 'Hello from Ably!', - 'body': 'Test push notification from Ably' + 'body': 'Test push notification from Ably', }, - 'data': {'foo': 'bar'} - } + 'data': {'foo': 'bar'}, + }, }; diff --git a/test_integration/lib/utils/encoders.dart b/test_integration/lib/utils/encoders.dart index 1cd7baddf..78f1ec5fc 100644 --- a/test_integration/lib/utils/encoders.dart +++ b/test_integration/lib/utils/encoders.dart @@ -2,83 +2,78 @@ import 'package:ably_flutter/ably_flutter.dart'; Map? encodeMessageExtras(MessageExtras? extras) => extras == null - ? null - : { - 'extras': extras.map, - 'delta': (extras.delta == null) - ? null - : { - 'from': extras.delta!.from, - 'format': extras.delta!.format, - }, - }; + ? null + : { + 'extras': extras.map, + 'delta': (extras.delta == null) + ? null + : {'from': extras.delta!.from, 'format': extras.delta!.format}, + }; Map encodeMessage(Message message) => { - 'id': message.id, - 'timestamp': message.timestamp?.toIso8601String(), - 'clientId': message.clientId, - 'connectionId': message.connectionId, - 'encoding': message.encoding, - 'data': message.data, - 'name': message.name, - 'extras': encodeMessageExtras(message.extras), - }; + 'id': message.id, + 'timestamp': message.timestamp?.toIso8601String(), + 'clientId': message.clientId, + 'connectionId': message.connectionId, + 'encoding': message.encoding, + 'data': message.data, + 'name': message.name, + 'extras': encodeMessageExtras(message.extras), +}; Map encodePresenceMessage(PresenceMessage message) => { - 'id': message.id, - 'action': enumValueToString(message.action!), - 'clientId': message.clientId, - 'connectionId': message.connectionId, - 'data': message.data, - 'encoding': message.encoding, - 'extras': encodeMessageExtras(message.extras), - 'timestamp': message.timestamp?.toIso8601String(), - }; + 'id': message.id, + 'action': enumValueToString(message.action!), + 'clientId': message.clientId, + 'connectionId': message.connectionId, + 'data': message.data, + 'encoding': message.encoding, + 'extras': encodeMessageExtras(message.extras), + 'timestamp': message.timestamp?.toIso8601String(), +}; String enumValueToString(Object value) => value.toString().substring(value.toString().indexOf('.') + 1); Map encodeChannelEvent(ChannelStateChange e) => { - 'event': enumValueToString(e.event), - 'current': enumValueToString(e.current), - 'previous': enumValueToString(e.previous), - 'reason': e.reason.toString(), - 'resumed': e.resumed, - }; + 'event': enumValueToString(e.event), + 'current': enumValueToString(e.current), + 'previous': enumValueToString(e.previous), + 'reason': e.reason.toString(), + 'resumed': e.resumed, +}; Map encodeConnectionEvent(ConnectionStateChange e) => { - 'event': enumValueToString(e.event), - 'current': enumValueToString(e.current), - 'previous': enumValueToString(e.previous), - 'reason': e.reason.toString(), - 'retryIn': e.retryIn, - }; + 'event': enumValueToString(e.event), + 'current': enumValueToString(e.current), + 'previous': enumValueToString(e.previous), + 'reason': e.reason.toString(), + 'retryIn': e.retryIn, +}; List> encodeList( List items, Map Function(T) typeEncoder, -) => - List.from(items).map>(typeEncoder).toList(); +) => List.from(items).map>(typeEncoder).toList(); Map encodePaginatedResult( PaginatedResult paginatedResult, Map Function(T) typeEncoder, -) => - { - 'items': encodeList(paginatedResult.items, typeEncoder), - 'hasNext': paginatedResult.hasNext(), - 'isLast': paginatedResult.isLast(), - }; +) => { + 'items': encodeList(paginatedResult.items, typeEncoder), + 'hasNext': paginatedResult.hasNext(), + 'isLast': paginatedResult.isLast(), +}; Map encodeAblyException(AblyException exception) => { - 'code': exception.code, - 'message': exception.message, - 'errorInfo': { - 'code': exception.errorInfo?.code, - 'href': exception.errorInfo?.href, - 'message': exception.errorInfo?.message, - 'cause': exception.errorInfo?.cause, - 'statusCode': exception.errorInfo?.statusCode, - 'requestId': exception.errorInfo?.requestId, - } - }; + 'code': exception.code, + 'message': exception.message, + 'errorInfo': { + 'code': exception.errorInfo?.code, + 'href': exception.errorInfo?.href, + 'message': exception.errorInfo?.message, + 'cause': exception.errorInfo?.cause, + 'statusCode': exception.errorInfo?.statusCode, + 'requestId': exception.errorInfo?.requestId, + }, +}; diff --git a/test_integration/lib/utils/realtime.dart b/test_integration/lib/utils/realtime.dart index 5d591c595..b1505714c 100644 --- a/test_integration/lib/utils/realtime.dart +++ b/test_integration/lib/utils/realtime.dart @@ -24,19 +24,20 @@ Future>> getHistory( Future>> getPresenceMembers( RealtimeChannel channel, [ RealtimePresenceParams? params, -]) async => - encodeList( - await channel.presence.get(params), - encodePresenceMessage, - ); +]) async => encodeList( + await channel.presence.get(params), + encodePresenceMessage, +); Future>> getPresenceHistory( RealtimeChannel channel, [ RealtimeHistoryParams? params, ]) async { var results = await channel.presence.history(params); - final messages = - encodeList(results.items, encodePresenceMessage); + final messages = encodeList( + results.items, + encodePresenceMessage, + ); while (results.hasNext()) { results = await results.next(); messages.addAll( diff --git a/test_integration/lib/utils/rest.dart b/test_integration/lib/utils/rest.dart index 0c14335fb..6f5d5b7e6 100644 --- a/test_integration/lib/utils/rest.dart +++ b/test_integration/lib/utils/rest.dart @@ -26,12 +26,15 @@ Future>> getPresenceHistory( RestHistoryParams? params, ]) async { var results = await channel.presence.history(params); - final messages = - encodeList(results.items, encodePresenceMessage); + final messages = encodeList( + results.items, + encodePresenceMessage, + ); while (results.hasNext()) { results = await results.next(); messages.addAll( - encodeList(results.items, encodePresenceMessage)); + encodeList(results.items, encodePresenceMessage), + ); } return messages; } @@ -41,12 +44,15 @@ Future>> getPresenceMembers( RestPresenceParams? params, ]) async { var results = await channel.presence.get(params); - final messages = - encodeList(results.items, encodePresenceMessage); + final messages = encodeList( + results.items, + encodePresenceMessage, + ); while (results.hasNext()) { results = await results.next(); messages.addAll( - encodeList(results.items, encodePresenceMessage)); + encodeList(results.items, encodePresenceMessage), + ); } return messages; } diff --git a/test_integration/pubspec.lock b/test_integration/pubspec.lock index 8f513be99..d21302a5e 100644 --- a/test_integration/pubspec.lock +++ b/test_integration/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7" + sha256: "8d7ff3948166b8ec5da0fbb5962000926b8e02f2ed9b3e51d1738905fbd4c98d" url: "https://pub.dev" source: hosted - version: "67.0.0" + version: "93.0.0" ably_flutter: dependency: "direct main" description: @@ -20,18 +20,18 @@ packages: dependency: transitive description: name: analyzer - sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d" + sha256: de7148ed2fcec579b19f122c1800933dfa028f6d9fd38a152b04b1516cec120b url: "https://pub.dev" source: hosted - version: "6.4.1" + version: "10.0.1" args: dependency: "direct main" description: name: args - sha256: b003c3098049a51720352d219b0bb5f219b60fbfb68e7a4748139a06a5676515 + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.7.0" async: dependency: transitive description: @@ -52,10 +52,10 @@ packages: dependency: transitive description: name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" charcode: dependency: transitive description: @@ -64,6 +64,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" + cli_config: + dependency: transitive + description: + name: cli_config + sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec + url: "https://pub.dev" + source: hosted + version: "0.2.0" clock: dependency: transitive description: @@ -92,10 +100,10 @@ packages: dependency: transitive description: name: coverage - sha256: "8acabb8306b57a409bf4c83522065672ee13179297a6bb0cb9ead73948df7c76" + sha256: "956a3de0725ca232ad353565a8290d3357592bf4250f6f298a185e2d949c5d3d" url: "https://pub.dev" source: hosted - version: "1.7.2" + version: "1.15.1" crypto: dependency: transitive description: @@ -116,10 +124,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.3.3" file: dependency: transitive description: @@ -204,38 +212,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.3" - js: - dependency: transitive - description: - name: js - sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" - url: "https://pub.dev" - source: hosted - version: "0.6.5" leak_tracker: dependency: transitive description: name: leak_tracker - sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.8" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: @@ -256,26 +256,26 @@ packages: dependency: transitive description: name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd" url: "https://pub.dev" source: hosted - version: "0.12.17" + version: "0.12.20" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "0.13.0" meta: dependency: transitive description: name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + sha256: "307249ce4ff29d58a18e97f6345f539382eb9c9c29ecda628900f31de0443dd9" url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.19.0" mime: dependency: transitive description: @@ -445,26 +445,26 @@ packages: dependency: "direct dev" description: name: test - sha256: "301b213cd241ca982e9ba50266bd3f5bd1ea33f1455554c5abb85d1be0e2d87e" + sha256: ca578dc12bb8b2f40b67b7d3bd2fac4f31c01a6ff7130a14e2597b919934507f url: "https://pub.dev" source: hosted - version: "1.25.15" + version: "1.31.1" test_api: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11" url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.12" test_core: dependency: transitive description: name: test_core - sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa" + sha256: d2e98ec12998368dc59ddd47ab709f2cd55acd6b66dc7db764455a44082f4bc5 url: "https://pub.dev" source: hosted - version: "0.6.8" + version: "0.6.18" typed_data: dependency: transitive description: @@ -477,10 +477,10 @@ packages: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: f36f9f3be64c6198714492bb455c11056e33e2f85d9a0b676a48301e44fdcf47 url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.4.2" vm_service: dependency: transitive description: @@ -525,10 +525,10 @@ packages: dependency: transitive description: name: yaml - sha256: "3cee79b1715110341012d27756d9bae38e650588acd38d3f3c610822e1337ace" + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.3" sdks: - dart: ">=3.7.0-0 <4.0.0" - flutter: ">=3.18.0-18.0.pre.54" + dart: ">=3.12.0 <4.0.0" + flutter: ">=3.44.0" diff --git a/test_integration/pubspec.yaml b/test_integration/pubspec.yaml index 5d487661e..ba6cfc7b8 100644 --- a/test_integration/pubspec.yaml +++ b/test_integration/pubspec.yaml @@ -4,7 +4,8 @@ publish_to: "none" version: 1.0.0+1 environment: - sdk: ">=2.14.0 <4.0.0" + sdk: ">=3.12.0 <4.0.0" + flutter: ">=3.44.0" dependencies: flutter: @@ -24,4 +25,10 @@ dev_dependencies: flutter_lints: ^1.0.4 flutter: + # Flutter 3.44 turns Swift Package Manager on by default, and building this + # app would migrate its Xcode project off CocoaPods on the spot. Hold that + # off so the migration can land as its own reviewable commit rather than as + # a side effect of a version bump. + config: + enable-swift-package-manager: false uses-material-design: true diff --git a/test_integration/test_driver/runner.dart b/test_integration/test_driver/runner.dart index 5a113d2bd..050e3ae61 100644 --- a/test_integration/test_driver/runner.dart +++ b/test_integration/test_driver/runner.dart @@ -25,8 +25,9 @@ void main(List args) { return; } - final selectedModules = - _parseModulesStringIntoTestModules(argv['modules'] as List); + final selectedModules = _parseModulesStringIntoTestModules( + argv['modules'] as List, + ); if (selectedModules.isEmpty) { runTests(all: true); @@ -36,7 +37,8 @@ void main(List args) { } Iterable _parseModulesStringIntoTestModules( - List modulesStrings) { + List modulesStrings, +) { final modules = modulesStrings .map((module) => EnumToString.fromString(TestModules.values, module)) .whereType() diff --git a/test_integration/test_driver/test_implementation/basic_platform_tests.dart b/test_integration/test_driver/test_implementation/basic_platform_tests.dart index 3eda6ae9d..51f603a47 100644 --- a/test_integration/test_driver/test_implementation/basic_platform_tests.dart +++ b/test_integration/test_driver/test_implementation/basic_platform_tests.dart @@ -6,7 +6,8 @@ void testPlatformAndAblyVersion(FlutterDriver Function() getDriver) { const message = TestControlMessage(TestName.platformAndAblyVersion); late TestControlResponseMessage response; setUpAll( - () async => response = await requestDataForTest(getDriver(), message)); + () async => response = await requestDataForTest(getDriver(), message), + ); test('platformVersion is a string', () { expect(response.payload['platformVersion'], isA()); @@ -29,7 +30,8 @@ void testDemoDependencies(FlutterDriver Function() getDriver) { const message = TestControlMessage(TestName.appKeyProvisioning); late TestControlResponseMessage response; setUpAll( - () async => response = await requestDataForTest(getDriver(), message)); + () async => response = await requestDataForTest(getDriver(), message), + ); test('appKey is a string', () { expect(response.payload['appKey'], isA()); diff --git a/test_integration/test_driver/test_implementation/crypto_tests.dart b/test_integration/test_driver/test_implementation/crypto_tests.dart index 201c6fd5a..c53282bb4 100644 --- a/test_integration/test_driver/test_implementation/crypto_tests.dart +++ b/test_integration/test_driver/test_implementation/crypto_tests.dart @@ -45,14 +45,18 @@ void testCryptoEnsureSupportedKeyLength(FlutterDriver Function() getDriver) { setUpAll(() async { response = await requestDataForTest(getDriver(), message); - keyWithDefaultLengthException = response - .payload['keyWithDefaultLengthException'] as Map?; - keyWith128BitLengthException = response - .payload['keyWith128BitLengthException'] as Map?; - keyWith256BitLengthException = response - .payload['keyWith256BitLengthException'] as Map?; - keyWith127BitLengthException = response - .payload['keyWith127BitLengthException'] as Map?; + keyWithDefaultLengthException = + response.payload['keyWithDefaultLengthException'] + as Map?; + keyWith128BitLengthException = + response.payload['keyWith128BitLengthException'] + as Map?; + keyWith256BitLengthException = + response.payload['keyWith256BitLengthException'] + as Map?; + keyWith127BitLengthException = + response.payload['keyWith127BitLengthException'] + as Map?; }); group('crypto#ensureSupportedKeyLength', () { @@ -86,8 +90,9 @@ void testCryptoGetDefaultParams(FlutterDriver Function() getDriver) { setUpAll(() async { response = await requestDataForTest(getDriver(), message); - keyWith127BitLengthException = response - .payload['keyWith127BitLengthException'] as Map?; + keyWith127BitLengthException = + response.payload['keyWith127BitLengthException'] + as Map?; didFetchDefaultParams = response.payload['didFetchDefaultParams'] as bool?; }); diff --git a/test_integration/test_driver/test_implementation/helper_tests.dart b/test_integration/test_driver/test_implementation/helper_tests.dart index 287b71770..948639a78 100644 --- a/test_integration/test_driver/test_implementation/helper_tests.dart +++ b/test_integration/test_driver/test_implementation/helper_tests.dart @@ -6,7 +6,8 @@ void testShouldReportUnhandledException(FlutterDriver Function() getDriver) { const message = TestControlMessage(TestName.testHelperUnhandledExceptionTest); late TestControlResponseMessage response; setUpAll( - () async => response = await requestDataForTest(getDriver(), message)); + () async => response = await requestDataForTest(getDriver(), message), + ); test('returns appropriate error message', () { expect(response.payload['error']['exceptionType'], 'String'); diff --git a/test_integration/test_driver/test_implementation/realtime_tests.dart b/test_integration/test_driver/test_implementation/realtime_tests.dart index 1a9646a15..bcd309df3 100644 --- a/test_integration/test_driver/test_implementation/realtime_tests.dart +++ b/test_integration/test_driver/test_implementation/realtime_tests.dart @@ -53,8 +53,9 @@ void testRealtimePublishSpec(FlutterDriver Function() getDriver) { messages = transformListResponse(response.payload['publishedMessages']); messages2 = transformListResponse(response.payload['publishedMessages2']); messages3 = transformListResponse(response.payload['publishedMessages3']); - messagesWithExtras = - transformListResponse(response.payload['publishedExtras']); + messagesWithExtras = transformListResponse( + response.payload['publishedExtras'], + ); exception = response.payload['exception'] as Map?; }); @@ -96,15 +97,13 @@ void testRealtimePublishSpec(FlutterDriver Function() getDriver) { expect(messages[5]['timestamp'] != messages[4]['timestamp'], true); }); - test( - '(RSL1m1) Publishing a Message with no clientId when the clientId' + test('(RSL1m1) Publishing a Message with no clientId when the clientId' ' is set to some value in the client options should result in a message' ' received with the clientId property set to that value', () { expect(messages[0]['clientId'], 'someClientId'); }); - test( - '(RSL1m2) Publishing a Message with a clientId set to the same' + test('(RSL1m2) Publishing a Message with a clientId set to the same' ' value as the clientId in the client options should result in' ' a message received with the clientId property set to that value', () { expect(messages[7]['clientId'], 'someClientId'); @@ -132,13 +131,10 @@ void testRealtimePublishSpec(FlutterDriver Function() getDriver) { () => expect(messages2[0]['clientId'], 'client-id'), ); - test( - 'publishes non-ascii characters', - () { - expect(messages3[0]['name'], 'Ωπ'); - expect(messages3[0]['data'], 'ΨΔ'); - }, - ); + test('publishes non-ascii characters', () { + expect(messages3[0]['name'], 'Ωπ'); + expect(messages3[0]['data'], 'ΨΔ'); + }); }); test('(RSL6a2) publishes message extras', () { @@ -173,21 +169,27 @@ void testRealtimeEncryptedPublishSpec(FlutterDriver Function() getDriver) { setUpAll(() async { response = await requestDataForTest(getDriver(), message); - historyOfEncryptedChannel = - transformListResponse(response.payload['historyOfEncryptedChannel']); - historyOfPlaintextChannel = - transformListResponse(response.payload['historyOfPlaintextChannel']); + historyOfEncryptedChannel = transformListResponse( + response.payload['historyOfEncryptedChannel'], + ); + historyOfPlaintextChannel = transformListResponse( + response.payload['historyOfPlaintextChannel'], + ); historyOfEncryptedPushEnabledChannel = transformListResponse( - response.payload['historyOfEncryptedPushEnabledChannel']); + response.payload['historyOfEncryptedPushEnabledChannel'], + ); historyOfPlaintextPushEnabledChannel = transformListResponse( - response.payload['historyOfPlaintextPushEnabledChannel']); + response.payload['historyOfPlaintextPushEnabledChannel'], + ); }); group('RSL5', () { test('does not encrypt name', () { for (var i = 0; i < historyOfEncryptedPushEnabledChannel.length; i++) { - expect(historyOfEncryptedChannel[i]['name'], - equals(historyOfPlaintextChannel[i]['name'])); + expect( + historyOfEncryptedChannel[i]['name'], + equals(historyOfPlaintextChannel[i]['name']), + ); } }); @@ -205,8 +207,10 @@ void testRealtimeEncryptedPublishSpec(FlutterDriver Function() getDriver) { test('does not encrypt extras', () { for (var i = 0; i < historyOfEncryptedPushEnabledChannel.length; i++) { - expect(historyOfEncryptedPushEnabledChannel[i]['name'], - equals(historyOfPlaintextPushEnabledChannel[i]['name'])); + expect( + historyOfEncryptedPushEnabledChannel[i]['name'], + equals(historyOfPlaintextPushEnabledChannel[i]['name']), + ); } }); }); @@ -246,70 +250,63 @@ void testRealtimeEvents(FlutterDriver Function() getDriver) { group('realtime#channel#connection', () { test('#state', () { expect( - connectionStates, - orderedEquals(const [ - 'initialized', - 'initialized', - 'connected', - 'connected', - 'closed', - ])); + connectionStates, + orderedEquals(const [ + 'initialized', + 'initialized', + 'connected', + 'connected', + 'closed', + ]), + ); }); test( '#on returns a stream which can be subscribed for connectionStateChanges', () { expect( - connectionStateChanges.map((e) => e['event']), - orderedEquals(const [ - 'connecting', - 'connected', - 'closing', - 'closed', - ])); + connectionStateChanges.map((e) => e['event']), + orderedEquals(const ['connecting', 'connected', 'closing', 'closed']), + ); expect( - connectionStateChanges.map((e) => e['previous']), - orderedEquals(const [ - 'initialized', - 'connecting', - 'connected', - 'closing', - ])); + connectionStateChanges.map((e) => e['previous']), + orderedEquals(const [ + 'initialized', + 'connecting', + 'connected', + 'closing', + ]), + ); }, ); - test( - '#on returns a stream which can be subscribed' - ' for connection state changes with filter', - () { - expect(filteredConnectionStateChanges.map((e) => e['event']), const [ - 'connected', - ]); - expect(filteredConnectionStateChanges.map((e) => e['current']), const [ - 'connected', - ]); - expect(filteredConnectionStateChanges.map((e) => e['previous']), const [ - 'connecting', - ]); - }, - ); + test('#on returns a stream which can be subscribed' + ' for connection state changes with filter', () { + expect(filteredConnectionStateChanges.map((e) => e['event']), const [ + 'connected', + ]); + expect(filteredConnectionStateChanges.map((e) => e['current']), const [ + 'connected', + ]); + expect(filteredConnectionStateChanges.map((e) => e['previous']), const [ + 'connecting', + ]); + }); }); group('realtime#channel#chanenls#channel', () { - test( - '#state', - () { - expect( - channelStates, - orderedEquals(const [ - 'initialized', - 'initialized', - 'attached', - 'attached', - 'detached', - 'detached', - ])); - }, - ); + test('#state', () { + expect( + channelStates, + orderedEquals(const [ + 'initialized', + 'initialized', + 'attached', + 'attached', + 'detached', + 'detached', + ]), + ); + }); test( '#on returns a stream which can be subscribed for channel state changes', () { @@ -359,55 +356,54 @@ void testRealtimeEvents(FlutterDriver Function() getDriver) { ]; } - expect(channelStateChanges.map((e) => e['event']), - orderedEquals(_stateChangeEvents)); + expect( + channelStateChanges.map((e) => e['event']), + orderedEquals(_stateChangeEvents), + ); - expect(channelStateChanges.map((e) => e['current']), - orderedEquals(_stateChangeCurrent)); + expect( + channelStateChanges.map((e) => e['current']), + orderedEquals(_stateChangeCurrent), + ); - expect(channelStateChanges.map((e) => e['previous']), - orderedEquals(_stateChangePrevious)); + expect( + channelStateChanges.map((e) => e['previous']), + orderedEquals(_stateChangePrevious), + ); }, ); - test( - '#on returns a stream which can be subscribed' - ' for channel state changes with filter', - () { - List _stateChangeCurrent; - List _stateChangePrevious; - List _stateChangeEvents; - if (channelStateChanges.length == 4) { - // iOS - _stateChangeCurrent = const [ - 'attaching', - ]; - _stateChangePrevious = const [ - 'initialized', - ]; - } else { - // Android - _stateChangeCurrent = const [ - 'attaching', - 'attaching', - ]; - _stateChangePrevious = const [ - 'initialized', - 'attaching', - ]; - } - _stateChangeEvents = _stateChangeCurrent; - // filteredChannelStateChanges - expect(filteredChannelStateChanges.map((e) => e['event']), - orderedEquals(_stateChangeEvents)); + test('#on returns a stream which can be subscribed' + ' for channel state changes with filter', () { + List _stateChangeCurrent; + List _stateChangePrevious; + List _stateChangeEvents; + if (channelStateChanges.length == 4) { + // iOS + _stateChangeCurrent = const ['attaching']; + _stateChangePrevious = const ['initialized']; + } else { + // Android + _stateChangeCurrent = const ['attaching', 'attaching']; + _stateChangePrevious = const ['initialized', 'attaching']; + } + _stateChangeEvents = _stateChangeCurrent; + // filteredChannelStateChanges + expect( + filteredChannelStateChanges.map((e) => e['event']), + orderedEquals(_stateChangeEvents), + ); - expect(filteredChannelStateChanges.map((e) => e['current']), - orderedEquals(_stateChangeCurrent)); + expect( + filteredChannelStateChanges.map((e) => e['current']), + orderedEquals(_stateChangeCurrent), + ); - expect(filteredChannelStateChanges.map((e) => e['previous']), - orderedEquals(_stateChangePrevious)); - }, - ); + expect( + filteredChannelStateChanges.map((e) => e['previous']), + orderedEquals(_stateChangePrevious), + ); + }); }); } @@ -422,55 +418,47 @@ void testRealtimeSubscribe(FlutterDriver Function() getDriver) { setUpAll(() async { response = await requestDataForTest(getDriver(), message); all = transformListResponse(response.payload['all']); - filteredWithName = - transformListResponse(response.payload['filteredWithName']); + filteredWithName = transformListResponse( + response.payload['filteredWithName'], + ); filteredWithNames = transformListResponse( response.payload['filteredWithNames'], ); extrasMessages = transformListResponse(response.payload['extrasMessages']); }); - test( - 'realtime#channels#channel#subscribe should subscribe to' - ' all message on channel', - () { - testAllPublishedMessages(all); - }, - ); + test('realtime#channels#channel#subscribe should subscribe to' + ' all message on channel', () { + testAllPublishedMessages(all); + }); - test( - 'realtime#channels#channel#subscribe(name: string)' - ' should subscribe to messages with specified name', - () { - expect(filteredWithName.length, equals(2)); + test('realtime#channels#channel#subscribe(name: string)' + ' should subscribe to messages with specified name', () { + expect(filteredWithName.length, equals(2)); - expect(filteredWithName[0]['name'], 'name1'); - expect(filteredWithName[0]['data'], isNull); + expect(filteredWithName[0]['name'], 'name1'); + expect(filteredWithName[0]['data'], isNull); - expect(filteredWithName[1]['name'], 'name1'); - expect(filteredWithName[1]['data'], equals('Ably')); - }, - ); + expect(filteredWithName[1]['name'], 'name1'); + expect(filteredWithName[1]['data'], equals('Ably')); + }); - test( - 'realtime#channels#channel#subscribe(names: List)' - ' should subscribe to messages with specified names', - () { - expect(filteredWithNames.length, equals(4)); + test('realtime#channels#channel#subscribe(names: List)' + ' should subscribe to messages with specified names', () { + expect(filteredWithNames.length, equals(4)); - expect(filteredWithNames[0]['name'], 'name1'); - expect(filteredWithNames[0]['data'], isNull); + expect(filteredWithNames[0]['name'], 'name1'); + expect(filteredWithNames[0]['data'], isNull); - expect(filteredWithNames[1]['name'], 'name1'); - expect(filteredWithNames[1]['data'], equals('Ably')); + expect(filteredWithNames[1]['name'], 'name1'); + expect(filteredWithNames[1]['data'], equals('Ably')); - expect(filteredWithNames[2]['name'], 'name2'); - expect(filteredWithNames[2]['data'], equals([1, 2, 3])); + expect(filteredWithNames[2]['name'], 'name2'); + expect(filteredWithNames[2]['data'], equals([1, 2, 3])); - expect(filteredWithNames[3]['name'], 'name2'); - expect(filteredWithNames[3]['data'], equals(['hello', 'ably'])); - }, - ); + expect(filteredWithNames[3]['name'], 'name2'); + expect(filteredWithNames[3]['data'], equals(['hello', 'ably'])); + }); test('retrieves extras posted in message', () { expect(extrasMessages[0]['name'], 'name'); @@ -499,10 +487,12 @@ void testRealtimeHistory(FlutterDriver Function() getDriver) { historyDefault = transformListResponse(response.payload['historyDefault']); historyLimit4 = transformListResponse(response.payload['historyLimit4']); historyLimit2 = transformListResponse(response.payload['historyLimit2']); - historyForwardLimit4 = - transformListResponse(response.payload['historyForwardLimit4']); - historyWithStart = - transformListResponse(response.payload['historyWithStart']); + historyForwardLimit4 = transformListResponse( + response.payload['historyForwardLimit4'], + ); + historyWithStart = transformListResponse( + response.payload['historyWithStart'], + ); historyWithStartAndEnd = transformListResponse( response.payload['historyWithStartAndEnd'], ); @@ -531,11 +521,13 @@ void testRealtimeHistory(FlutterDriver Function() getDriver) { testAllPublishedMessages(historyLimit4.reversed.toList()); testAllPublishedMessages(historyLimit2.reversed.toList()); }); - test('queries entries in reverse order with direction set to "forward"', - () { - expect(historyForwardLimit4.length, equals(8)); - testAllPublishedMessages(historyForwardLimit4); - }); + test( + 'queries entries in reverse order with direction set to "forward"', + () { + expect(historyForwardLimit4.length, equals(8)); + testAllPublishedMessages(historyForwardLimit4); + }, + ); test('returns entries created after specified time', () { expect(historyWithStart.length, equals(2)); expect(historyWithStart[0]['name'], equals('history')); @@ -555,7 +547,8 @@ void testRealtimeHistoryWithAuthCallback(FlutterDriver Function() getDriver) { const message = TestControlMessage(TestName.realtimeHistoryWithAuthCallback); late TestControlResponseMessage response; setUpAll( - () async => response = await requestDataForTest(getDriver(), message)); + () async => response = await requestDataForTest(getDriver(), message), + ); test('auth callback is invoked', () { expect(response.payload['authCallbackInvoked'], isTrue); @@ -592,10 +585,12 @@ void testRealtimePresenceGet(FlutterDriver Function() getDriver) { response = await requestDataForTest(getDriver(), message); membersInitial = transformListResponse(response.payload['membersInitial']); membersDefault = transformListResponse(response.payload['membersDefault']); - membersClientId = - transformListResponse(response.payload['membersClientId']); - membersConnectionId = - transformListResponse(response.payload['membersConnectionId']); + membersClientId = transformListResponse( + response.payload['membersClientId'], + ); + membersConnectionId = transformListResponse( + response.payload['membersConnectionId'], + ); }); group('realtime#channels#channel#presence#get', () { @@ -639,8 +634,9 @@ void testRealtimePresenceHistory(FlutterDriver Function() getDriver) { historyDefault = transformListResponse(response.payload['historyDefault']); historyLimit4 = transformListResponse(response.payload['historyLimit4']); historyLimit2 = transformListResponse(response.payload['historyLimit2']); - historyForwards = - transformListResponse(response.payload['historyForwards']); + historyForwards = transformListResponse( + response.payload['historyForwards'], + ); historyWithStart = transformListResponse( response.payload['historyWithStart'], ).reversed.toList(); @@ -663,13 +659,10 @@ void testRealtimePresenceHistory(FlutterDriver Function() getDriver) { testAllPresenceMessagesHistory(historyLimit4.reversed.toList()); testAllPresenceMessagesHistory(historyLimit2.reversed.toList()); }); - test( - 'queries entries in reverse order with direction set to "forward"', - () { - expect(historyForwards.length, equals(8)); - testAllPresenceMessagesHistory(historyForwards.toList()); - }, - ); + test('queries entries in reverse order with direction set to "forward"', () { + expect(historyForwards.length, equals(8)); + testAllPresenceMessagesHistory(historyForwards.toList()); + }); test('returns entries created after specified time', () { expect(historyWithStart.length, equals(2)); expect(historyWithStart[0]['clientId'], equals('someClientId')); @@ -693,8 +686,9 @@ void testRealtimeEnterUpdateLeave(FlutterDriver Function() getDriver) { setUpAll(() async { response = await requestDataForTest(getDriver(), message); - clientIDClashMatrix = - transformListResponse(response.payload['clientIDClashMatrix']); + clientIDClashMatrix = transformListResponse( + response.payload['clientIDClashMatrix'], + ); actionMatrix = transformListResponse(response.payload['actionMatrix']); }); @@ -739,8 +733,7 @@ void testRealtimeEnterUpdateLeave(FlutterDriver Function() getDriver) { ); } - test( - 'clientID should be same in both realtime ClientOptions as well as' + test('clientID should be same in both realtime ClientOptions as well as' ' the one passed to presence enter/update/leave APIs.' ' If unequal, throw error.', () { for (final clashEntry in clientIDClashMatrix) { @@ -758,20 +751,10 @@ void testRealtimeEnterUpdateLeave(FlutterDriver Function() getDriver) { ); } else if (presenceClientID == null) { // only realtimeClientID is present - testMatrixEntry( - clashEntry, - enter: true, - update: true, - leave: true, - ); + testMatrixEntry(clashEntry, enter: true, update: true, leave: true); } else { // both clientIDs are present and are unequal - testMatrixEntry( - clashEntry, - enter: true, - update: true, - leave: true, - ); + testMatrixEntry(clashEntry, enter: true, update: true, leave: true); } } else { if (presenceClientID == null) { @@ -820,10 +803,12 @@ void testRealtimePresenceSubscription(FlutterDriver Function() getDriver) { response = await requestDataForTest(getDriver(), message); allMessages = transformListResponse(response.payload['allMessages']); enterMessages = transformListResponse(response.payload['enterMessages']); - enterUpdateMessages = - transformListResponse(response.payload['enterUpdateMessages']); - partialMessages = - transformListResponse(response.payload['partialMessages']); + enterUpdateMessages = transformListResponse( + response.payload['enterUpdateMessages'], + ); + partialMessages = transformListResponse( + response.payload['partialMessages'], + ); }); void _test(List> messages) { @@ -838,31 +823,43 @@ void testRealtimePresenceSubscription(FlutterDriver Function() getDriver) { } } - test('listens to messages', () { - expect(allMessages.length, equals(8)); - _test(allMessages); - }, - skip: - 'One message in allMessages gets `present` action, but should have been `enter`. See https://github.com/ably/ably-flutter/issues/150'); - - test('filters messages with single action', () { - expect(enterMessages.length, equals(1)); - _test(enterMessages); - }, - skip: - 'expected 1 but got 0. See https://github.com/ably/ably-flutter/issues/150'); - - test('filters messages with multiple actions', () { - expect(enterUpdateMessages.length, equals(7)); - _test(enterUpdateMessages); - }, - skip: - 'Got a length of 6 but expected 7. See https://github.com/ably/ably-flutter/issues/150'); - - test('listens to messages only until subscription is active', () { - expect(partialMessages.length, equals(7)); - expect(partialMessages, equals(enterUpdateMessages)); - }, - skip: - 'Expected a set of messages, but got the same set but with 1 unexpected extra message at the start, with `present` action. See https://github.com/ably/ably-flutter/issues/150'); + test( + 'listens to messages', + () { + expect(allMessages.length, equals(8)); + _test(allMessages); + }, + skip: + 'One message in allMessages gets `present` action, but should have been `enter`. See https://github.com/ably/ably-flutter/issues/150', + ); + + test( + 'filters messages with single action', + () { + expect(enterMessages.length, equals(1)); + _test(enterMessages); + }, + skip: + 'expected 1 but got 0. See https://github.com/ably/ably-flutter/issues/150', + ); + + test( + 'filters messages with multiple actions', + () { + expect(enterUpdateMessages.length, equals(7)); + _test(enterUpdateMessages); + }, + skip: + 'Got a length of 6 but expected 7. See https://github.com/ably/ably-flutter/issues/150', + ); + + test( + 'listens to messages only until subscription is active', + () { + expect(partialMessages.length, equals(7)); + expect(partialMessages, equals(enterUpdateMessages)); + }, + skip: + 'Expected a set of messages, but got the same set but with 1 unexpected extra message at the start, with `present` action. See https://github.com/ably/ably-flutter/issues/150', + ); } diff --git a/test_integration/test_driver/test_implementation/rest_tests.dart b/test_integration/test_driver/test_implementation/rest_tests.dart index 0e740c30e..c92cc1190 100644 --- a/test_integration/test_driver/test_implementation/rest_tests.dart +++ b/test_integration/test_driver/test_implementation/rest_tests.dart @@ -10,7 +10,8 @@ void testRestPublish(FlutterDriver Function() getDriver) { const message = TestControlMessage(TestName.restPublish); late TestControlResponseMessage response; setUpAll( - () async => response = await requestDataForTest(getDriver(), message)); + () async => response = await requestDataForTest(getDriver(), message), + ); test('rest instance has a valid handle on publish', () { expect(response.payload['handle'], isA()); @@ -22,10 +23,10 @@ void testRestRequestTokenPublish(FlutterDriver Function() getDriver) { const message = TestControlMessage(TestName.restRequestToken); late TestControlResponseMessage response; setUpAll( - () async => response = await requestDataForTest(getDriver(), message)); + () async => response = await requestDataForTest(getDriver(), message), + ); - test( - 'rest instance with token has a valid handle and successfully' + test('rest instance with token has a valid handle and successfully' ' publishes messages', () { expect(response.payload['handle'], isA()); expect(response.payload['handle'], greaterThan(0)); @@ -36,10 +37,10 @@ void testRestCreateTokenRequestPublish(FlutterDriver Function() getDriver) { const message = TestControlMessage(TestName.restCreateTokenRequest); late TestControlResponseMessage response; setUpAll( - () async => response = await requestDataForTest(getDriver(), message)); + () async => response = await requestDataForTest(getDriver(), message), + ); - test( - 'rest instance with token has a valid handle and successfully ' + test('rest instance with token has a valid handle and successfully ' 'publishes messages', () { expect(response.payload['handle'], isA()); expect(response.payload['log'], greaterThan(0)); @@ -50,7 +51,8 @@ void testRestEncryptedPublish(FlutterDriver Function() getDriver) { const message = TestControlMessage(TestName.restEncryptedPublish); late TestControlResponseMessage response; setUpAll( - () async => response = await requestDataForTest(getDriver(), message)); + () async => response = await requestDataForTest(getDriver(), message), + ); test('rest instance has a valid handle on encrypted publish', () { expect(response.payload['handle'], isA()); @@ -75,8 +77,9 @@ void testRestPublishSpec(FlutterDriver Function() getDriver) { messages = transformListResponse(response.payload['publishedMessages']); messages2 = transformListResponse(response.payload['publishedMessages2']); messages3 = transformListResponse(response.payload['publishedMessages3']); - messagesWithExtras = - transformListResponse(response.payload['publishedExtras']); + messagesWithExtras = transformListResponse( + response.payload['publishedExtras'], + ); exception = response.payload['exception'] as Map?; exception2 = response.payload['exception2'] as Map?; exception3 = response.payload['exception3'] as Map?; @@ -115,16 +118,17 @@ void testRestPublishSpec(FlutterDriver Function() getDriver) { }); test( - '(RSL1m1) Publishing a Message with no clientId when the clientId' - ' is set to some value in the client options should result in a message' - ' received with the clientId property set to that value', () { - expect(messages[0]['clientId'], 'someClientId'); - }, - skip: - 'Failing on Android, the clientId is null`. See https://github.com/ably/ably-flutter/issues/150'); + '(RSL1m1) Publishing a Message with no clientId when the clientId' + ' is set to some value in the client options should result in a message' + ' received with the clientId property set to that value', + () { + expect(messages[0]['clientId'], 'someClientId'); + }, + skip: + 'Failing on Android, the clientId is null`. See https://github.com/ably/ably-flutter/issues/150', + ); - test( - '(RSL1m2) Publishing a Message with a clientId set to the same' + test('(RSL1m2) Publishing a Message with a clientId set to the same' ' value as the clientId in the client options should result in' ' a message received with the clientId property set to that value', () { expect(messages[7]['clientId'], 'someClientId'); @@ -165,26 +169,20 @@ void testRestPublishSpec(FlutterDriver Function() getDriver) { () => expect(messages2[0]['clientId'], 'client-id'), ); - test( - '(RSL1i) If the total size of the message or (if publishing an array)' - ' messages, calculated per TO3l8, exceeds the maxMessageSize, then the' - ' client library should reject the publish and indicate an error' - ' with code 40009', - () { - // allows publishing messages length <= max allowed limit - expect(exception2 == null, true); - // errors out publishing messages length > max allowed limit - expect(exception3 == null, false); - }, - ); + test('(RSL1i) If the total size of the message or (if publishing an array)' + ' messages, calculated per TO3l8, exceeds the maxMessageSize, then the' + ' client library should reject the publish and indicate an error' + ' with code 40009', () { + // allows publishing messages length <= max allowed limit + expect(exception2 == null, true); + // errors out publishing messages length > max allowed limit + expect(exception3 == null, false); + }); - test( - 'publishes non-ascii characters', - () { - expect(messages3[0]['name'], 'Ωπ'); - expect(messages3[0]['data'], 'ΨΔ'); - }, - ); + test('publishes non-ascii characters', () { + expect(messages3[0]['name'], 'Ωπ'); + expect(messages3[0]['data'], 'ΨΔ'); + }); }); test('RSL6a2 publishes message extras', () { @@ -206,21 +204,27 @@ void testRestEncryptedPublishSpec(FlutterDriver Function() getDriver) { setUpAll(() async { response = await requestDataForTest(getDriver(), message); - historyOfEncryptedChannel = - transformListResponse(response.payload['historyOfEncryptedChannel']); - historyOfPlaintextChannel = - transformListResponse(response.payload['historyOfPlaintextChannel']); + historyOfEncryptedChannel = transformListResponse( + response.payload['historyOfEncryptedChannel'], + ); + historyOfPlaintextChannel = transformListResponse( + response.payload['historyOfPlaintextChannel'], + ); historyOfEncryptedPushEnabledChannel = transformListResponse( - response.payload['historyOfEncryptedPushEnabledChannel']); + response.payload['historyOfEncryptedPushEnabledChannel'], + ); historyOfPlaintextPushEnabledChannel = transformListResponse( - response.payload['historyOfPlaintextPushEnabledChannel']); + response.payload['historyOfPlaintextPushEnabledChannel'], + ); }); group('RSL5', () { test('does not encrypt name', () { for (var i = 0; i < historyOfEncryptedPushEnabledChannel.length; i++) { - expect(historyOfEncryptedChannel[i]['name'], - equals(historyOfPlaintextChannel[i]['name'])); + expect( + historyOfEncryptedChannel[i]['name'], + equals(historyOfPlaintextChannel[i]['name']), + ); } }); @@ -238,8 +242,10 @@ void testRestEncryptedPublishSpec(FlutterDriver Function() getDriver) { test('does not encrypt extras', () { for (var i = 0; i < historyOfEncryptedPushEnabledChannel.length; i++) { - expect(historyOfEncryptedPushEnabledChannel[i]['name'], - equals(historyOfPlaintextPushEnabledChannel[i]['name'])); + expect( + historyOfEncryptedPushEnabledChannel[i]['name'], + equals(historyOfPlaintextPushEnabledChannel[i]['name']), + ); } }); }); @@ -249,7 +255,8 @@ void testRestPublishWithAuthCallback(FlutterDriver Function() getDriver) { const message = TestControlMessage(TestName.restPublishWithAuthCallback); late TestControlResponseMessage response; setUpAll( - () async => response = await requestDataForTest(getDriver(), message)); + () async => response = await requestDataForTest(getDriver(), message), + ); test('auth callback is invoked', () { expect(response.payload['authCallbackInvoked'], isTrue); @@ -275,10 +282,12 @@ void testRestHistory(FlutterDriver Function() getDriver) { historyDefault = transformListResponse(response.payload['historyDefault']); historyLimit4 = transformListResponse(response.payload['historyLimit4']); historyLimit2 = transformListResponse(response.payload['historyLimit2']); - historyForwardLimit4 = - transformListResponse(response.payload['historyForwardLimit4']); - historyWithStart = - transformListResponse(response.payload['historyWithStart']); + historyForwardLimit4 = transformListResponse( + response.payload['historyForwardLimit4'], + ); + historyWithStart = transformListResponse( + response.payload['historyWithStart'], + ); historyWithStartAndEnd = transformListResponse( response.payload['historyWithStartAndEnd'], ); @@ -307,11 +316,13 @@ void testRestHistory(FlutterDriver Function() getDriver) { testAllPublishedMessages(historyLimit4.reversed.toList()); testAllPublishedMessages(historyLimit2.reversed.toList()); }); - test('queries entries in reverse order with direction set to "forward"', - () { - expect(historyForwardLimit4.length, equals(8)); - testAllPublishedMessages(historyForwardLimit4); - }); + test( + 'queries entries in reverse order with direction set to "forward"', + () { + expect(historyForwardLimit4.length, equals(8)); + testAllPublishedMessages(historyForwardLimit4); + }, + ); test('returns entries created after specified time', () { expect(historyWithStart.length, equals(2)); expect(historyWithStart[0]['name'], equals('history')); @@ -331,7 +342,8 @@ void testRestHistoryWithAuthCallback(FlutterDriver Function() getDriver) { const message = TestControlMessage(TestName.restHistoryWithAuthCallback); late TestControlResponseMessage response; setUpAll( - () async => response = await requestDataForTest(getDriver(), message)); + () async => response = await requestDataForTest(getDriver(), message), + ); test('auth callback is invoked', () { expect(response.payload['authCallbackInvoked'], isTrue); @@ -372,10 +384,12 @@ void testRestPresenceGet(FlutterDriver Function() getDriver) { membersDefault = transformListResponse(response.payload['membersDefault']); membersLimit4 = transformListResponse(response.payload['membersLimit4']); membersLimit2 = transformListResponse(response.payload['membersLimit2']); - membersClientId = - transformListResponse(response.payload['membersClientId']); - membersConnectionId = - transformListResponse(response.payload['membersConnectionId']); + membersClientId = transformListResponse( + response.payload['membersClientId'], + ); + membersConnectionId = transformListResponse( + response.payload['membersConnectionId'], + ); }); group('rest#channels#channel#presence#get', () { @@ -426,8 +440,9 @@ void testRestPresenceHistory(FlutterDriver Function() getDriver) { historyDefault = transformListResponse(response.payload['historyDefault']); historyLimit4 = transformListResponse(response.payload['historyLimit4']); historyLimit2 = transformListResponse(response.payload['historyLimit2']); - historyForwards = - transformListResponse(response.payload['historyForwards']); + historyForwards = transformListResponse( + response.payload['historyForwards'], + ); historyWithStart = transformListResponse( response.payload['historyWithStart'], ).reversed.toList(); diff --git a/test_integration/test_driver/test_implementation/utils.dart b/test_integration/test_driver/test_implementation/utils.dart index 26297d222..ed0ee7d8e 100644 --- a/test_integration/test_driver/test_implementation/utils.dart +++ b/test_integration/test_driver/test_implementation/utils.dart @@ -23,24 +23,20 @@ void checkMessageData(int index, Object? data) { case 6: expect( data, - equals( - { - 'hello': 'ably', - 'items': ['1', 2.2, true] - }, - ), + equals({ + 'hello': 'ably', + 'items': ['1', 2.2, true], + }), ); break; case 7: expect( data, - equals( - [ - {'hello': 'ably'}, - 'ably', - 'realtime' - ], - ), + equals([ + {'hello': 'ably'}, + 'ably', + 'realtime', + ]), ); } } @@ -113,6 +109,6 @@ void checkMessageExtras(Map messageExtras) { } List> transformListResponse(dynamic items) => - List.from(items as List) - .map((t) => t as Map) - .toList(); + List.from( + items as List, + ).map((t) => t as Map).toList(); diff --git a/test_integration/test_driver/tests_abstract.dart b/test_integration/test_driver/tests_abstract.dart index e93ceb773..64417bb4c 100644 --- a/test_integration/test_driver/tests_abstract.dart +++ b/test_integration/test_driver/tests_abstract.dart @@ -5,14 +5,8 @@ import 'package:test/test.dart'; import 'tests_config.dart'; -void runTests({ - bool all = false, - Iterable? testModules, -}) { - final tests = getTestsFor( - all: all, - testModules: testModules, - ); +void runTests({bool all = false, Iterable? testModules}) { + final tests = getTestsFor(all: all, testModules: testModules); late FlutterDriver driver; @@ -32,10 +26,7 @@ void runTests({ for (final testModule in tests.keys) { final testModuleName = EnumToString.convertToString(testModule); - tests[testModule]!.forEach(( - testGroupName, - testFunction, - ) { + tests[testModule]!.forEach((testGroupName, testFunction) { group( 'Module: $testModuleName. Group: $testGroupName. Test: ', () => testFunction(getDriver), diff --git a/test_integration/test_driver/tests_config.dart b/test_integration/test_driver/tests_config.dart index ecf9a293a..ce62f9c82 100644 --- a/test_integration/test_driver/tests_config.dart +++ b/test_integration/test_driver/tests_config.dart @@ -9,56 +9,57 @@ enum TestModules { basicTests, helperTests, rest, realtime, crypto } final _tests = >{ - TestModules.basicTests: { - 'should return Platform and Ably version': testPlatformAndAblyVersion, - 'should provision AppKey': testDemoDependencies, - }, - TestModules.helperTests: { - 'should report unhandled exception': testShouldReportUnhandledException, - }, - TestModules.rest: { - 'should publish': testRestPublish, - 'should publish with tokenRequest': testRestRequestTokenPublish, - 'should publish encrypted': testRestEncryptedPublish, - 'should retrieve history': testRestHistory, - 'should retrieve history with auth callback': - testRestHistoryWithAuthCallback, - 'should retrieve time': testRestTime, - 'conforms to publish spec': testRestPublishSpec, - 'conforms to publish spec when encrypted': testRestEncryptedPublishSpec, - 'should publish with AuthCallback': testRestPublishWithAuthCallback, - 'should get Presence Members': testRestPresenceGet, - 'should get Presence History': testRestPresenceHistory, - 'conforms to capabilitySpec': testCapabilityMatrix, - }, - TestModules.realtime: { - 'should publish': testRealtimePublish, - 'should publish encrypted': testRealtimeEncryptedPublish, - 'conforms to publish spec': testRealtimePublishSpec, - 'conforms to publish spec when encrypted': testRealtimeEncryptedPublishSpec, - 'should subscribe to connection and channel': testRealtimeEvents, - 'should subscribe to messages': testRealtimeSubscribe, - 'should retrieve history': testRealtimeHistory, - 'should retrieve history with auth callback': - testRealtimeHistoryWithAuthCallback, - 'should retrieve time': testRealtimeTime, - 'realtime#channels#channel#presence#get': testRealtimePresenceGet, - 'realtime#channels#channel#presence#history': testRealtimePresenceHistory, - 'should enter, update and leave Presence': testRealtimeEnterUpdateLeave, - 'should subscribe to channel presence': testRealtimePresenceSubscription, - }, - TestModules.crypto: { - 'should generate random crypto key': testCryptoGenerateRandomKey, - 'should validate supported key lengths': testCryptoEnsureSupportedKeyLength, - 'should get default params': testCryptoGetDefaultParams, - } -}; + TestModules.basicTests: { + 'should return Platform and Ably version': testPlatformAndAblyVersion, + 'should provision AppKey': testDemoDependencies, + }, + TestModules.helperTests: { + 'should report unhandled exception': testShouldReportUnhandledException, + }, + TestModules.rest: { + 'should publish': testRestPublish, + 'should publish with tokenRequest': testRestRequestTokenPublish, + 'should publish encrypted': testRestEncryptedPublish, + 'should retrieve history': testRestHistory, + 'should retrieve history with auth callback': + testRestHistoryWithAuthCallback, + 'should retrieve time': testRestTime, + 'conforms to publish spec': testRestPublishSpec, + 'conforms to publish spec when encrypted': testRestEncryptedPublishSpec, + 'should publish with AuthCallback': testRestPublishWithAuthCallback, + 'should get Presence Members': testRestPresenceGet, + 'should get Presence History': testRestPresenceHistory, + 'conforms to capabilitySpec': testCapabilityMatrix, + }, + TestModules.realtime: { + 'should publish': testRealtimePublish, + 'should publish encrypted': testRealtimeEncryptedPublish, + 'conforms to publish spec': testRealtimePublishSpec, + 'conforms to publish spec when encrypted': + testRealtimeEncryptedPublishSpec, + 'should subscribe to connection and channel': testRealtimeEvents, + 'should subscribe to messages': testRealtimeSubscribe, + 'should retrieve history': testRealtimeHistory, + 'should retrieve history with auth callback': + testRealtimeHistoryWithAuthCallback, + 'should retrieve time': testRealtimeTime, + 'realtime#channels#channel#presence#get': testRealtimePresenceGet, + 'realtime#channels#channel#presence#history': + testRealtimePresenceHistory, + 'should enter, update and leave Presence': testRealtimeEnterUpdateLeave, + 'should subscribe to channel presence': + testRealtimePresenceSubscription, + }, + TestModules.crypto: { + 'should generate random crypto key': testCryptoGenerateRandomKey, + 'should validate supported key lengths': + testCryptoEnsureSupportedKeyLength, + 'should get default params': testCryptoGetDefaultParams, + }, + }; Map> - getTestsFor({ - bool all = false, - Iterable? testModules, -}) { +getTestsFor({bool all = false, Iterable? testModules}) { assert(testModules != null || all != false); late Iterable _testModules; if (all) {