diff --git a/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift b/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift index c8702156d..c34420f7c 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift @@ -21,7 +21,7 @@ enum LoadableImageMediaType: Equatable { } struct LoadableImage: View { - private let mediaSource: MediaSourceProxy + private let mediaSource: MediaSourceProxy? private let mediaType: LoadableImageMediaType private let blurhash: String? private let size: CGSize? @@ -60,27 +60,31 @@ struct LoadableImage: View { mediaProvider: MediaProviderProtocol?, transformer: @escaping (AnyView) -> TransformerView = { $0 }, placeholder: @escaping () -> PlaceholderView) { - self.init(mediaSource: MediaSourceProxy(url: url, mimeType: nil), - mediaType: mediaType, - blurhash: blurhash, - size: size, - mediaProvider: mediaProvider, - transformer: transformer, - placeholder: placeholder) + mediaSource = try? MediaSourceProxy(url: url, mimeType: nil) + self.mediaType = mediaType + self.blurhash = blurhash + self.size = size + self.mediaProvider = mediaProvider + self.transformer = transformer + self.placeholder = placeholder } var body: some View { - LoadableImageContent(mediaSource: mediaSource, - mediaType: mediaType, - blurhash: blurhash, - size: size, - mediaProvider: mediaProvider, - transformer: transformer, - placeholder: placeholder) - .id(stableMediaIdentifier) + if let mediaSource { + LoadableImageContent(mediaSource: mediaSource, + mediaType: mediaType, + blurhash: blurhash, + size: size, + mediaProvider: mediaProvider, + transformer: transformer, + placeholder: placeholder) + .id(stableMediaIdentifier) + } else { + placeholder() + } } - private var stableMediaIdentifier: String { + private var stableMediaIdentifier: String? { switch mediaType { case .timelineItem(let uniqueID): // Consider media for the same item to be the same view @@ -88,7 +92,7 @@ struct LoadableImage: View { default: // Binds the lifecycle of the LoadableImage to the associated URL. // This fixes the problem of the cache returning old values after a change in the URL. - mediaSource.url.absoluteString + mediaSource?.url.absoluteString } } } diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift index 34a8d8a27..a7a8cbd85 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift @@ -363,7 +363,8 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr } // We don't actually know the mime type here, assume it's an image. - if case let .success(file) = await mediaProvider.loadFileFromSource(.init(url: url, mimeType: "image/jpeg")) { + if let mediaSource = try? MediaSourceProxy(url: url, mimeType: "image/jpeg"), + case let .success(file) = await mediaProvider.loadFileFromSource(mediaSource) { state.bindings.mediaPreviewItem = MediaPreviewItem(file: file, title: roomProxy.infoPublisher.value.displayName) } } diff --git a/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift b/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift index 178183a85..ac550181f 100644 --- a/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift @@ -165,7 +165,8 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro defer { userIndicatorController.retractIndicatorWithId(loadingIndicatorIdentifier) } // We don't actually know the mime type here, assume it's an image. - if case let .success(file) = await mediaProvider.loadFileFromSource(.init(url: url, mimeType: "image/jpeg")) { + if let mediaSource = try? MediaSourceProxy(url: url, mimeType: "image/jpeg"), + case let .success(file) = await mediaProvider.loadFileFromSource(mediaSource) { state.bindings.mediaPreviewItem = MediaPreviewItem(file: file, title: roomMemberProxy.displayName) } } diff --git a/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModel.swift b/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModel.swift index 01a0f1033..bbf1f2eff 100644 --- a/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModel.swift +++ b/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModel.swift @@ -104,7 +104,8 @@ class UserProfileScreenViewModel: UserProfileScreenViewModelType, UserProfileScr defer { hideLoadingIndicator() } // We don't actually know the mime type here, assume it's an image. - if case let .success(file) = await mediaProvider.loadFileFromSource(.init(url: url, mimeType: "image/jpeg")) { + if let mediaSource = try? MediaSourceProxy(url: url, mimeType: "image/jpeg"), + case let .success(file) = await mediaProvider.loadFileFromSource(mediaSource) { state.bindings.mediaPreviewItem = MediaPreviewItem(file: file, title: userProfile.displayName) } } diff --git a/ElementX/Sources/Services/Media/Provider/MediaSourceProxy.swift b/ElementX/Sources/Services/Media/Provider/MediaSourceProxy.swift index 50023b562..2f1a85a82 100644 --- a/ElementX/Sources/Services/Media/Provider/MediaSourceProxy.swift +++ b/ElementX/Sources/Services/Media/Provider/MediaSourceProxy.swift @@ -23,11 +23,8 @@ struct MediaSourceProxy: Hashable { self.mimeType = mimeType } - init(url: URL, mimeType: String?) { - guard let mediaSource = try? MediaSource.fromUrl(url: url.absoluteString) else { - fatalError("Unable to create MediaSource from URL: \(url.absoluteString)") - } - underlyingSource = mediaSource + init(url: URL, mimeType: String?) throws { + underlyingSource = try MediaSource.fromUrl(url: url.absoluteString) self.url = URL(string: underlyingSource.url()) self.mimeType = mimeType } diff --git a/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxy.swift b/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxy.swift index 40cbf1e8a..ab181df3d 100644 --- a/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxy.swift +++ b/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxy.swift @@ -55,7 +55,7 @@ struct NotificationItemProxy: NotificationItemProxyProtocol { var senderAvatarMediaSource: MediaSourceProxy? { if let senderAvatarURLString = notificationItem.senderInfo.avatarUrl, let senderAvatarURL = URL(string: senderAvatarURLString) { - return MediaSourceProxy(url: senderAvatarURL, mimeType: nil) + return try? MediaSourceProxy(url: senderAvatarURL, mimeType: nil) } return nil } @@ -63,7 +63,7 @@ struct NotificationItemProxy: NotificationItemProxyProtocol { var roomAvatarMediaSource: MediaSourceProxy? { if let roomAvatarURLString = notificationItem.roomInfo.avatarUrl, let roomAvatarURL = URL(string: roomAvatarURLString) { - return MediaSourceProxy(url: roomAvatarURL, mimeType: nil) + return try? MediaSourceProxy(url: roomAvatarURL, mimeType: nil) } return nil } diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift index a9abcd63f..bdf6a5a6e 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift @@ -195,9 +195,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol { } } - if let avatarURL { - let mediaSource = MediaSourceProxy(url: avatarURL, mimeType: nil) - + if let avatarURL, let mediaSource = try? MediaSourceProxy(url: avatarURL, mimeType: nil) { if case let .success(avatarData) = await mediaProvider.loadThumbnailForSource(source: mediaSource, size: .init(width: 100, height: 100)) { sendMessageIntent.setImage(INImage(imageData: avatarData), forParameterNamed: \.speakableGroupName) } else { diff --git a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift index 776a6c552..bd024e496 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift @@ -243,11 +243,15 @@ struct VideoInfoProxy: Hashable { } static var mockVideo: VideoInfoProxy { - .init(source: .init(url: .mockMXCVideo, mimeType: nil), - duration: 100, - size: .init(width: 1920, height: 1080), - aspectRatio: 1.78, - mimeType: nil) + guard let mediaSource = try? MediaSourceProxy(url: .mockMXCVideo, mimeType: nil) else { + fatalError("Invalid mock media source URL") + } + + return .init(source: mediaSource, + duration: 100, + size: .init(width: 1920, height: 1080), + aspectRatio: 1.78, + mimeType: nil) } } @@ -269,10 +273,6 @@ struct ImageInfoProxy: Hashable { self.init(source: .init(source: source, mimeType: mimeType), width: width, height: height, mimeType: mimeType) } - init(url: URL, width: UInt64?, height: UInt64?, mimeType: String?) { - self.init(source: .init(url: url, mimeType: mimeType), width: width, height: height, mimeType: mimeType) - } - init(source: MediaSourceProxy, width: UInt64?, height: UInt64?, mimeType: String?) { self.source = source @@ -292,17 +292,25 @@ struct ImageInfoProxy: Hashable { } static var mockImage: ImageInfoProxy { - .init(source: .init(url: .mockMXCImage, mimeType: "image/png"), - size: .init(width: 100, height: 100), - aspectRatio: 1, - mimeType: "image/png") + guard let mediaSource = try? MediaSourceProxy(url: .mockMXCImage, mimeType: "image/png") else { + fatalError("Invalid mock media source URL") + } + + return .init(source: mediaSource, + size: .init(width: 100, height: 100), + aspectRatio: 1, + mimeType: "image/png") } static var mockThumbnail: ImageInfoProxy { - .init(source: .init(url: .mockMXCImage, mimeType: nil), - size: nil, - aspectRatio: nil, - mimeType: nil) + guard let mediaSource = try? MediaSourceProxy(url: .mockMXCImage, mimeType: "image/png") else { + fatalError("Invalid mock media source URL") + } + + return .init(source: mediaSource, + size: nil, + aspectRatio: nil, + mimeType: nil) } } diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift index 0843b042f..e1a3fd6c5 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift @@ -33,12 +33,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { case .redactedMessage: return buildRedactedTimelineItem(eventItemProxy, isOutgoing) case .sticker(let body, let imageInfo, let mediaSource): - guard let url = URL(string: mediaSource.url()) else { - MXLog.error("Invalid sticker url string: \(mediaSource.url())") - return buildUnsupportedTimelineItem(eventItemProxy, "m.sticker", "Invalid Sticker URL", isOutgoing) - } - - return buildStickerTimelineItem(eventItemProxy, body, imageInfo, url, isOutgoing) + return buildStickerTimelineItem(eventItemProxy, body, imageInfo, mediaSource, isOutgoing) case .failedToParseMessageLike(let eventType, let error): return buildUnsupportedTimelineItem(eventItemProxy, eventType, error, isOutgoing) case .failedToParseState(let eventType, _, let error): @@ -119,9 +114,9 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { private func buildStickerTimelineItem(_ eventItemProxy: EventTimelineItemProxy, _ body: String, _ info: MatrixRustSDK.ImageInfo, - _ imageURL: URL, + _ mediaSource: MediaSource, _ isOutgoing: Bool) -> RoomTimelineItemProtocol { - let imageInfo = ImageInfoProxy(url: imageURL, width: info.width, height: info.height, mimeType: info.mimetype) + let imageInfo = ImageInfoProxy(source: mediaSource, width: info.width, height: info.height, mimeType: info.mimetype) return StickerRoomTimelineItem(id: eventItemProxy.id, body: body, diff --git a/UnitTests/Sources/MediaProvider/MediaLoaderTests.swift b/UnitTests/Sources/MediaProvider/MediaLoaderTests.swift index 2e2b6e7d8..bca846f2b 100644 --- a/UnitTests/Sources/MediaProvider/MediaLoaderTests.swift +++ b/UnitTests/Sources/MediaProvider/MediaLoaderTests.swift @@ -10,12 +10,12 @@ import MatrixRustSDK import XCTest final class MediaLoaderTests: XCTestCase { - func testMediaRequestCoalescing() async { + func testMediaRequestCoalescing() async throws { let mediaLoadingClient = ClientSDKMock() mediaLoadingClient.getMediaContentMediaSourceReturnValue = Data() let mediaLoader = MediaLoader(client: mediaLoadingClient) - let mediaSource = MediaSourceProxy(url: .mockMXCFile, mimeType: nil) + let mediaSource = try MediaSourceProxy(url: .mockMXCFile, mimeType: nil) do { for _ in 1...10 { @@ -28,12 +28,12 @@ final class MediaLoaderTests: XCTestCase { } } - func testMediaThumbnailRequestCoalescing() async { + func testMediaThumbnailRequestCoalescing() async throws { let mediaLoadingClient = ClientSDKMock() mediaLoadingClient.getMediaThumbnailMediaSourceWidthHeightReturnValue = Data() let mediaLoader = MediaLoader(client: mediaLoadingClient) - let mediaSource = MediaSourceProxy(url: .mockMXCImage, mimeType: nil) + let mediaSource = try MediaSourceProxy(url: .mockMXCImage, mimeType: nil) do { for _ in 1...10 { diff --git a/UnitTests/Sources/MediaProvider/MediaProviderTests.swift b/UnitTests/Sources/MediaProvider/MediaProviderTests.swift index 9e1dc87bd..a012afe77 100644 --- a/UnitTests/Sources/MediaProvider/MediaProviderTests.swift +++ b/UnitTests/Sources/MediaProvider/MediaProviderTests.swift @@ -36,7 +36,7 @@ final class MediaProviderTests: XCTestCase { return } - let loadTask = mediaProvider.loadImageRetryingOnReconnection(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg")) + let loadTask = try mediaProvider.loadImageRetryingOnReconnection(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg")) let connectivitySubject = CurrentValueSubject(.unreachable) @@ -59,7 +59,7 @@ final class MediaProviderTests: XCTestCase { } func testLoadingRetriedOnReconnectionCancelsAfterSecondFailure() async throws { - let loadTask = mediaProvider.loadImageRetryingOnReconnection(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg")) + let loadTask = try mediaProvider.loadImageRetryingOnReconnection(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg")) let connectivitySubject = CurrentValueSubject(.reachable) @@ -73,7 +73,7 @@ final class MediaProviderTests: XCTestCase { } func test_whenImageFromSourceWithSourceNil_nilReturned() throws { - let image = mediaProvider.imageFromSource(nil, size: Avatars.Size.room(on: .timeline).scaledSize) + let image = try mediaProvider.imageFromSource(nil, size: Avatars.Size.room(on: .timeline).scaledSize) XCTAssertNil(image) } @@ -83,14 +83,14 @@ final class MediaProviderTests: XCTestCase { let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}" let imageForKey = UIImage() imageCache.retrievedImagesInMemory[key] = imageForKey - let image = mediaProvider.imageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"), - size: avatarSize.scaledSize) + let image = try mediaProvider.imageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"), + size: avatarSize.scaledSize) XCTAssertEqual(image, imageForKey) } func test_whenImageFromSourceWithSourceNotNilAndImageNotCached_nilReturned() throws { - let image = mediaProvider.imageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), - size: Avatars.Size.room(on: .timeline).scaledSize) + let image = try mediaProvider.imageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), + size: Avatars.Size.room(on: .timeline).scaledSize) XCTAssertNil(image) } @@ -100,8 +100,8 @@ final class MediaProviderTests: XCTestCase { let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}" let imageForKey = UIImage() imageCache.retrievedImagesInMemory[key] = imageForKey - let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"), - size: avatarSize.scaledSize) + let result = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"), + size: avatarSize.scaledSize) XCTAssertEqual(Result.success(imageForKey), result) } @@ -111,8 +111,8 @@ final class MediaProviderTests: XCTestCase { let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}" let imageForKey = UIImage() imageCache.retrievedImages[key] = imageForKey - let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"), - size: avatarSize.scaledSize) + let result = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"), + size: avatarSize.scaledSize) XCTAssertEqual(Result.success(imageForKey), result) } @@ -122,8 +122,8 @@ final class MediaProviderTests: XCTestCase { mediaLoader.loadMediaThumbnailForSourceWidthHeightReturnValue = expectedImage.pngData() - let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), - size: avatarSize.scaledSize) + let result = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), + size: avatarSize.scaledSize) switch result { case .success(let image): XCTAssertEqual(image.pngData(), expectedImage.pngData()) @@ -140,8 +140,8 @@ final class MediaProviderTests: XCTestCase { mediaLoader.loadMediaThumbnailForSourceWidthHeightReturnValue = expectedImage.pngData() - _ = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"), - size: avatarSize.scaledSize) + _ = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"), + size: avatarSize.scaledSize) let storedImage = try XCTUnwrap(imageCache.storedImages[key]) XCTAssertEqual(expectedImage.pngData(), storedImage.pngData()) } @@ -151,8 +151,8 @@ final class MediaProviderTests: XCTestCase { mediaLoader.loadMediaContentForSourceReturnValue = expectedImage.pngData() - let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), - size: nil) + let result = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), + size: nil) switch result { case .success(let image): XCTAssertEqual(image.pngData(), expectedImage.pngData()) @@ -164,8 +164,8 @@ final class MediaProviderTests: XCTestCase { func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndLoadImageThumbnailFails_errorIsThrown() async throws { mediaLoader.loadMediaThumbnailForSourceWidthHeightThrowableError = MediaProviderTestsError.error - let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), - size: Avatars.Size.room(on: .timeline).scaledSize) + let result = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), + size: Avatars.Size.room(on: .timeline).scaledSize) switch result { case .success: XCTFail("Should fail") @@ -177,8 +177,8 @@ final class MediaProviderTests: XCTestCase { func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndNoAvatarSizeAndLoadImageContentFails_errorIsThrown() async throws { mediaLoader.loadMediaContentForSourceThrowableError = MediaProviderTestsError.error - let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), - size: nil) + let result = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), + size: nil) switch result { case .success: XCTFail("Should fail") @@ -190,8 +190,8 @@ final class MediaProviderTests: XCTestCase { func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndImageThumbnailIsLoadedWithCorruptedData_errorIsThrown() async throws { mediaLoader.loadMediaThumbnailForSourceWidthHeightReturnValue = Data() - let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), - size: Avatars.Size.room(on: .timeline).scaledSize) + let result = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), + size: Avatars.Size.room(on: .timeline).scaledSize) switch result { case .success: XCTFail("Should fail") diff --git a/UnitTests/Sources/VoiceMessageCacheTests.swift b/UnitTests/Sources/VoiceMessageCacheTests.swift index 752086776..d5cb77a7f 100644 --- a/UnitTests/Sources/VoiceMessageCacheTests.swift +++ b/UnitTests/Sources/VoiceMessageCacheTests.swift @@ -26,7 +26,7 @@ class VoiceMessageCacheTests: XCTestCase { voiceMessageCache.clearCache() fileManager = FileManager.default - mediaSource = MediaSourceProxy(url: someURL, mimeType: "audio/ogg") + mediaSource = try MediaSourceProxy(url: someURL, mimeType: "audio/ogg") // Create the temporary directory we will use try fileManager.createDirectory(at: testTemporaryDirectory, withIntermediateDirectories: true) diff --git a/UnitTests/Sources/VoiceMessageMediaManagerTests.swift b/UnitTests/Sources/VoiceMessageMediaManagerTests.swift index 2aeecf062..b9dba4287 100644 --- a/UnitTests/Sources/VoiceMessageMediaManagerTests.swift +++ b/UnitTests/Sources/VoiceMessageMediaManagerTests.swift @@ -28,7 +28,7 @@ class VoiceMessageMediaManagerTests: XCTestCase { func testLoadVoiceMessageFromSourceUnsupportedMedia() async throws { // Only "audio/ogg" file are supported - let unsupportedMediaSource = MediaSourceProxy(url: someURL, mimeType: "audio/wav") + let unsupportedMediaSource = try MediaSourceProxy(url: someURL, mimeType: "audio/wav") do { _ = try await voiceMessageMediaManager.loadVoiceMessageFromSource(unsupportedMediaSource, body: nil) XCTFail("A `VoiceMessageMediaManagerError.unsupportedMimeTye` error is expected") @@ -49,7 +49,7 @@ class VoiceMessageMediaManagerTests: XCTestCase { let cachedConvertedFileURL = URL("/some/url/cached_converted_file.m4a") voiceMessageCache.fileURLForReturnValue = nil - let mediaSource = MediaSourceProxy(url: someURL, mimeType: "audio/ogg; codecs=opus") + let mediaSource = try MediaSourceProxy(url: someURL, mimeType: "audio/ogg; codecs=opus") mediaProvider.loadFileFromSourceFilenameReturnValue = .success(MediaFileHandleProxy.unmanaged(url: loadedFile)) voiceMessageCache.cacheMediaSourceUsingMoveReturnValue = .success(cachedConvertedFileURL) @@ -67,7 +67,7 @@ class VoiceMessageMediaManagerTests: XCTestCase { func testLoadVoiceMessageFromSourceAlreadyCached() async throws { // Check if the file is already present in cache voiceMessageCache.fileURLForReturnValue = URL("/converted_file/url") - let mediaSource = MediaSourceProxy(url: someURL, mimeType: audioOGGMimeType) + let mediaSource = try MediaSourceProxy(url: someURL, mimeType: audioOGGMimeType) let url = try await voiceMessageMediaManager.loadVoiceMessageFromSource(mediaSource, body: nil) XCTAssertEqual(url, URL("/converted_file/url")) // The file must have be search in the cache @@ -81,7 +81,7 @@ class VoiceMessageMediaManagerTests: XCTestCase { // An error must be reported if the file cannot be retrieved do { voiceMessageCache.fileURLForReturnValue = nil - let mediaSource = MediaSourceProxy(url: someURL, mimeType: audioOGGMimeType) + let mediaSource = try MediaSourceProxy(url: someURL, mimeType: audioOGGMimeType) _ = try await voiceMessageMediaManager.loadVoiceMessageFromSource(mediaSource, body: nil) XCTFail("A `MediaProviderError.failedRetrievingFile` error is expected") } catch { @@ -102,7 +102,7 @@ class VoiceMessageMediaManagerTests: XCTestCase { // Check if the file is not already present in cache voiceMessageCache.fileURLForReturnValue = nil - let mediaSource = MediaSourceProxy(url: someURL, mimeType: audioOGGMimeType) + let mediaSource = try MediaSourceProxy(url: someURL, mimeType: audioOGGMimeType) mediaProvider.loadFileFromSourceFilenameReturnValue = .success(MediaFileHandleProxy.unmanaged(url: loadedFile)) let audioConverter = AudioConverterMock() voiceMessageCache.cacheMediaSourceUsingMoveReturnValue = .success(cachedConvertedFileURL) @@ -145,7 +145,7 @@ class VoiceMessageMediaManagerTests: XCTestCase { voiceMessageCache: voiceMessageCache, audioConverter: audioConverter) - let mediaSource = MediaSourceProxy(url: someURL, mimeType: audioOGGMimeType) + let mediaSource = try MediaSourceProxy(url: someURL, mimeType: audioOGGMimeType) for _ in 0..<10 { let url = try await voiceMessageMediaManager.loadVoiceMessageFromSource(mediaSource, body: nil) XCTAssertEqual(url, cachedConvertedFileURL)