From 901f4eb8127351ce30759071570df2dfeb6750a5 Mon Sep 17 00:00:00 2001 From: Doug Date: Wed, 10 Dec 2025 17:30:50 +0000 Subject: [PATCH 1/3] Remove `eraseToStream` now that `any AsyncSequence` is available to us. # Conflicts: # ElementX/Sources/Screens/LinkNewDeviceScreen/View/LinkNewDeviceScreen.swift --- .../AccessibilityTestsAppCoordinator.swift | 4 +- .../Other/Extensions/AsyncSequence.swift | 15 -------- .../Other/Extensions/Snapshotting.swift | 8 ++-- .../Sources/Other/Extensions/XCTestCase.swift | 38 +++++++++---------- .../LoginScreen/View/LoginScreen.swift | 4 +- .../View/EmojiPickerScreen.swift | 2 +- .../TimelineMediaPreviewDetailsView.swift | 6 +-- .../View/IdentityConfirmationScreen.swift | 2 +- .../View/RoomDetailsScreen.swift | 10 ++--- ...SecureBackupLogoutConfirmationScreen.swift | 8 ++-- .../View/SecureBackupRecoveryKeyScreen.swift | 2 +- .../View/SecureBackupScreen.swift | 8 ++-- .../View/NotificationSettingsScreen.swift | 4 +- .../SettingsScreen/View/SettingsScreen.swift | 4 +- .../View/UserProfileScreen.swift | 6 +-- PreviewTests/Sources/PreviewTests.swift | 4 +- .../ElementX/View/TemplateScreen.swift | 2 +- 17 files changed, 56 insertions(+), 71 deletions(-) diff --git a/ElementX/Sources/AccessibilityTests/AccessibilityTestsAppCoordinator.swift b/ElementX/Sources/AccessibilityTests/AccessibilityTestsAppCoordinator.swift index 0793360fff..b601f3d7b7 100644 --- a/ElementX/Sources/AccessibilityTests/AccessibilityTestsAppCoordinator.swift +++ b/ElementX/Sources/AccessibilityTests/AccessibilityTestsAppCoordinator.swift @@ -154,8 +154,8 @@ struct PreviewsWrapperView: View { // this is a temporary solution .timeout(.seconds(1), scheduler: DispatchQueue.main) .values.first { $0 == true } - case .stream(let stream): - _ = await stream.first { $0 == true } + case .sequence(let sequence): + _ = await sequence.first { $0 == true } case .none: break } diff --git a/ElementX/Sources/Other/Extensions/AsyncSequence.swift b/ElementX/Sources/Other/Extensions/AsyncSequence.swift index f4335e438a..68a9cf51ab 100644 --- a/ElementX/Sources/Other/Extensions/AsyncSequence.swift +++ b/ElementX/Sources/Other/Extensions/AsyncSequence.swift @@ -10,19 +10,4 @@ extension AsyncSequence { func first() async rethrows -> Self.Element? { try await first { _ in true } } - - /// Type-erases the sequence into a newly constructed asynchronous stream. This is useful until - /// we drop support for iOS 17, at which point we can replace this with `any AsyncSequence`. - @available(iOS, deprecated: 18.0, message: "Use `any AsyncSequence` instead.") - func eraseToStream() -> AsyncStream { - var asyncIterator = makeAsyncIterator() - return AsyncStream { - do { - return try await asyncIterator.next() - } catch { - MXLog.warning("Stopping stream: \(error)") - return nil - } - } - } } diff --git a/ElementX/Sources/Other/Extensions/Snapshotting.swift b/ElementX/Sources/Other/Extensions/Snapshotting.swift index 73b63f87aa..8f2707ebda 100644 --- a/ElementX/Sources/Other/Extensions/Snapshotting.swift +++ b/ElementX/Sources/Other/Extensions/Snapshotting.swift @@ -34,7 +34,7 @@ struct SnapshotFulfillmentPreferenceKey: PreferenceKey { enum Source { case publisher(AnyPublisher) - case stream(AsyncStream) + case sequence(any AsyncSequence) } struct Wrapper: Equatable { @@ -69,14 +69,14 @@ extension SwiftUI.View { /// These preferences can then be retrieved and used elsewhere in your view hierarchy. /// /// - Parameters: - /// - expect: A stream that indicates when the preview is ready for snapshotting. + /// - expect: An async sequence that indicates when the preview is ready for snapshotting. /// - precision: The percentage of pixels that must match. /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. 98-99% mimics the precision of the human eye. - func snapshotPreferences(expect fulfillmentStream: AsyncStream? = nil, + func snapshotPreferences(expect fulfillmentSequence: (any AsyncSequence)? = nil, precision: Float = 1.0, perceptualPrecision: Float = 0.98) -> some SwiftUI.View { preference(key: SnapshotPrecisionPreferenceKey.self, value: precision) .preference(key: SnapshotPerceptualPrecisionPreferenceKey.self, value: perceptualPrecision) - .preference(key: SnapshotFulfillmentPreferenceKey.self, value: fulfillmentStream.map { SnapshotFulfillmentPreferenceKey.Wrapper(source: .stream($0)) }) + .preference(key: SnapshotFulfillmentPreferenceKey.self, value: fulfillmentSequence.map { SnapshotFulfillmentPreferenceKey.Wrapper(source: .sequence($0)) }) } } diff --git a/ElementX/Sources/Other/Extensions/XCTestCase.swift b/ElementX/Sources/Other/Extensions/XCTestCase.swift index 6a5eee39ac..e9e2ec07cd 100644 --- a/ElementX/Sources/Other/Extensions/XCTestCase.swift +++ b/ElementX/Sources/Other/Extensions/XCTestCase.swift @@ -49,23 +49,23 @@ extension XCTestCase { } } - /// XCTest utility that assists in observing an async stream, deferring the fulfilment and results until some condition has been met. + /// XCTest utility that assists in observing an async sequence, deferring the fulfilment and results until some condition has been met. /// - Parameters: - /// - asyncStream: The stream to wait on. + /// - asyncSequence: The sequence to wait on. /// - timeout: A timeout after which we give up. /// - message: An optional custom expectation message /// - until: callback that evaluates outputs until some condition is reached - /// - Returns: The deferred fulfilment to be executed after some actions and that returns the result of the stream. - func deferFulfillment(_ asyncStream: AsyncStream, + /// - Returns: The deferred fulfilment to be executed after some actions and that returns the result of the sequence. + func deferFulfillment(_ asyncSequence: any AsyncSequence, timeout: TimeInterval = 10, message: String? = nil, until condition: @escaping (Value) -> Bool) -> DeferredFulfillment { var result: Result? - let expectation = expectation(description: message ?? "Awaiting stream") + let expectation = expectation(description: message ?? "Awaiting sequence") var hasFulfilled = false let task = Task { - for await value in asyncStream { + for await value in asyncSequence { if condition(value), !hasFulfilled { result = .success(value) expectation.fulfill() @@ -77,7 +77,7 @@ extension XCTestCase { return DeferredFulfillment { await self.fulfillment(of: [expectation], timeout: timeout) task.cancel() - let unwrappedResult = try XCTUnwrap(result, "Awaited stream did not produce any output") + let unwrappedResult = try XCTUnwrap(result, "Awaited sequence did not produce any output") return try unwrappedResult.get() } } @@ -108,19 +108,19 @@ extension XCTestCase { return deferred } - /// XCTest utility that assists in subscribing to an async stream and deferring the fulfilment and results until some other actions have been performed. + /// XCTest utility that assists in subscribing to an async sequence and deferring the fulfilment and results until some other actions have been performed. /// - Parameters: - /// - asyncStream: The stream to wait on. - /// - transitionValues: the values through which the stream needs to transition through + /// - asyncSequence: The sequence to wait on. + /// - transitionValues: the values through which the sequence needs to transition through /// - timeout: A timeout after which we give up. /// - message: An optional custom expectation message - /// - Returns: The deferred fulfilment to be executed after some actions and that returns the result of the stream. - func deferFulfillment(_ asyncStream: AsyncStream, + /// - Returns: The deferred fulfilment to be executed after some actions and that returns the result of the sequence. + func deferFulfillment(_ asyncSequence: any AsyncSequence, transitionValues: [Value], timeout: TimeInterval = 10, message: String? = nil) -> DeferredFulfillment { var expectedOrder = transitionValues - let deferred = deferFulfillment(asyncStream, timeout: timeout, message: message) { value in + let deferred = deferFulfillment(asyncSequence, timeout: timeout, message: message) { value in if let index = expectedOrder.firstIndex(where: { $0 == value }), index == 0 { expectedOrder.remove(at: index) } @@ -159,23 +159,23 @@ extension XCTestCase { } } - /// XCTest utility that assists in subscribing to an async stream and deferring the failure for a particular value until some other actions have been performed. + /// XCTest utility that assists in subscribing to an async sequence and deferring the failure for a particular value until some other actions have been performed. /// - Parameters: - /// - asyncStream: The stream to wait on. + /// - asyncSequence: The sequence to wait on. /// - timeout: A timeout after which we give up. /// - message: An optional custom expectation message /// - until: callback that evaluates outputs until some condition is reached - /// - Returns: The deferred fulfilment to be executed after some actions. The stream's result is not returned from this fulfilment. - func deferFailure(_ asyncStream: AsyncStream, + /// - Returns: The deferred fulfilment to be executed after some actions. The sequence's result is not returned from this fulfilment. + func deferFailure(_ asyncSequence: any AsyncSequence, timeout: TimeInterval, message: String? = nil, until condition: @escaping (Value) -> Bool) -> DeferredFulfillment { - let expectation = expectation(description: message ?? "Awaiting stream") + let expectation = expectation(description: message ?? "Awaiting sequence") expectation.isInverted = true var hasFulfilled = false let task = Task { - for await value in asyncStream { + for await value in asyncSequence { if condition(value), !hasFulfilled { expectation.fulfill() hasFulfilled = true diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift index aec527f62a..6d71dc68a5 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift @@ -137,13 +137,13 @@ struct LoginScreen_Previews: PreviewProvider, TestablePreview { NavigationStack { LoginScreen(context: viewModel.context) } - .snapshotPreferences(expect: viewModel.context.observe(\.viewState.homeserver.loginMode).map { $0 == .password }.eraseToStream()) + .snapshotPreferences(expect: viewModel.context.observe(\.viewState.homeserver.loginMode).map { $0 == .password }) .previewDisplayName("Initial State") NavigationStack { LoginScreen(context: credentialsViewModel.context) } - .snapshotPreferences(expect: credentialsViewModel.context.observe(\.viewState.homeserver.loginMode).map { $0 == .password }.eraseToStream()) + .snapshotPreferences(expect: credentialsViewModel.context.observe(\.viewState.homeserver.loginMode).map { $0 == .password }) .previewDisplayName("Credentials Entered") NavigationStack { diff --git a/ElementX/Sources/Screens/EmojiPickerScreen/View/EmojiPickerScreen.swift b/ElementX/Sources/Screens/EmojiPickerScreen/View/EmojiPickerScreen.swift index 7feae2789b..7057d2ec77 100644 --- a/ElementX/Sources/Screens/EmojiPickerScreen/View/EmojiPickerScreen.swift +++ b/ElementX/Sources/Screens/EmojiPickerScreen/View/EmojiPickerScreen.swift @@ -109,7 +109,7 @@ struct EmojiPickerScreen_Previews: PreviewProvider, TestablePreview { static var previews: some View { EmojiPickerScreen(context: viewModel.context) .previewDisplayName("Screen") - .snapshotPreferences(expect: viewModel.context.observe(\.viewState.categories).map { !$0.isEmpty }.eraseToStream()) + .snapshotPreferences(expect: viewModel.context.observe(\.viewState.categories).map { !$0.isEmpty }) } } diff --git a/ElementX/Sources/Screens/FilePreviewScreen/View/TimelineMediaPreviewDetailsView.swift b/ElementX/Sources/Screens/FilePreviewScreen/View/TimelineMediaPreviewDetailsView.swift index c424b3575f..096876ffa9 100644 --- a/ElementX/Sources/Screens/FilePreviewScreen/View/TimelineMediaPreviewDetailsView.swift +++ b/ElementX/Sources/Screens/FilePreviewScreen/View/TimelineMediaPreviewDetailsView.swift @@ -185,7 +185,7 @@ struct TimelineMediaPreviewDetailsView_Previews: PreviewProvider, TestablePrevie if case let .media(mediaItem) = viewModel.state.currentItem { TimelineMediaPreviewDetailsView(item: mediaItem, context: viewModel.context, sheetHeight: $sheetHeight) .previewDisplayName("Image") - .snapshotPreferences(expect: mediaItem.observe(\.fileHandle).map { $0 != nil }.eraseToStream()) + .snapshotPreferences(expect: mediaItem.observe(\.fileHandle).map { $0 != nil }) } if case let .media(mediaItem) = loadingViewModel.state.currentItem { @@ -196,13 +196,13 @@ struct TimelineMediaPreviewDetailsView_Previews: PreviewProvider, TestablePrevie if case let .media(mediaItem) = unknownTypeViewModel.state.currentItem { TimelineMediaPreviewDetailsView(item: mediaItem, context: unknownTypeViewModel.context, sheetHeight: $sheetHeight) .previewDisplayName("Unknown type") - .snapshotPreferences(expect: mediaItem.observe(\.fileHandle).map { $0 != nil }.eraseToStream()) + .snapshotPreferences(expect: mediaItem.observe(\.fileHandle).map { $0 != nil }) } if case let .media(mediaItem) = presentedOnRoomViewModel.state.currentItem { TimelineMediaPreviewDetailsView(item: mediaItem, context: presentedOnRoomViewModel.context, sheetHeight: $sheetHeight) .previewDisplayName("Incoming on Room") - .snapshotPreferences(expect: mediaItem.observe(\.fileHandle).map { $0 != nil }.eraseToStream()) + .snapshotPreferences(expect: mediaItem.observe(\.fileHandle).map { $0 != nil }) } } diff --git a/ElementX/Sources/Screens/Onboarding/IdentityConfirmationScreen/View/IdentityConfirmationScreen.swift b/ElementX/Sources/Screens/Onboarding/IdentityConfirmationScreen/View/IdentityConfirmationScreen.swift index 929ce69518..8715498ca4 100644 --- a/ElementX/Sources/Screens/Onboarding/IdentityConfirmationScreen/View/IdentityConfirmationScreen.swift +++ b/ElementX/Sources/Screens/Onboarding/IdentityConfirmationScreen/View/IdentityConfirmationScreen.swift @@ -127,7 +127,7 @@ struct IdentityConfirmationScreen_Previews: PreviewProvider, TestablePreview { .previewDisplayName("Actions") .snapshotPreferences(expect: viewModel.context.observe(\.viewState.availableActions).map { actions in actions?.contains([.interactiveVerification, .recovery]) == true - }.eraseToStream()) + }) NavigationStack { IdentityConfirmationScreen(context: loadingViewModel.context) diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift index db1daa7380..e48f8740e3 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift @@ -339,23 +339,23 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview { static var previews: some View { RoomDetailsScreen(context: genericRoomViewModel.context) - .snapshotPreferences(expect: genericRoomViewModel.context.observe(\.viewState.permalink).map { $0 != nil }.eraseToStream()) + .snapshotPreferences(expect: genericRoomViewModel.context.observe(\.viewState.permalink).map { $0 != nil }) .previewDisplayName("Generic Room") RoomDetailsScreen(context: simpleRoomViewModel.context) - .snapshotPreferences(expect: simpleRoomViewModel.context.observe(\.viewState.permalink).map { $0 != nil }.eraseToStream()) + .snapshotPreferences(expect: simpleRoomViewModel.context.observe(\.viewState.permalink).map { $0 != nil }) .previewDisplayName("Simple Room") RoomDetailsScreen(context: dmRoomViewModel.context) - .snapshotPreferences(expect: dmRoomViewModel.context.observe(\.viewState.accountOwner).map { $0 != nil }.eraseToStream()) + .snapshotPreferences(expect: dmRoomViewModel.context.observe(\.viewState.accountOwner).map { $0 != nil }) .previewDisplayName("DM Room") RoomDetailsScreen(context: dmRoomVerifiedViewModel.context) - .snapshotPreferences(expect: dmRoomVerifiedViewModel.context.observe(\.viewState.dmRecipientInfo?.verificationState).map { $0 == .verified }.eraseToStream()) + .snapshotPreferences(expect: dmRoomVerifiedViewModel.context.observe(\.viewState.dmRecipientInfo?.verificationState).map { $0 == .verified }) .previewDisplayName("DM Room Verified") RoomDetailsScreen(context: dmRoomVerificationViolationViewModel.context) - .snapshotPreferences(expect: dmRoomVerificationViolationViewModel.context.observe(\.viewState.accountOwner).map { $0 != nil }.eraseToStream()) + .snapshotPreferences(expect: dmRoomVerificationViolationViewModel.context.observe(\.viewState.accountOwner).map { $0 != nil }) .previewDisplayName("DM Room Verification Violation") } diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/View/SecureBackupLogoutConfirmationScreen.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/View/SecureBackupLogoutConfirmationScreen.swift index 3f9b6cf9fa..e55ea5487b 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/View/SecureBackupLogoutConfirmationScreen.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/View/SecureBackupLogoutConfirmationScreen.swift @@ -127,26 +127,26 @@ struct SecureBackupLogoutConfirmationScreen_Previews: PreviewProvider, TestableP SecureBackupLogoutConfirmationScreen(context: waitingViewModel.context) } .previewDisplayName("Waiting") - .snapshotPreferences(expect: waitingViewModel.context.observe(\.viewState.mode).map { $0 == .waitingToStart(hasStalled: false) }.eraseToStream()) + .snapshotPreferences(expect: waitingViewModel.context.observe(\.viewState.mode).map { $0 == .waitingToStart(hasStalled: false) }) NavigationStack { SecureBackupLogoutConfirmationScreen(context: ongoingViewModel.context) } .previewDisplayName("Ongoing") - .snapshotPreferences(expect: ongoingViewModel.context.observe(\.viewState.mode).map { $0 == .backupOngoing(progress: 0.5) }.eraseToStream()) + .snapshotPreferences(expect: ongoingViewModel.context.observe(\.viewState.mode).map { $0 == .backupOngoing(progress: 0.5) }) // Uses the same view model as Waiting but with a different expectation. NavigationStack { SecureBackupLogoutConfirmationScreen(context: waitingViewModel.context) } .previewDisplayName("Stalled") - .snapshotPreferences(expect: waitingViewModel.context.observe(\.viewState.mode).map { $0 == .waitingToStart(hasStalled: true) }.eraseToStream()) + .snapshotPreferences(expect: waitingViewModel.context.observe(\.viewState.mode).map { $0 == .waitingToStart(hasStalled: true) }) NavigationStack { SecureBackupLogoutConfirmationScreen(context: offlineViewModel.context) } .previewDisplayName("Offline") - .snapshotPreferences(expect: offlineViewModel.context.observe(\.viewState.mode).map { $0 == .offline }.eraseToStream()) + .snapshotPreferences(expect: offlineViewModel.context.observe(\.viewState.mode).map { $0 == .offline }) } static func makeViewModel(mode: SecureBackupLogoutConfirmationScreenViewMode) -> SecureBackupLogoutConfirmationScreenViewModel { diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/View/SecureBackupRecoveryKeyScreen.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/View/SecureBackupRecoveryKeyScreen.swift index c21959b647..d2070fc473 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/View/SecureBackupRecoveryKeyScreen.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/View/SecureBackupRecoveryKeyScreen.swift @@ -261,7 +261,7 @@ struct SecureBackupRecoveryKeyScreen_Previews: PreviewProvider, TestablePreview NavigationStack { SecureBackupRecoveryKeyScreen(context: setupViewModel.context) } - .snapshotPreferences(expect: setupViewModel.context.observe(\.viewState.recoveryKey).map { $0 != nil }.eraseToStream()) + .snapshotPreferences(expect: setupViewModel.context.observe(\.viewState.recoveryKey).map { $0 != nil }) .previewDisplayName("Set up") NavigationStack { diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/View/SecureBackupScreen.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/View/SecureBackupScreen.swift index c2344b423a..cd9b80ead9 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/View/SecureBackupScreen.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/View/SecureBackupScreen.swift @@ -129,25 +129,25 @@ struct SecureBackupScreen_Previews: PreviewProvider, TestablePreview { NavigationStack { SecureBackupScreen(context: bothSetupViewModel.context) } - .snapshotPreferences(expect: bothSetupViewModel.context.observe(\.viewState.keyBackupState).map { $0 == .enabled }.eraseToStream()) + .snapshotPreferences(expect: bothSetupViewModel.context.observe(\.viewState.keyBackupState).map { $0 == .enabled }) .previewDisplayName("Both setup") NavigationStack { SecureBackupScreen(context: onlyKeyBackupSetUpViewModel.context) } - .snapshotPreferences(expect: onlyKeyBackupSetUpViewModel.context.observe(\.viewState.keyBackupState).map { $0 == .enabled }.eraseToStream()) + .snapshotPreferences(expect: onlyKeyBackupSetUpViewModel.context.observe(\.viewState.keyBackupState).map { $0 == .enabled }) .previewDisplayName("Only key backup setup") NavigationStack { SecureBackupScreen(context: keyBackupDisabledViewModel.context) } - .snapshotPreferences(expect: keyBackupDisabledViewModel.context.observe(\.viewState.keyBackupState).map { $0 == .unknown }.eraseToStream()) + .snapshotPreferences(expect: keyBackupDisabledViewModel.context.observe(\.viewState.keyBackupState).map { $0 == .unknown }) .previewDisplayName("Key backup disabled") NavigationStack { SecureBackupScreen(context: recoveryIncompleteViewModel.context) } - .snapshotPreferences(expect: recoveryIncompleteViewModel.context.observe(\.viewState.recoveryState).map { $0 == .incomplete }.eraseToStream()) + .snapshotPreferences(expect: recoveryIncompleteViewModel.context.observe(\.viewState.recoveryState).map { $0 == .incomplete }) .previewDisplayName("Recovery incomplete") } diff --git a/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/View/NotificationSettingsScreen.swift b/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/View/NotificationSettingsScreen.swift index 3a3b79974f..3d9ddcda3f 100644 --- a/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/View/NotificationSettingsScreen.swift +++ b/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/View/NotificationSettingsScreen.swift @@ -256,10 +256,10 @@ struct NotificationSettingsScreen_Previews: PreviewProvider, TestablePreview { static var previews: some View { NotificationSettingsScreen(context: viewModel.context) - .snapshotPreferences(expect: viewModel.context.observe(\.viewState.settings).map { $0 != nil }.eraseToStream()) + .snapshotPreferences(expect: viewModel.context.observe(\.viewState.settings).map { $0 != nil }) NotificationSettingsScreen(context: viewModelConfigurationMismatch.context) - .snapshotPreferences(expect: viewModelConfigurationMismatch.context.observe(\.viewState.settings).map { $0 != nil }.eraseToStream()) + .snapshotPreferences(expect: viewModelConfigurationMismatch.context.observe(\.viewState.settings).map { $0 != nil }) .previewDisplayName("Configuration mismatch") } } diff --git a/ElementX/Sources/Screens/Settings/SettingsScreen/View/SettingsScreen.swift b/ElementX/Sources/Screens/Settings/SettingsScreen/View/SettingsScreen.swift index ab89f5d153..9ef6068b31 100644 --- a/ElementX/Sources/Screens/Settings/SettingsScreen/View/SettingsScreen.swift +++ b/ElementX/Sources/Screens/Settings/SettingsScreen/View/SettingsScreen.swift @@ -262,13 +262,13 @@ struct SettingsScreen_Previews: PreviewProvider, TestablePreview { NavigationStack { SettingsScreen(context: viewModel.context) } - .snapshotPreferences(expect: viewModel.context.observe(\.viewState.accountSessionsListURL).map { $0 != nil }.eraseToStream()) + .snapshotPreferences(expect: viewModel.context.observe(\.viewState.accountSessionsListURL).map { $0 != nil }) .previewDisplayName("Default") NavigationStack { SettingsScreen(context: bugReportDisabledViewModel.context) } - .snapshotPreferences(expect: bugReportDisabledViewModel.context.observe(\.viewState.accountSessionsListURL).map { $0 != nil }.eraseToStream()) + .snapshotPreferences(expect: bugReportDisabledViewModel.context.observe(\.viewState.accountSessionsListURL).map { $0 != nil }) .previewDisplayName("Bug report disabled") } diff --git a/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift b/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift index bf5b888d17..8c8ca68e1c 100644 --- a/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift +++ b/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift @@ -104,15 +104,15 @@ struct UserProfileScreen_Previews: PreviewProvider, TestablePreview { static var previews: some View { UserProfileScreen(context: verifiedUserViewModel.context) - .snapshotPreferences(expect: verifiedUserViewModel.context.observe(\.viewState.isVerified).map { $0 != nil }.eraseToStream()) + .snapshotPreferences(expect: verifiedUserViewModel.context.observe(\.viewState.isVerified).map { $0 != nil }) .previewDisplayName("Verified User") UserProfileScreen(context: otherUserViewModel.context) - .snapshotPreferences(expect: otherUserViewModel.context.observe(\.viewState.isVerified).map { $0 != nil }.eraseToStream()) + .snapshotPreferences(expect: otherUserViewModel.context.observe(\.viewState.isVerified).map { $0 != nil }) .previewDisplayName("Other User") UserProfileScreen(context: accountOwnerViewModel.context) - .snapshotPreferences(expect: accountOwnerViewModel.context.observe(\.viewState.isVerified).map { $0 != nil }.eraseToStream()) + .snapshotPreferences(expect: accountOwnerViewModel.context.observe(\.viewState.isVerified).map { $0 != nil }) .previewDisplayName("Account Owner") } diff --git a/PreviewTests/Sources/PreviewTests.swift b/PreviewTests/Sources/PreviewTests.swift index 1013322feb..75f9c93e6f 100644 --- a/PreviewTests/Sources/PreviewTests.swift +++ b/PreviewTests/Sources/PreviewTests.swift @@ -76,8 +76,8 @@ class PreviewTests: XCTestCase { case .publisher(let publisher): let deferred = deferFulfillment(publisher) { $0 == true } try await deferred.fulfill() - case .stream(let stream): - let deferred = deferFulfillment(stream) { $0 == true } + case .sequence(let sequence): + let deferred = deferFulfillment(sequence) { $0 == true } try await deferred.fulfill() case .none: break diff --git a/Tools/Scripts/Templates/SimpleScreenExample/ElementX/View/TemplateScreen.swift b/Tools/Scripts/Templates/SimpleScreenExample/ElementX/View/TemplateScreen.swift index 6b60581292..c7a22fcd30 100644 --- a/Tools/Scripts/Templates/SimpleScreenExample/ElementX/View/TemplateScreen.swift +++ b/Tools/Scripts/Templates/SimpleScreenExample/ElementX/View/TemplateScreen.swift @@ -56,7 +56,7 @@ struct TemplateScreen_Previews: PreviewProvider, TestablePreview { TemplateScreen(context: incrementedViewModel.context) } .previewDisplayName("Incremented") - .snapshotPreferences(expect: incrementedViewModel.context.observe(\.viewState.counter).map { $0 == 1 }.eraseToStream()) + .snapshotPreferences(expect: incrementedViewModel.context.observe(\.viewState.counter).map { $0 == 1 }) } static func makeViewModel(counterValue: Int = 0) -> TemplateScreenViewModel { From c488fd68cd13e811ade1b6491d58a4b77722fb16 Mon Sep 17 00:00:00 2001 From: Doug Date: Wed, 10 Dec 2025 17:34:52 +0000 Subject: [PATCH 2/3] Remove the now unnecessary backport of Mutex. --- ElementX.xcodeproj/project.pbxproj | 61 +++++++------------ .../xcshareddata/swiftpm/Package.resolved | 9 --- .../Sources/Other/Extensions/Observable.swift | 2 +- .../Settings.bundle/Acknowledgements.plist | 8 --- .../Settings.bundle/Packages/Mutex.plist | 36 ----------- ElementX/SupportingFiles/target.yml | 1 - project.yml | 3 - 7 files changed, 23 insertions(+), 97 deletions(-) delete mode 100644 ElementX/SupportingFiles/Settings.bundle/Packages/Mutex.plist diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 96d43a1adb..9b5e1dde51 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -311,13 +311,13 @@ 36926D795D6D19177C7812F8 /* EncryptionResetPasswordScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6935A55AB3B0C94BC566DD6 /* EncryptionResetPasswordScreenCoordinator.swift */; }; 369BF960E52BBEE61F8A5BD1 /* BlockedUsersScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */; }; 36AC963F2F04069B7FF1AA0C /* UIConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */; }; - 36AD4DD4C798E22584ED3200 /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 7731767AE437BA3BD2CC14A8 /* Sentry */; }; - 36CD6E11B37396E14F032CB6 /* SentrySwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = 75361A9D8A3C5501EADB225D /* SentrySwiftUI */; }; + 36AD4DD4C798E22584ED3200 /* SentrySwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = 75361A9D8A3C5501EADB225D /* SentrySwiftUI */; }; + 36CD6E11B37396E14F032CB6 /* Version in Frameworks */ = {isa = PBXBuildFile; productRef = A05AF81DDD14AD58CB0E1B9B /* Version */; }; 36DE961B784087D5E18EF9BA /* LogViewerScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A07692536D66E3DA32C4964 /* LogViewerScreen.swift */; }; 370AF5BFCD4384DD455479B6 /* ElementCallWidgetDriverProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6C11AD9813045E44F950410 /* ElementCallWidgetDriverProtocol.swift */; }; 37906355E207DB5703754675 /* AppLockSetupBiometricsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9F893F4A111CB7BA5C96949 /* AppLockSetupBiometricsScreenViewModel.swift */; }; 37D789F24199B32E3FD1AA7B /* FileRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 216F0DDC98F2A2C162D09C28 /* FileRoomTimelineItemContent.swift */; }; - 37E47F5101C0C036289D3807 /* SwiftOGG in Frameworks */ = {isa = PBXBuildFile; productRef = 391D11F92DFC91666AA1503F /* SwiftOGG */; }; + 37E47F5101C0C036289D3807 /* SwiftSoup in Frameworks */ = {isa = PBXBuildFile; productRef = EDFB92E97D9AC4BA8540C18C /* SwiftSoup */; }; 383063A7924F06D54BA9B24C /* SpaceSettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9475FD81B13D50103E5290EB /* SpaceSettingsScreen.swift */; }; 384D6B9A7DFD7260139D6852 /* UITestsNotificationCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBEB8D9F4940E161B18FE4BC /* UITestsNotificationCenter.swift */; }; 38546A6010A2CF240EC9AF73 /* BindableState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA1D2CBAEA5D0BD00B90D1B /* BindableState.swift */; }; @@ -384,11 +384,11 @@ 441857143FC100E0A7DE42A8 /* RoomPowerLevelProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D635709C1D6D37C225AD40E /* RoomPowerLevelProxyProtocol.swift */; }; 446BCD2D0AE27E0CFD1BDC8F /* ImageMediaEventsTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FF584D757E768EA7776A532 /* ImageMediaEventsTimelineView.swift */; }; 44BDD670FF9095ACE240A3A2 /* VoiceMessageMediaManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC4F10BDD56FA77FEC742333 /* VoiceMessageMediaManagerTests.swift */; }; - 44F0E1B576C7599DF8022071 /* Emojibase in Frameworks */ = {isa = PBXBuildFile; productRef = C05729B1684C331F5FFE9232 /* Emojibase */; }; + 44F0E1B576C7599DF8022071 /* WysiwygComposer in Frameworks */ = {isa = PBXBuildFile; productRef = CA07D57389DACE18AEB6A5E2 /* WysiwygComposer */; }; 454311EAC17D778E19F46592 /* NotificationPermissionsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91868EB98818044E6FEBE532 /* NotificationPermissionsScreenCoordinator.swift */; }; 454F8DDC4442C0DE54094902 /* LABiometryType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3F219838588C62198E726E3 /* LABiometryType.swift */; }; 45D6DC594816288983627484 /* UITestsScreenIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEBE5EA91E8691EDF364EC2 /* UITestsScreenIdentifier.swift */; }; - 4610C57A4785FFF5E67F0C6D /* SwiftSoup in Frameworks */ = {isa = PBXBuildFile; productRef = EDFB92E97D9AC4BA8540C18C /* SwiftSoup */; }; + 4610C57A4785FFF5E67F0C6D /* DSWaveformImageViews in Frameworks */ = {isa = PBXBuildFile; productRef = 2A4106A0A96DC4C273128AA5 /* DSWaveformImageViews */; }; 46562110EE202E580A5FFD9C /* RoomScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93CF7B19FFCF8EFBE0A8696A /* RoomScreenViewModelTests.swift */; }; 4681820102DAC8BA586357D4 /* VoiceMessageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB8D7926A5684E18196B538 /* VoiceMessageCache.swift */; }; 46A183C6125A669AEB005699 /* UserProfileScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F134D2D91DFF732FB75B2CB7 /* UserProfileScreenViewModelProtocol.swift */; }; @@ -657,7 +657,7 @@ 743790BF6A5B0577EA74AF14 /* ReadMarkerRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF3D25B3EDB283B5807EADCF /* ReadMarkerRoomTimelineItem.swift */; }; 748F482FEF4E04D61C39AAD7 /* EmojiPickerScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = F174A5627CDB3CAF280D1880 /* EmojiPickerScreenModels.swift */; }; 7501442D52A65F73DF79FFD4 /* PaginationIndicatorRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B987FC3FDBAA0E1C5AA235C /* PaginationIndicatorRoomTimelineItem.swift */; }; - 754602A7B2AAD443C4228ED4 /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 9573B94B1C86C6DF751AF3FD /* SwiftState */; }; + 754602A7B2AAD443C4228ED4 /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 997C7385E1A07E061D7E2100 /* GZIP */; }; 755395927DDD6EBDDA5E217A /* SettingsFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28F7A6CEEA4A2815B0F0F55 /* SettingsFlowCoordinator.swift */; }; 755727E0B756430DFFEC4732 /* SessionVerificationViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF05DA24F71B455E8EFEBC3B /* SessionVerificationViewModelTests.swift */; }; 756EA0D663261889EF64E6D4 /* VoiceMessageRecordingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9CBF577B9711CFBB4FA40D /* VoiceMessageRecordingView.swift */; }; @@ -918,7 +918,7 @@ A07178337F3C0B208B5A77A8 /* NotificationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6ED50FE104992419310EEB /* NotificationHandler.swift */; }; A0861B727B273B5B3DD7FBF6 /* KnockRequestsListScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09227E671DB30795C43FFFD /* KnockRequestsListScreenViewModel.swift */; }; A0868BDE84D2140A885BE3C9 /* EncryptionResetScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E8562F4D7DE073BC32902AB /* EncryptionResetScreenViewModelProtocol.swift */; }; - A0D7E5BD0298A97DCBDCE40B /* Version in Frameworks */ = {isa = PBXBuildFile; productRef = A05AF81DDD14AD58CB0E1B9B /* Version */; }; + A0D7E5BD0298A97DCBDCE40B /* Emojibase in Frameworks */ = {isa = PBXBuildFile; productRef = C05729B1684C331F5FFE9232 /* Emojibase */; }; A10D6CCDE2010C09EEA1A593 /* HomeScreenRoomList.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7661EFFCAA307A97D71132A /* HomeScreenRoomList.swift */; }; A14A9419105A1CD42F0511C4 /* UserIndicatorModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43005941B3A2C9671E23C85 /* UserIndicatorModalView.swift */; }; A1672EF491FE6F3BBF7878BE /* test_apple_image.heic in Resources */ = {isa = PBXBuildFile; fileRef = BB576F4118C35E6B5124FA22 /* test_apple_image.heic */; }; @@ -968,10 +968,9 @@ A816F7087C495D85048AC50E /* RoomMemberDetailsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B6E30BB748F3F480F077969 /* RoomMemberDetailsScreenModels.swift */; }; A851635B3255C6DC07034A12 /* RoomScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8108C8F0ACF6A7EB72D0117 /* RoomScreenCoordinator.swift */; }; A87DC550659C5176AC1829DE /* ElementTextFieldStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7673F2B0B038FAB2A8D16AD /* ElementTextFieldStyle.swift */; }; - A88328D7E17F73AB64501B51 /* DSWaveformImageViews in Frameworks */ = {isa = PBXBuildFile; productRef = 2A4106A0A96DC4C273128AA5 /* DSWaveformImageViews */; }; A8FA7671948E3DF27F320026 /* BugReportFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7367B3B9A8CAF902220F31D1 /* BugReportFlowCoordinator.swift */; }; A91D125414C3D9ABBABCF2F1 /* KZFileWatchers in Frameworks */ = {isa = PBXBuildFile; productRef = 6690850AA47ECED7E1CAB345 /* KZFileWatchers */; }; - A93661C962B12942C08864B6 /* WysiwygComposer in Frameworks */ = {isa = PBXBuildFile; productRef = CA07D57389DACE18AEB6A5E2 /* WysiwygComposer */; }; + A93661C962B12942C08864B6 /* SwiftOGG in Frameworks */ = {isa = PBXBuildFile; productRef = 391D11F92DFC91666AA1503F /* SwiftOGG */; }; A950C95855C474F75B30CA7B /* PollFormScreenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCDAB580109C09A6AA97AF7E /* PollFormScreenTests.swift */; }; A969147E0EEE0E27EE226570 /* MediaUploadPreviewScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47F29139BC2A804CE5E0757E /* MediaUploadPreviewScreenViewModel.swift */; }; A975D60EA49F6AF73308809F /* RoomMembersListScreenMemberCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC03209FDE8CE0810617BFFF /* RoomMembersListScreenMemberCell.swift */; }; @@ -1002,7 +1001,7 @@ AF8BFA37791E1756EE243E08 /* SettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8F0ED874DF8C9A51B0AB6F /* SettingsScreenCoordinator.swift */; }; AFE2AB612A1460E49578D746 /* JoinRoomScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BDCCD2F6B405C14B9BCE94E /* JoinRoomScreenCoordinator.swift */; }; B04E9EB589CE99C3929E817A /* HomeScreenRecoveryKeyConfirmationBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05512FB13987D221B7205DE0 /* HomeScreenRecoveryKeyConfirmationBanner.swift */; }; - B0CB16349B96262AA65A04AF /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 997C7385E1A07E061D7E2100 /* GZIP */; }; + B0CB16349B96262AA65A04AF /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 7731767AE437BA3BD2CC14A8 /* Sentry */; }; B1069F361E604D5436AE9FFD /* StaticLocationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B06663F7858E45882E63471 /* StaticLocationScreen.swift */; }; B1088417801A962BA861C13F /* RoomPowerLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E247E29C7A0E421DB839D7 /* RoomPowerLevel.swift */; }; B10F7D5C237417DA160F4603 /* LongPressWithFeedback.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D9F148717D74F73BE724434 /* LongPressWithFeedback.swift */; }; @@ -1309,7 +1308,7 @@ EA78A7512AFB1E5451744EB1 /* AppRouteURLParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E461B3C8BBBFCA400B268D14 /* AppRouteURLParserTests.swift */; }; EA8D941771E762A5D3D7FA0D /* FileMediaEventsTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 430C73079A84654BF46A7FF5 /* FileMediaEventsTimelineView.swift */; }; EAB3C1F0BC7F671ED8BDF82D /* CompletionSuggestionServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ECF11669EF253E98AA2977A /* CompletionSuggestionServiceProtocol.swift */; }; - EAC6FE2CD4F50A43068ADCD8 /* PostHog in Frameworks */ = {isa = PBXBuildFile; productRef = 4278261E147DB2DE5CFB7FC5 /* PostHog */; }; + EAC6FE2CD4F50A43068ADCD8 /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 9573B94B1C86C6DF751AF3FD /* SwiftState */; }; EAF2B3E6C6AEC4AD3A8BD454 /* RoomMemberDetailsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A87D0471D438A233C2CF4A /* RoomMemberDetailsScreenViewModel.swift */; }; EB87DF90CF6F8D5D12404C6E /* SecureBackupLogoutConfirmationScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848F69921527D31CAACB93AF /* SecureBackupLogoutConfirmationScreenViewModelTests.swift */; }; EB88DBD77221E2CFE463018C /* NSE.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 0D8F620C8B314840D8602E3F /* NSE.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; @@ -1417,7 +1416,7 @@ FBD402E3170EB1ED0D1AA672 /* EncryptionKeyProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2355398E4A55DA5A89128AD1 /* EncryptionKeyProvider.swift */; }; FBF09B6C900415800DDF2A21 /* EmojiProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C113E0CB7E15E9765B1817A /* EmojiProvider.swift */; }; FC0EEFF630F34899953BB950 /* BigIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01FD1171FF40E34D707FD00 /* BigIcon.swift */; }; - FC10228E73323BDC09526F97 /* Mutex in Frameworks */ = {isa = PBXBuildFile; productRef = AC946195B56DE9EACB9F6343 /* Mutex */; }; + FC10228E73323BDC09526F97 /* PostHog in Frameworks */ = {isa = PBXBuildFile; productRef = 4278261E147DB2DE5CFB7FC5 /* PostHog */; }; FC31493979ED1FDF7D5EA3F9 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */; }; FCD3F2B82CAB29A07887A127 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = DE8DC9B3FBA402117DC4C49F /* Kingfisher */; }; FCF95603F1D056B1B106A415 /* AdvancedSettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83E2B20431F890ED64255CA1 /* AdvancedSettingsScreenViewModelProtocol.swift */; }; @@ -2978,18 +2977,17 @@ 6298AB0906DDD3525CD78C6B /* LoremSwiftum in Frameworks */, 407DCE030E0F9B7C9861D38A /* LRUCache in Frameworks */, 8F2FAA98457750D9D664136F /* Mapbox in Frameworks */, - FC10228E73323BDC09526F97 /* Mutex in Frameworks */, - EAC6FE2CD4F50A43068ADCD8 /* PostHog in Frameworks */, - 754602A7B2AAD443C4228ED4 /* SwiftState in Frameworks */, - B0CB16349B96262AA65A04AF /* GZIP in Frameworks */, - 36AD4DD4C798E22584ED3200 /* Sentry in Frameworks */, - 36CD6E11B37396E14F032CB6 /* SentrySwiftUI in Frameworks */, - A0D7E5BD0298A97DCBDCE40B /* Version in Frameworks */, - 44F0E1B576C7599DF8022071 /* Emojibase in Frameworks */, - A93661C962B12942C08864B6 /* WysiwygComposer in Frameworks */, - 37E47F5101C0C036289D3807 /* SwiftOGG in Frameworks */, - 4610C57A4785FFF5E67F0C6D /* SwiftSoup in Frameworks */, - A88328D7E17F73AB64501B51 /* DSWaveformImageViews in Frameworks */, + FC10228E73323BDC09526F97 /* PostHog in Frameworks */, + EAC6FE2CD4F50A43068ADCD8 /* SwiftState in Frameworks */, + 754602A7B2AAD443C4228ED4 /* GZIP in Frameworks */, + B0CB16349B96262AA65A04AF /* Sentry in Frameworks */, + 36AD4DD4C798E22584ED3200 /* SentrySwiftUI in Frameworks */, + 36CD6E11B37396E14F032CB6 /* Version in Frameworks */, + A0D7E5BD0298A97DCBDCE40B /* Emojibase in Frameworks */, + 44F0E1B576C7599DF8022071 /* WysiwygComposer in Frameworks */, + A93661C962B12942C08864B6 /* SwiftOGG in Frameworks */, + 37E47F5101C0C036289D3807 /* SwiftSoup in Frameworks */, + 4610C57A4785FFF5E67F0C6D /* DSWaveformImageViews in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -6858,7 +6856,6 @@ 1A6B622CCFDEFB92D9CF1CA5 /* LoremSwiftum */, 1081D3630AAD3ACEDDEC3A98 /* LRUCache */, C1BF15833233CD3BDB7E2B1D /* Mapbox */, - AC946195B56DE9EACB9F6343 /* Mutex */, 4278261E147DB2DE5CFB7FC5 /* PostHog */, 9573B94B1C86C6DF751AF3FD /* SwiftState */, 997C7385E1A07E061D7E2100 /* GZIP */, @@ -7037,7 +7034,6 @@ 4BDA7F6042968E8422470F3F /* XCRemoteSwiftPackageReference "LoremSwiftum" */, 0CBF57301AA172C21F76CE86 /* XCRemoteSwiftPackageReference "maplibre-gl-native-distribution" */, 6FC4820D8D4559CEECA064D7 /* XCRemoteSwiftPackageReference "matrix-rust-components-swift" */, - 91740346377FEBEAF7AD32FC /* XCRemoteSwiftPackageReference "swift-mutex" */, 96495DD8554E2F39D3954354 /* XCRemoteSwiftPackageReference "posthog-ios" */, A08925A9D5E3770DEB9D8509 /* XCRemoteSwiftPackageReference "sentry-cocoa" */, E9C4F3A12AA1F65C13A8C8EB /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */, @@ -9581,14 +9577,6 @@ minimumVersion = 1.0.6; }; }; - 91740346377FEBEAF7AD32FC /* XCRemoteSwiftPackageReference "swift-mutex" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/swhitty/swift-mutex"; - requirement = { - kind = upToNextMinorVersion; - minimumVersion = 0.0.6; - }; - }; 96495DD8554E2F39D3954354 /* XCRemoteSwiftPackageReference "posthog-ios" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/PostHog/posthog-ios"; @@ -9919,11 +9907,6 @@ package = D5F7D47BBAAE0CF1DDEB3034 /* XCRemoteSwiftPackageReference "DeviceKit" */; productName = DeviceKit; }; - AC946195B56DE9EACB9F6343 /* Mutex */ = { - isa = XCSwiftPackageProductDependency; - package = 91740346377FEBEAF7AD32FC /* XCRemoteSwiftPackageReference "swift-mutex" */; - productName = Mutex; - }; AD544C0FA48DFFB080920061 /* Collections */ = { isa = XCSwiftPackageProductDependency; package = F76A08D0EA29A07A54F4EB4D /* XCRemoteSwiftPackageReference "swift-collections" */; diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 6e83175d71..c77277b2ee 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -261,15 +261,6 @@ "version" : "1.3.3" } }, - { - "identity" : "swift-mutex", - "kind" : "remoteSourceControl", - "location" : "https://github.com/swhitty/swift-mutex", - "state" : { - "revision" : "1770152df756b54c28ef1787df1e957d93cc62d5", - "version" : "0.0.6" - } - }, { "identity" : "swift-numerics", "kind" : "remoteSourceControl", diff --git a/ElementX/Sources/Other/Extensions/Observable.swift b/ElementX/Sources/Other/Extensions/Observable.swift index fdced4a697..5be2dea447 100644 --- a/ElementX/Sources/Other/Extensions/Observable.swift +++ b/ElementX/Sources/Other/Extensions/Observable.swift @@ -7,7 +7,7 @@ // import Foundation -import Mutex +import Synchronization extension Observable { /// Creates an async stream for the specified property on this object. We probably won't need this once SE-0475 is available: diff --git a/ElementX/SupportingFiles/Settings.bundle/Acknowledgements.plist b/ElementX/SupportingFiles/Settings.bundle/Acknowledgements.plist index cf6d4223ea..d1a011a0f1 100644 --- a/ElementX/SupportingFiles/Settings.bundle/Acknowledgements.plist +++ b/ElementX/SupportingFiles/Settings.bundle/Acknowledgements.plist @@ -210,14 +210,6 @@ Type PSChildPaneSpecifier - - File - Packages/Mutex - Title - Mutex - Type - PSChildPaneSpecifier - File Packages/swift-numerics diff --git a/ElementX/SupportingFiles/Settings.bundle/Packages/Mutex.plist b/ElementX/SupportingFiles/Settings.bundle/Packages/Mutex.plist deleted file mode 100644 index 64d8fdff20..0000000000 --- a/ElementX/SupportingFiles/Settings.bundle/Packages/Mutex.plist +++ /dev/null @@ -1,36 +0,0 @@ - - - - - PreferenceSpecifiers - - - FooterText - MIT License - -Copyright (c) 2023 Simon Whitty - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - Type - PSGroupSpecifier - - - - diff --git a/ElementX/SupportingFiles/target.yml b/ElementX/SupportingFiles/target.yml index 33afe57c3f..a66af0c3ac 100644 --- a/ElementX/SupportingFiles/target.yml +++ b/ElementX/SupportingFiles/target.yml @@ -235,7 +235,6 @@ targets: - package: LoremSwiftum - package: LRUCache - package: Mapbox - - package: Mutex - package: PostHog - package: SwiftState - package: GZIP diff --git a/project.yml b/project.yml index d616c6dae2..52f70c0396 100644 --- a/project.yml +++ b/project.yml @@ -138,9 +138,6 @@ packages: Mapbox: url: https://github.com/maplibre/maplibre-gl-native-distribution minorVersion: 5.13.0 - Mutex: # Backports Swift's built in Mutex so we can use it on iOS 17. - url: https://github.com/swhitty/swift-mutex - minorVersion: 0.0.6 PostHog: url: https://github.com/PostHog/posthog-ios minorVersion: 3.27.0 From 1d60bc21535283f452559376954cec9220c886be Mon Sep 17 00:00:00 2001 From: Doug Date: Wed, 10 Dec 2025 17:41:29 +0000 Subject: [PATCH 3/3] Silence a couple more deprecation warnings. --- .../Sources/Services/Media/MediaUploadingPreprocessor.swift | 2 +- ElementX/Sources/UITests/UITestsSignalling.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ElementX/Sources/Services/Media/MediaUploadingPreprocessor.swift b/ElementX/Sources/Services/Media/MediaUploadingPreprocessor.swift index a1a37737ea..5b361021d6 100644 --- a/ElementX/Sources/Services/Media/MediaUploadingPreprocessor.swift +++ b/ElementX/Sources/Services/Media/MediaUploadingPreprocessor.swift @@ -396,7 +396,7 @@ struct MediaUploadingPreprocessor { /// - Parameter url: the video URL /// - Returns: the URL for the resulting thumbnail and its sizing info as an `ImageProcessingResult` private func generateThumbnailForVideoAt(_ url: URL) async throws(MediaUploadingPreprocessorError) -> ImageProcessingInfo { - let assetImageGenerator = AVAssetImageGenerator(asset: AVAsset(url: url)) + let assetImageGenerator = AVAssetImageGenerator(asset: AVURLAsset(url: url)) assetImageGenerator.appliesPreferredTrackTransform = true assetImageGenerator.maximumSize = Constants.maximumThumbnailSize diff --git a/ElementX/Sources/UITests/UITestsSignalling.swift b/ElementX/Sources/UITests/UITestsSignalling.swift index c5d1ddaadc..e22326d62b 100644 --- a/ElementX/Sources/UITests/UITestsSignalling.swift +++ b/ElementX/Sources/UITests/UITestsSignalling.swift @@ -94,7 +94,7 @@ enum UITestsSignalling { try rawMessage(.ready).write(to: fileURL, atomically: false, encoding: .utf8) case .app: // The app client is started second and checks that there is a ready signal from the tests. - guard try String(contentsOf: fileURL) == Message(mode: .tests, signal: .ready).rawValue else { throw UITestsSignalError.testsClientNotReady } + guard try String(contentsOf: fileURL, encoding: .utf8) == Message(mode: .tests, signal: .ready).rawValue else { throw UITestsSignalError.testsClientNotReady } isConnected = true // The app client then echoes back to the tests that it is now ready. try send(.ready)