CI tweaks and incremented build number
Added the XCBeautify pod (so the CI doesn't need to separately install something) Updated the CI build script to use XCBeautify Fixed some broken unit tests
This commit is contained in:
parent
970efbc3be
commit
c86cc0ed9c
|
@ -71,13 +71,7 @@ local update_cocoapods_cache = {
|
|||
name: 'Run Unit Tests',
|
||||
commands: [
|
||||
'mkdir build',
|
||||
|||
|
||||
if command -v xcpretty >/dev/null 2>&1; then
|
||||
xcodebuild test -workspace Session.xcworkspace -scheme Session -destination "platform=iOS Simulator,name=iPhone 14 Pro" | xcpretty
|
||||
else
|
||||
xcodebuild test -workspace Session.xcworkspace -scheme Session -destination "platform=iOS Simulator,name=iPhone 14 Pro"
|
||||
fi
|
||||
|||
|
||||
'NSUnbufferedIO=YES set -o pipefail && xcodebuild test -workspace Session.xcworkspace -scheme Session -destination "platform=iOS Simulator,name=iPhone 14 Pro" -maximum-test-execution-time-allowance 2 -collect-test-diagnostics never 2>&1 | ./Pods/xcbeautify/xcbeautify'
|
||||
],
|
||||
},
|
||||
update_cocoapods_cache
|
||||
|
@ -97,13 +91,7 @@ local update_cocoapods_cache = {
|
|||
name: 'Build',
|
||||
commands: [
|
||||
'mkdir build',
|
||||
|||
|
||||
if command -v xcpretty >/dev/null 2>&1; then
|
||||
xcodebuild archive -workspace Session.xcworkspace -scheme Session -configuration 'App Store Release' -sdk iphonesimulator -archivePath ./build/Session_sim.xcarchive -destination "generic/platform=iOS Simulator" | xcpretty
|
||||
else
|
||||
xcodebuild archive -workspace Session.xcworkspace -scheme Session -configuration 'App Store Release' -sdk iphonesimulator -archivePath ./build/Session_sim.xcarchive -destination "generic/platform=iOS Simulator"
|
||||
fi
|
||||
|||
|
||||
'xcodebuild archive -workspace Session.xcworkspace -scheme Session -configuration 'App Store Release' -sdk iphonesimulator -archivePath ./build/Session_sim.xcarchive -destination "generic/platform=iOS Simulator" | ./Pods/xcbeautify/xcbeautify'
|
||||
],
|
||||
},
|
||||
update_cocoapods_cache,
|
||||
|
@ -129,13 +117,7 @@ local update_cocoapods_cache = {
|
|||
name: 'Build',
|
||||
commands: [
|
||||
'mkdir build',
|
||||
|||
|
||||
if command -v xcpretty >/dev/null 2>&1; then
|
||||
xcodebuild archive -workspace Session.xcworkspace -scheme Session -configuration 'App Store Release' -sdk iphoneos -archivePath ./build/Session.xcarchive -destination "generic/platform=iOS" -allowProvisioningUpdates | xcpretty
|
||||
else
|
||||
xcodebuild archive -workspace Session.xcworkspace -scheme Session -configuration 'App Store Release' -sdk iphoneos -archivePath ./build/Session.xcarchive -destination "generic/platform=iOS" -allowProvisioningUpdates
|
||||
fi
|
||||
|||
|
||||
'xcodebuild archive -workspace Session.xcworkspace -scheme Session -configuration 'App Store Release' -sdk iphoneos -archivePath ./build/Session.xcarchive -destination "generic/platform=iOS" -allowProvisioningUpdates | ./Pods/xcbeautify/xcbeautify'
|
||||
],
|
||||
},
|
||||
update_cocoapods_cache,
|
||||
|
|
3
Podfile
3
Podfile
|
@ -5,6 +5,9 @@ inhibit_all_warnings!
|
|||
|
||||
install! 'cocoapods', :warn_for_unused_master_specs_repo => false
|
||||
|
||||
# CI Dependencies
|
||||
pod 'xcbeautify'
|
||||
|
||||
# Dependencies to be included in the app and all extensions/frameworks
|
||||
abstract_target 'GlobalDependencies' do
|
||||
# FIXME: If https://github.com/jedisct1/swift-sodium/pull/249 gets resolved then revert this back to the standard pod
|
||||
|
|
|
@ -42,6 +42,7 @@ PODS:
|
|||
- SQLCipher/common
|
||||
- SwiftProtobuf (1.5.0)
|
||||
- WebRTC-lib (114.0.0)
|
||||
- xcbeautify (0.17.0)
|
||||
- YapDatabase/SQLCipher (3.1.1):
|
||||
- YapDatabase/SQLCipher/Core (= 3.1.1)
|
||||
- YapDatabase/SQLCipher/Extensions (= 3.1.1)
|
||||
|
@ -124,6 +125,7 @@ DEPENDENCIES:
|
|||
- SQLCipher (~> 4.5.3)
|
||||
- SwiftProtobuf (~> 1.5.0)
|
||||
- WebRTC-lib
|
||||
- xcbeautify
|
||||
- YapDatabase/SQLCipher (from `https://github.com/oxen-io/session-ios-yap-database.git`, branch `signal-release`)
|
||||
- YYImage/libwebp (from `https://github.com/signalapp/YYImage`)
|
||||
|
||||
|
@ -143,6 +145,8 @@ SPEC REPOS:
|
|||
- SQLCipher
|
||||
- SwiftProtobuf
|
||||
- WebRTC-lib
|
||||
trunk:
|
||||
- xcbeautify
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
Curve25519Kit:
|
||||
|
@ -195,9 +199,10 @@ SPEC CHECKSUMS:
|
|||
SQLCipher: 57fa9f863fa4a3ed9dd3c90ace52315db8c0fdca
|
||||
SwiftProtobuf: 241400280f912735c1e1b9fe675fdd2c6c4d42e2
|
||||
WebRTC-lib: d83df8976fa608b980f1d85796b3de66d60a1953
|
||||
xcbeautify: 6e2f57af5c3a86d490376d5758030a8dcc201c1b
|
||||
YapDatabase: b418a4baa6906e8028748938f9159807fd039af4
|
||||
YYImage: f1ddd15ac032a58b78bbed1e012b50302d318331
|
||||
|
||||
PODFILE CHECKSUM: f56c28baefe3077effcb3a2ea5941b52c4cc6e86
|
||||
PODFILE CHECKSUM: dd814a5a92577bb2a94dac6a1cc482f193721cdf
|
||||
|
||||
COCOAPODS: 1.12.1
|
||||
|
|
|
@ -6366,7 +6366,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 418;
|
||||
CURRENT_PROJECT_VERSION = 419;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||
|
@ -6438,7 +6438,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 418;
|
||||
CURRENT_PROJECT_VERSION = 419;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
|
@ -6503,7 +6503,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 418;
|
||||
CURRENT_PROJECT_VERSION = 419;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||
|
@ -6577,7 +6577,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 418;
|
||||
CURRENT_PROJECT_VERSION = 419;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
|
@ -7537,7 +7537,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 418;
|
||||
CURRENT_PROJECT_VERSION = 419;
|
||||
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -7608,7 +7608,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 418;
|
||||
CURRENT_PROJECT_VERSION = 419;
|
||||
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import Foundation
|
||||
import GRDB
|
||||
import SessionUtilitiesKit
|
||||
|
||||
public enum SNMessagingKit { // Just to make the external API nice
|
||||
public static func migrations() -> TargetMigrations {
|
||||
public enum SNMessagingKit: MigratableTarget { // Just to make the external API nice
|
||||
public static func migrations(_ db: Database) -> TargetMigrations {
|
||||
return TargetMigrations(
|
||||
identifier: .messagingKit,
|
||||
migrations: [
|
||||
|
@ -33,7 +34,7 @@ public enum SNMessagingKit { // Just to make the external API nice
|
|||
// Wait until the feature is turned on before doing the migration that generates
|
||||
// the config dump data
|
||||
// FIXME: Remove this once `useSharedUtilForUserConfig` is permanent
|
||||
(Features.useSharedUtilForUserConfig() ?
|
||||
(Features.useSharedUtilForUserConfig(db) ?
|
||||
_014_GenerateInitialUserConfigDumps.self :
|
||||
(nil as Migration.Type?)
|
||||
)
|
||||
|
|
|
@ -37,9 +37,9 @@ class OpenGroupAPISpec: QuickSpec {
|
|||
beforeEach {
|
||||
mockStorage = Storage(
|
||||
customWriter: try! DatabaseQueue(),
|
||||
customMigrations: [
|
||||
SNUtilitiesKit.migrations(),
|
||||
SNMessagingKit.migrations()
|
||||
customMigrationTargets: [
|
||||
SNUtilitiesKit.self,
|
||||
SNMessagingKit.self
|
||||
]
|
||||
)
|
||||
mockSodium = MockSodium()
|
||||
|
|
|
@ -103,9 +103,9 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
mockGeneralCache = MockGeneralCache()
|
||||
mockStorage = Storage(
|
||||
customWriter: try! DatabaseQueue(),
|
||||
customMigrations: [
|
||||
SNUtilitiesKit.migrations(),
|
||||
SNMessagingKit.migrations()
|
||||
customMigrationTargets: [
|
||||
SNUtilitiesKit.self,
|
||||
SNMessagingKit.self
|
||||
]
|
||||
)
|
||||
mockSodium = MockSodium()
|
||||
|
|
|
@ -27,9 +27,9 @@ class MessageReceiverDecryptionSpec: QuickSpec {
|
|||
beforeEach {
|
||||
mockStorage = Storage(
|
||||
customWriter: try! DatabaseQueue(),
|
||||
customMigrations: [
|
||||
SNUtilitiesKit.migrations(),
|
||||
SNMessagingKit.migrations()
|
||||
customMigrationTargets: [
|
||||
SNUtilitiesKit.self,
|
||||
SNMessagingKit.self
|
||||
]
|
||||
)
|
||||
mockSodium = MockSodium()
|
||||
|
|
|
@ -24,9 +24,9 @@ class MessageSenderEncryptionSpec: QuickSpec {
|
|||
beforeEach {
|
||||
mockStorage = Storage(
|
||||
customWriter: try! DatabaseQueue(),
|
||||
customMigrations: [
|
||||
SNUtilitiesKit.migrations(),
|
||||
SNMessagingKit.migrations()
|
||||
customMigrationTargets: [
|
||||
SNUtilitiesKit.self,
|
||||
SNMessagingKit.self
|
||||
]
|
||||
)
|
||||
mockBox = MockBox()
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import GRDB
|
||||
import SessionUtilitiesKit
|
||||
|
||||
public enum SNSnodeKit { // Just to make the external API nice
|
||||
public static func migrations() -> TargetMigrations {
|
||||
public enum SNSnodeKit: MigratableTarget { // Just to make the external API nice
|
||||
public static func migrations(_ db: Database) -> TargetMigrations {
|
||||
return TargetMigrations(
|
||||
identifier: .snodeKit,
|
||||
migrations: [
|
||||
|
|
|
@ -26,11 +26,11 @@ class ThreadDisappearingMessagesSettingsViewModelSpec: QuickSpec {
|
|||
beforeEach {
|
||||
mockStorage = Storage(
|
||||
customWriter: try! DatabaseQueue(),
|
||||
customMigrations: [
|
||||
SNUtilitiesKit.migrations(),
|
||||
SNSnodeKit.migrations(),
|
||||
SNMessagingKit.migrations(),
|
||||
SNUIKit.migrations()
|
||||
customMigrationTargets: [
|
||||
SNUtilitiesKit.self,
|
||||
SNSnodeKit.self,
|
||||
SNMessagingKit.self,
|
||||
SNUIKit.self
|
||||
]
|
||||
)
|
||||
dependencies = Dependencies(
|
||||
|
|
|
@ -28,11 +28,11 @@ class ThreadSettingsViewModelSpec: QuickSpec {
|
|||
beforeEach {
|
||||
mockStorage = SynchronousStorage(
|
||||
customWriter: try! DatabaseQueue(),
|
||||
customMigrations: [
|
||||
SNUtilitiesKit.migrations(),
|
||||
SNSnodeKit.migrations(),
|
||||
SNMessagingKit.migrations(),
|
||||
SNUIKit.migrations()
|
||||
customMigrationTargets: [
|
||||
SNUtilitiesKit.self,
|
||||
SNSnodeKit.self,
|
||||
SNMessagingKit.self,
|
||||
SNUIKit.self
|
||||
]
|
||||
)
|
||||
mockGeneralCache = MockGeneralCache()
|
||||
|
|
|
@ -25,11 +25,11 @@ class NotificationContentViewModelSpec: QuickSpec {
|
|||
beforeEach {
|
||||
mockStorage = Storage(
|
||||
customWriter: try! DatabaseQueue(),
|
||||
customMigrations: [
|
||||
SNUtilitiesKit.migrations(),
|
||||
SNSnodeKit.migrations(),
|
||||
SNMessagingKit.migrations(),
|
||||
SNUIKit.migrations()
|
||||
customMigrationTargets: [
|
||||
SNUtilitiesKit.self,
|
||||
SNSnodeKit.self,
|
||||
SNMessagingKit.self,
|
||||
SNUIKit.self
|
||||
]
|
||||
)
|
||||
viewModel = NotificationContentViewModel(storage: mockStorage, scheduling: .immediate)
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import GRDB
|
||||
import SessionUtilitiesKit
|
||||
|
||||
public enum SNUIKit {
|
||||
public static func migrations() -> TargetMigrations {
|
||||
public enum SNUIKit: MigratableTarget {
|
||||
public static func migrations(_ db: Database) -> TargetMigrations {
|
||||
return TargetMigrations(
|
||||
identifier: .uiKit,
|
||||
migrations: [
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import GRDB
|
||||
|
||||
public enum SNUtilitiesKit { // Just to make the external API nice
|
||||
public static func migrations() -> TargetMigrations {
|
||||
public enum SNUtilitiesKit: MigratableTarget { // Just to make the external API nice
|
||||
public static func migrations(_ db: Database) -> TargetMigrations {
|
||||
return TargetMigrations(
|
||||
identifier: .utilitiesKit,
|
||||
migrations: [
|
||||
|
|
|
@ -47,14 +47,14 @@ open class Storage {
|
|||
|
||||
public init(
|
||||
customWriter: DatabaseWriter? = nil,
|
||||
customMigrations: [TargetMigrations]? = nil
|
||||
customMigrationTargets: [MigratableTarget.Type]? = nil
|
||||
) {
|
||||
configureDatabase(customWriter: customWriter, customMigrations: customMigrations)
|
||||
configureDatabase(customWriter: customWriter, customMigrationTargets: customMigrationTargets)
|
||||
}
|
||||
|
||||
private func configureDatabase(
|
||||
customWriter: DatabaseWriter? = nil,
|
||||
customMigrations: [TargetMigrations]? = nil
|
||||
customMigrationTargets: [MigratableTarget.Type]? = nil
|
||||
) {
|
||||
// Create the database directory if needed and ensure it's protection level is set before attempting to
|
||||
// create the database KeySpec or the database itself
|
||||
|
@ -66,7 +66,12 @@ open class Storage {
|
|||
dbWriter = customWriter
|
||||
isValid = true
|
||||
Storage.internalHasCreatedValidInstance.mutate { $0 = true }
|
||||
perform(migrations: (customMigrations ?? []), async: false, onProgressUpdate: nil, onComplete: { _, _ in })
|
||||
perform(
|
||||
migrationTargets: (customMigrationTargets ?? []),
|
||||
async: false,
|
||||
onProgressUpdate: nil,
|
||||
onComplete: { _, _ in }
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -128,7 +133,7 @@ open class Storage {
|
|||
}
|
||||
|
||||
public func perform(
|
||||
migrations: [TargetMigrations],
|
||||
migrationTargets: [MigratableTarget.Type],
|
||||
async: Bool = true,
|
||||
onProgressUpdate: ((CGFloat, TimeInterval) -> ())?,
|
||||
onComplete: @escaping (Swift.Result<Void, Error>, Bool) -> ()
|
||||
|
@ -141,18 +146,28 @@ open class Storage {
|
|||
}
|
||||
|
||||
typealias MigrationInfo = (identifier: TargetMigrations.Identifier, migrations: TargetMigrations.MigrationSet)
|
||||
let sortedMigrationInfo: [MigrationInfo] = migrations
|
||||
.sorted()
|
||||
.reduce(into: [[MigrationInfo]]()) { result, next in
|
||||
next.migrations.enumerated().forEach { index, migrationSet in
|
||||
if result.count <= index {
|
||||
result.append([])
|
||||
}
|
||||
let maybeSortedMigrationInfo: [MigrationInfo]? = try? dbWriter
|
||||
.read { db -> [MigrationInfo] in
|
||||
migrationTargets
|
||||
.map { target -> TargetMigrations in target.migrations(db) }
|
||||
.sorted()
|
||||
.reduce(into: [[MigrationInfo]]()) { result, next in
|
||||
next.migrations.enumerated().forEach { index, migrationSet in
|
||||
if result.count <= index {
|
||||
result.append([])
|
||||
}
|
||||
|
||||
result[index] = (result[index] + [(next.identifier, migrationSet)])
|
||||
}
|
||||
result[index] = (result[index] + [(next.identifier, migrationSet)])
|
||||
}
|
||||
}
|
||||
.reduce(into: []) { result, next in result.append(contentsOf: next) }
|
||||
}
|
||||
.reduce(into: []) { result, next in result.append(contentsOf: next) }
|
||||
|
||||
guard let sortedMigrationInfo: [MigrationInfo] = maybeSortedMigrationInfo else {
|
||||
SNLog("[Database Error] Statup failed with error: Unable to prepare migrations")
|
||||
onComplete(.failure(StorageError.startupFailed), false)
|
||||
return
|
||||
}
|
||||
|
||||
// Setup and run any required migrations
|
||||
migrator = { [weak self] in
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import GRDB
|
||||
|
||||
public protocol MigratableTarget {
|
||||
static func migrations(_ db: Database) -> TargetMigrations
|
||||
}
|
||||
|
||||
public struct TargetMigrations: Comparable {
|
||||
/// This identifier is used to determine the order each set of migrations should run in.
|
||||
|
|
|
@ -18,8 +18,8 @@ class IdentitySpec: QuickSpec {
|
|||
beforeEach {
|
||||
mockStorage = Storage(
|
||||
customWriter: try! DatabaseQueue(),
|
||||
customMigrations: [
|
||||
SNUtilitiesKit.migrations()
|
||||
customMigrationTargets: [
|
||||
SNUtilitiesKit.self
|
||||
]
|
||||
)
|
||||
}
|
||||
|
|
|
@ -84,6 +84,17 @@ class PersistableRecordUtilitiesSpec: QuickSpec {
|
|||
}
|
||||
}
|
||||
|
||||
private struct TestTarget: MigratableTarget {
|
||||
static func migrations(_ db: Database) -> TargetMigrations {
|
||||
return TargetMigrations(
|
||||
identifier: .test,
|
||||
migrations: (0..<100)
|
||||
.map { _ in [] }
|
||||
.appending([TestInsertTestTypeMigration.self])
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Spec
|
||||
|
||||
override func spec() {
|
||||
|
@ -96,13 +107,8 @@ class PersistableRecordUtilitiesSpec: QuickSpec {
|
|||
PersistableRecordUtilitiesSpec.customWriter = customWriter
|
||||
mockStorage = Storage(
|
||||
customWriter: customWriter,
|
||||
customMigrations: [
|
||||
TargetMigrations(
|
||||
identifier: .test,
|
||||
migrations: (0..<100)
|
||||
.map { _ in [] }
|
||||
.appending([TestInsertTestTypeMigration.self])
|
||||
)
|
||||
customMigrationTargets: [
|
||||
TestTarget.self
|
||||
]
|
||||
)
|
||||
}
|
||||
|
|
|
@ -66,11 +66,11 @@ public enum AppSetup {
|
|||
var backgroundTask: OWSBackgroundTask? = (backgroundTask ?? OWSBackgroundTask(labelStr: #function))
|
||||
|
||||
Storage.shared.perform(
|
||||
migrations: [
|
||||
SNUtilitiesKit.migrations(),
|
||||
SNSnodeKit.migrations(),
|
||||
SNMessagingKit.migrations(),
|
||||
SNUIKit.migrations()
|
||||
migrationTargets: [
|
||||
SNUtilitiesKit.self,
|
||||
SNSnodeKit.self,
|
||||
SNMessagingKit.self,
|
||||
SNUIKit.self
|
||||
],
|
||||
onProgressUpdate: migrationProgressChanged,
|
||||
onComplete: { result, needsConfigSync in
|
||||
|
|
Loading…
Reference in New Issue