mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:33:26 +00:00
Remove eraseToStream now that any AsyncSequence is available to us. (#4836)
* Remove `eraseToStream` now that `any AsyncSequence` is available to us. * Remove the now unnecessary backport of Mutex. * Silence a couple more deprecation warnings.
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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<Element> {
|
||||
var asyncIterator = makeAsyncIterator()
|
||||
return AsyncStream<Element> {
|
||||
do {
|
||||
return try await asyncIterator.next()
|
||||
} catch {
|
||||
MXLog.warning("Stopping stream: \(error)")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -34,7 +34,7 @@ struct SnapshotFulfillmentPreferenceKey: PreferenceKey {
|
||||
|
||||
enum Source {
|
||||
case publisher(AnyPublisher<Bool, Never>)
|
||||
case stream(AsyncStream<Bool>)
|
||||
case sequence(any AsyncSequence<Bool, Never>)
|
||||
}
|
||||
|
||||
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<Bool>? = nil,
|
||||
func snapshotPreferences(expect fulfillmentSequence: (any AsyncSequence<Bool, Never>)? = 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)) })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Value>(_ asyncStream: AsyncStream<Value>,
|
||||
/// - Returns: The deferred fulfilment to be executed after some actions and that returns the result of the sequence.
|
||||
func deferFulfillment<Value>(_ asyncSequence: any AsyncSequence<Value, Never>,
|
||||
timeout: TimeInterval = 10,
|
||||
message: String? = nil,
|
||||
until condition: @escaping (Value) -> Bool) -> DeferredFulfillment<Value> {
|
||||
var result: Result<Value, Error>?
|
||||
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<Value> {
|
||||
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<Value: Equatable>(_ asyncStream: AsyncStream<Value>,
|
||||
/// - Returns: The deferred fulfilment to be executed after some actions and that returns the result of the sequence.
|
||||
func deferFulfillment<Value: Equatable>(_ asyncSequence: any AsyncSequence<Value, Never>,
|
||||
transitionValues: [Value],
|
||||
timeout: TimeInterval = 10,
|
||||
message: String? = nil) -> DeferredFulfillment<Value> {
|
||||
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<Value>(_ asyncStream: AsyncStream<Value>,
|
||||
/// - Returns: The deferred fulfilment to be executed after some actions. The sequence's result is not returned from this fulfilment.
|
||||
func deferFailure<Value>(_ asyncSequence: any AsyncSequence<Value, Never>,
|
||||
timeout: TimeInterval,
|
||||
message: String? = nil,
|
||||
until condition: @escaping (Value) -> Bool) -> DeferredFulfillment<Void> {
|
||||
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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -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 })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
+4
-4
@@ -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")
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user