mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-05 20:09:04 +00:00
Update the SDK and use media filename and caption internally. (#3375)
Doesn't render captions (other than in fallback places).
This commit is contained in:
@@ -1921,6 +1921,7 @@
|
|||||||
A84D413BF49F0E980F010A6B /* LogViewerScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewerScreenCoordinator.swift; sourceTree = "<group>"; };
|
A84D413BF49F0E980F010A6B /* LogViewerScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewerScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||||
A861DA5932B128FE1DCB5CE2 /* InviteUsersScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenCoordinator.swift; sourceTree = "<group>"; };
|
A861DA5932B128FE1DCB5CE2 /* InviteUsersScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||||
A8DF55467ED4CE76B7AE9A33 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
A8DF55467ED4CE76B7AE9A33 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||||
|
A9873374E72AA53260AE90A2 /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = fa.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
A9B069D7772DDF6513E0F1B8 /* AuthenticationFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationFlowCoordinator.swift; sourceTree = "<group>"; };
|
A9B069D7772DDF6513E0F1B8 /* AuthenticationFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationFlowCoordinator.swift; sourceTree = "<group>"; };
|
||||||
A9E6065FC6BC4A1B4C629E08 /* TimelineItemMenuActionProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemMenuActionProvider.swift; sourceTree = "<group>"; };
|
A9E6065FC6BC4A1B4C629E08 /* TimelineItemMenuActionProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemMenuActionProvider.swift; sourceTree = "<group>"; };
|
||||||
A9FAFE1C2149E6AC8156ED2B /* Collection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Collection.swift; sourceTree = "<group>"; };
|
A9FAFE1C2149E6AC8156ED2B /* Collection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Collection.swift; sourceTree = "<group>"; };
|
||||||
@@ -2065,6 +2066,7 @@
|
|||||||
C6A9F49B3EE59147AF2F70BB /* SeparatorRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineItem.swift; sourceTree = "<group>"; };
|
C6A9F49B3EE59147AF2F70BB /* SeparatorRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||||
C6FEA87EA3752203065ECE27 /* BugReportUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportUITests.swift; sourceTree = "<group>"; };
|
C6FEA87EA3752203065ECE27 /* BugReportUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportUITests.swift; sourceTree = "<group>"; };
|
||||||
C705E605EF57C19DBE86FFA1 /* PlaceholderAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderAvatarImage.swift; sourceTree = "<group>"; };
|
C705E605EF57C19DBE86FFA1 /* PlaceholderAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderAvatarImage.swift; sourceTree = "<group>"; };
|
||||||
|
C715CFE00686DACA59D836EA /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = fa.lproj/SAS.strings; sourceTree = "<group>"; };
|
||||||
C729D95CB4588D4D9AAC3DFA /* RoomChangePermissionsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangePermissionsScreenModels.swift; sourceTree = "<group>"; };
|
C729D95CB4588D4D9AAC3DFA /* RoomChangePermissionsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangePermissionsScreenModels.swift; sourceTree = "<group>"; };
|
||||||
C733D11B421CFE3A657EF230 /* test_image.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = test_image.png; sourceTree = "<group>"; };
|
C733D11B421CFE3A657EF230 /* test_image.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = test_image.png; sourceTree = "<group>"; };
|
||||||
C75EF87651B00A176AB08E97 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
C75EF87651B00A176AB08E97 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
@@ -5755,6 +5757,7 @@
|
|||||||
en,
|
en,
|
||||||
es,
|
es,
|
||||||
et,
|
et,
|
||||||
|
fa,
|
||||||
fr,
|
fr,
|
||||||
hu,
|
hu,
|
||||||
id,
|
id,
|
||||||
@@ -7119,6 +7122,7 @@
|
|||||||
7447C0AD7EF302CD027D6230 /* en */,
|
7447C0AD7EF302CD027D6230 /* en */,
|
||||||
6722709BD6178E10B70C9641 /* es */,
|
6722709BD6178E10B70C9641 /* es */,
|
||||||
F3C7252B3461D06175D975A4 /* et */,
|
F3C7252B3461D06175D975A4 /* et */,
|
||||||
|
C715CFE00686DACA59D836EA /* fa */,
|
||||||
CEE20623EB4A9B88FB29F2BA /* fr */,
|
CEE20623EB4A9B88FB29F2BA /* fr */,
|
||||||
D196116D2DD3F2757D45FCB7 /* hu */,
|
D196116D2DD3F2757D45FCB7 /* hu */,
|
||||||
330AF4D121C3396F7A14B21D /* id */,
|
330AF4D121C3396F7A14B21D /* id */,
|
||||||
@@ -7178,6 +7182,7 @@
|
|||||||
CACA846B3E3E9A521D98B178 /* en */,
|
CACA846B3E3E9A521D98B178 /* en */,
|
||||||
CBBCC6E74774E79B599625D0 /* es */,
|
CBBCC6E74774E79B599625D0 /* es */,
|
||||||
A443FAE2EE820A5790C35C8D /* et */,
|
A443FAE2EE820A5790C35C8D /* et */,
|
||||||
|
A9873374E72AA53260AE90A2 /* fa */,
|
||||||
CC680E0E79D818706CB28CF8 /* fr */,
|
CC680E0E79D818706CB28CF8 /* fr */,
|
||||||
624244C398804ADC885239AA /* hu */,
|
624244C398804ADC885239AA /* hu */,
|
||||||
EF98A02DED04075F7CF0C721 /* id */,
|
EF98A02DED04075F7CF0C721 /* id */,
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ extension ClientProxyMock {
|
|||||||
|
|
||||||
loadMediaContentForSourceThrowableError = ClientProxyError.sdkError(ClientProxyMockError.generic)
|
loadMediaContentForSourceThrowableError = ClientProxyError.sdkError(ClientProxyMockError.generic)
|
||||||
loadMediaThumbnailForSourceWidthHeightThrowableError = ClientProxyError.sdkError(ClientProxyMockError.generic)
|
loadMediaThumbnailForSourceWidthHeightThrowableError = ClientProxyError.sdkError(ClientProxyMockError.generic)
|
||||||
loadMediaFileForSourceBodyThrowableError = ClientProxyError.sdkError(ClientProxyMockError.generic)
|
loadMediaFileForSourceFilenameThrowableError = ClientProxyError.sdkError(ClientProxyMockError.generic)
|
||||||
|
|
||||||
secureBackupController = {
|
secureBackupController = {
|
||||||
let secureBackupController = SecureBackupControllerMock()
|
let secureBackupController = SecureBackupControllerMock()
|
||||||
|
|||||||
@@ -4710,16 +4710,16 @@ class ClientProxyMock: ClientProxyProtocol {
|
|||||||
}
|
}
|
||||||
//MARK: - loadMediaFileForSource
|
//MARK: - loadMediaFileForSource
|
||||||
|
|
||||||
var loadMediaFileForSourceBodyThrowableError: Error?
|
var loadMediaFileForSourceFilenameThrowableError: Error?
|
||||||
var loadMediaFileForSourceBodyUnderlyingCallsCount = 0
|
var loadMediaFileForSourceFilenameUnderlyingCallsCount = 0
|
||||||
var loadMediaFileForSourceBodyCallsCount: Int {
|
var loadMediaFileForSourceFilenameCallsCount: Int {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return loadMediaFileForSourceBodyUnderlyingCallsCount
|
return loadMediaFileForSourceFilenameUnderlyingCallsCount
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Int? = nil
|
var returnValue: Int? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = loadMediaFileForSourceBodyUnderlyingCallsCount
|
returnValue = loadMediaFileForSourceFilenameUnderlyingCallsCount
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -4727,29 +4727,29 @@ class ClientProxyMock: ClientProxyProtocol {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
loadMediaFileForSourceBodyUnderlyingCallsCount = newValue
|
loadMediaFileForSourceFilenameUnderlyingCallsCount = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
loadMediaFileForSourceBodyUnderlyingCallsCount = newValue
|
loadMediaFileForSourceFilenameUnderlyingCallsCount = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var loadMediaFileForSourceBodyCalled: Bool {
|
var loadMediaFileForSourceFilenameCalled: Bool {
|
||||||
return loadMediaFileForSourceBodyCallsCount > 0
|
return loadMediaFileForSourceFilenameCallsCount > 0
|
||||||
}
|
}
|
||||||
var loadMediaFileForSourceBodyReceivedArguments: (source: MediaSourceProxy, body: String?)?
|
var loadMediaFileForSourceFilenameReceivedArguments: (source: MediaSourceProxy, filename: String?)?
|
||||||
var loadMediaFileForSourceBodyReceivedInvocations: [(source: MediaSourceProxy, body: String?)] = []
|
var loadMediaFileForSourceFilenameReceivedInvocations: [(source: MediaSourceProxy, filename: String?)] = []
|
||||||
|
|
||||||
var loadMediaFileForSourceBodyUnderlyingReturnValue: MediaFileHandleProxy!
|
var loadMediaFileForSourceFilenameUnderlyingReturnValue: MediaFileHandleProxy!
|
||||||
var loadMediaFileForSourceBodyReturnValue: MediaFileHandleProxy! {
|
var loadMediaFileForSourceFilenameReturnValue: MediaFileHandleProxy! {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return loadMediaFileForSourceBodyUnderlyingReturnValue
|
return loadMediaFileForSourceFilenameUnderlyingReturnValue
|
||||||
} else {
|
} else {
|
||||||
var returnValue: MediaFileHandleProxy? = nil
|
var returnValue: MediaFileHandleProxy? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = loadMediaFileForSourceBodyUnderlyingReturnValue
|
returnValue = loadMediaFileForSourceFilenameUnderlyingReturnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -4757,29 +4757,29 @@ class ClientProxyMock: ClientProxyProtocol {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
loadMediaFileForSourceBodyUnderlyingReturnValue = newValue
|
loadMediaFileForSourceFilenameUnderlyingReturnValue = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
loadMediaFileForSourceBodyUnderlyingReturnValue = newValue
|
loadMediaFileForSourceFilenameUnderlyingReturnValue = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var loadMediaFileForSourceBodyClosure: ((MediaSourceProxy, String?) async throws -> MediaFileHandleProxy)?
|
var loadMediaFileForSourceFilenameClosure: ((MediaSourceProxy, String?) async throws -> MediaFileHandleProxy)?
|
||||||
|
|
||||||
func loadMediaFileForSource(_ source: MediaSourceProxy, body: String?) async throws -> MediaFileHandleProxy {
|
func loadMediaFileForSource(_ source: MediaSourceProxy, filename: String?) async throws -> MediaFileHandleProxy {
|
||||||
if let error = loadMediaFileForSourceBodyThrowableError {
|
if let error = loadMediaFileForSourceFilenameThrowableError {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
loadMediaFileForSourceBodyCallsCount += 1
|
loadMediaFileForSourceFilenameCallsCount += 1
|
||||||
loadMediaFileForSourceBodyReceivedArguments = (source: source, body: body)
|
loadMediaFileForSourceFilenameReceivedArguments = (source: source, filename: filename)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.loadMediaFileForSourceBodyReceivedInvocations.append((source: source, body: body))
|
self.loadMediaFileForSourceFilenameReceivedInvocations.append((source: source, filename: filename))
|
||||||
}
|
}
|
||||||
if let loadMediaFileForSourceBodyClosure = loadMediaFileForSourceBodyClosure {
|
if let loadMediaFileForSourceFilenameClosure = loadMediaFileForSourceFilenameClosure {
|
||||||
return try await loadMediaFileForSourceBodyClosure(source, body)
|
return try await loadMediaFileForSourceFilenameClosure(source, filename)
|
||||||
} else {
|
} else {
|
||||||
return loadMediaFileForSourceBodyReturnValue
|
return loadMediaFileForSourceFilenameReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9693,16 +9693,16 @@ class MediaLoaderMock: MediaLoaderProtocol {
|
|||||||
}
|
}
|
||||||
//MARK: - loadMediaFileForSource
|
//MARK: - loadMediaFileForSource
|
||||||
|
|
||||||
var loadMediaFileForSourceBodyThrowableError: Error?
|
var loadMediaFileForSourceFilenameThrowableError: Error?
|
||||||
var loadMediaFileForSourceBodyUnderlyingCallsCount = 0
|
var loadMediaFileForSourceFilenameUnderlyingCallsCount = 0
|
||||||
var loadMediaFileForSourceBodyCallsCount: Int {
|
var loadMediaFileForSourceFilenameCallsCount: Int {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return loadMediaFileForSourceBodyUnderlyingCallsCount
|
return loadMediaFileForSourceFilenameUnderlyingCallsCount
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Int? = nil
|
var returnValue: Int? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = loadMediaFileForSourceBodyUnderlyingCallsCount
|
returnValue = loadMediaFileForSourceFilenameUnderlyingCallsCount
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -9710,29 +9710,29 @@ class MediaLoaderMock: MediaLoaderProtocol {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
loadMediaFileForSourceBodyUnderlyingCallsCount = newValue
|
loadMediaFileForSourceFilenameUnderlyingCallsCount = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
loadMediaFileForSourceBodyUnderlyingCallsCount = newValue
|
loadMediaFileForSourceFilenameUnderlyingCallsCount = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var loadMediaFileForSourceBodyCalled: Bool {
|
var loadMediaFileForSourceFilenameCalled: Bool {
|
||||||
return loadMediaFileForSourceBodyCallsCount > 0
|
return loadMediaFileForSourceFilenameCallsCount > 0
|
||||||
}
|
}
|
||||||
var loadMediaFileForSourceBodyReceivedArguments: (source: MediaSourceProxy, body: String?)?
|
var loadMediaFileForSourceFilenameReceivedArguments: (source: MediaSourceProxy, filename: String?)?
|
||||||
var loadMediaFileForSourceBodyReceivedInvocations: [(source: MediaSourceProxy, body: String?)] = []
|
var loadMediaFileForSourceFilenameReceivedInvocations: [(source: MediaSourceProxy, filename: String?)] = []
|
||||||
|
|
||||||
var loadMediaFileForSourceBodyUnderlyingReturnValue: MediaFileHandleProxy!
|
var loadMediaFileForSourceFilenameUnderlyingReturnValue: MediaFileHandleProxy!
|
||||||
var loadMediaFileForSourceBodyReturnValue: MediaFileHandleProxy! {
|
var loadMediaFileForSourceFilenameReturnValue: MediaFileHandleProxy! {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return loadMediaFileForSourceBodyUnderlyingReturnValue
|
return loadMediaFileForSourceFilenameUnderlyingReturnValue
|
||||||
} else {
|
} else {
|
||||||
var returnValue: MediaFileHandleProxy? = nil
|
var returnValue: MediaFileHandleProxy? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = loadMediaFileForSourceBodyUnderlyingReturnValue
|
returnValue = loadMediaFileForSourceFilenameUnderlyingReturnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -9740,29 +9740,29 @@ class MediaLoaderMock: MediaLoaderProtocol {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
loadMediaFileForSourceBodyUnderlyingReturnValue = newValue
|
loadMediaFileForSourceFilenameUnderlyingReturnValue = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
loadMediaFileForSourceBodyUnderlyingReturnValue = newValue
|
loadMediaFileForSourceFilenameUnderlyingReturnValue = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var loadMediaFileForSourceBodyClosure: ((MediaSourceProxy, String?) async throws -> MediaFileHandleProxy)?
|
var loadMediaFileForSourceFilenameClosure: ((MediaSourceProxy, String?) async throws -> MediaFileHandleProxy)?
|
||||||
|
|
||||||
func loadMediaFileForSource(_ source: MediaSourceProxy, body: String?) async throws -> MediaFileHandleProxy {
|
func loadMediaFileForSource(_ source: MediaSourceProxy, filename: String?) async throws -> MediaFileHandleProxy {
|
||||||
if let error = loadMediaFileForSourceBodyThrowableError {
|
if let error = loadMediaFileForSourceFilenameThrowableError {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
loadMediaFileForSourceBodyCallsCount += 1
|
loadMediaFileForSourceFilenameCallsCount += 1
|
||||||
loadMediaFileForSourceBodyReceivedArguments = (source: source, body: body)
|
loadMediaFileForSourceFilenameReceivedArguments = (source: source, filename: filename)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.loadMediaFileForSourceBodyReceivedInvocations.append((source: source, body: body))
|
self.loadMediaFileForSourceFilenameReceivedInvocations.append((source: source, filename: filename))
|
||||||
}
|
}
|
||||||
if let loadMediaFileForSourceBodyClosure = loadMediaFileForSourceBodyClosure {
|
if let loadMediaFileForSourceFilenameClosure = loadMediaFileForSourceFilenameClosure {
|
||||||
return try await loadMediaFileForSourceBodyClosure(source, body)
|
return try await loadMediaFileForSourceFilenameClosure(source, filename)
|
||||||
} else {
|
} else {
|
||||||
return loadMediaFileForSourceBodyReturnValue
|
return loadMediaFileForSourceFilenameReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10628,15 +10628,15 @@ class MediaProviderMock: MediaProviderProtocol {
|
|||||||
}
|
}
|
||||||
//MARK: - loadFileFromSource
|
//MARK: - loadFileFromSource
|
||||||
|
|
||||||
var loadFileFromSourceBodyUnderlyingCallsCount = 0
|
var loadFileFromSourceFilenameUnderlyingCallsCount = 0
|
||||||
var loadFileFromSourceBodyCallsCount: Int {
|
var loadFileFromSourceFilenameCallsCount: Int {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return loadFileFromSourceBodyUnderlyingCallsCount
|
return loadFileFromSourceFilenameUnderlyingCallsCount
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Int? = nil
|
var returnValue: Int? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = loadFileFromSourceBodyUnderlyingCallsCount
|
returnValue = loadFileFromSourceFilenameUnderlyingCallsCount
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -10644,29 +10644,29 @@ class MediaProviderMock: MediaProviderProtocol {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
loadFileFromSourceBodyUnderlyingCallsCount = newValue
|
loadFileFromSourceFilenameUnderlyingCallsCount = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
loadFileFromSourceBodyUnderlyingCallsCount = newValue
|
loadFileFromSourceFilenameUnderlyingCallsCount = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var loadFileFromSourceBodyCalled: Bool {
|
var loadFileFromSourceFilenameCalled: Bool {
|
||||||
return loadFileFromSourceBodyCallsCount > 0
|
return loadFileFromSourceFilenameCallsCount > 0
|
||||||
}
|
}
|
||||||
var loadFileFromSourceBodyReceivedArguments: (source: MediaSourceProxy, body: String?)?
|
var loadFileFromSourceFilenameReceivedArguments: (source: MediaSourceProxy, filename: String?)?
|
||||||
var loadFileFromSourceBodyReceivedInvocations: [(source: MediaSourceProxy, body: String?)] = []
|
var loadFileFromSourceFilenameReceivedInvocations: [(source: MediaSourceProxy, filename: String?)] = []
|
||||||
|
|
||||||
var loadFileFromSourceBodyUnderlyingReturnValue: Result<MediaFileHandleProxy, MediaProviderError>!
|
var loadFileFromSourceFilenameUnderlyingReturnValue: Result<MediaFileHandleProxy, MediaProviderError>!
|
||||||
var loadFileFromSourceBodyReturnValue: Result<MediaFileHandleProxy, MediaProviderError>! {
|
var loadFileFromSourceFilenameReturnValue: Result<MediaFileHandleProxy, MediaProviderError>! {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return loadFileFromSourceBodyUnderlyingReturnValue
|
return loadFileFromSourceFilenameUnderlyingReturnValue
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Result<MediaFileHandleProxy, MediaProviderError>? = nil
|
var returnValue: Result<MediaFileHandleProxy, MediaProviderError>? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = loadFileFromSourceBodyUnderlyingReturnValue
|
returnValue = loadFileFromSourceFilenameUnderlyingReturnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -10674,26 +10674,26 @@ class MediaProviderMock: MediaProviderProtocol {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
loadFileFromSourceBodyUnderlyingReturnValue = newValue
|
loadFileFromSourceFilenameUnderlyingReturnValue = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
loadFileFromSourceBodyUnderlyingReturnValue = newValue
|
loadFileFromSourceFilenameUnderlyingReturnValue = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var loadFileFromSourceBodyClosure: ((MediaSourceProxy, String?) async -> Result<MediaFileHandleProxy, MediaProviderError>)?
|
var loadFileFromSourceFilenameClosure: ((MediaSourceProxy, String?) async -> Result<MediaFileHandleProxy, MediaProviderError>)?
|
||||||
|
|
||||||
func loadFileFromSource(_ source: MediaSourceProxy, body: String?) async -> Result<MediaFileHandleProxy, MediaProviderError> {
|
func loadFileFromSource(_ source: MediaSourceProxy, filename: String?) async -> Result<MediaFileHandleProxy, MediaProviderError> {
|
||||||
loadFileFromSourceBodyCallsCount += 1
|
loadFileFromSourceFilenameCallsCount += 1
|
||||||
loadFileFromSourceBodyReceivedArguments = (source: source, body: body)
|
loadFileFromSourceFilenameReceivedArguments = (source: source, filename: filename)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.loadFileFromSourceBodyReceivedInvocations.append((source: source, body: body))
|
self.loadFileFromSourceFilenameReceivedInvocations.append((source: source, filename: filename))
|
||||||
}
|
}
|
||||||
if let loadFileFromSourceBodyClosure = loadFileFromSourceBodyClosure {
|
if let loadFileFromSourceFilenameClosure = loadFileFromSourceFilenameClosure {
|
||||||
return await loadFileFromSourceBodyClosure(source, body)
|
return await loadFileFromSourceFilenameClosure(source, filename)
|
||||||
} else {
|
} else {
|
||||||
return loadFileFromSourceBodyReturnValue
|
return loadFileFromSourceFilenameReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6139,6 +6139,81 @@ open class EncryptionSDKMock: MatrixRustSDK.Encryption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//MARK: - getUserIdentity
|
||||||
|
|
||||||
|
open var getUserIdentityUserIdThrowableError: Error?
|
||||||
|
var getUserIdentityUserIdUnderlyingCallsCount = 0
|
||||||
|
open var getUserIdentityUserIdCallsCount: Int {
|
||||||
|
get {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
return getUserIdentityUserIdUnderlyingCallsCount
|
||||||
|
} else {
|
||||||
|
var returnValue: Int? = nil
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
returnValue = getUserIdentityUserIdUnderlyingCallsCount
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
getUserIdentityUserIdUnderlyingCallsCount = newValue
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
getUserIdentityUserIdUnderlyingCallsCount = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
open var getUserIdentityUserIdCalled: Bool {
|
||||||
|
return getUserIdentityUserIdCallsCount > 0
|
||||||
|
}
|
||||||
|
open var getUserIdentityUserIdReceivedUserId: String?
|
||||||
|
open var getUserIdentityUserIdReceivedInvocations: [String] = []
|
||||||
|
|
||||||
|
var getUserIdentityUserIdUnderlyingReturnValue: UserIdentity?
|
||||||
|
open var getUserIdentityUserIdReturnValue: UserIdentity? {
|
||||||
|
get {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
return getUserIdentityUserIdUnderlyingReturnValue
|
||||||
|
} else {
|
||||||
|
var returnValue: UserIdentity?? = nil
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
returnValue = getUserIdentityUserIdUnderlyingReturnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
getUserIdentityUserIdUnderlyingReturnValue = newValue
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
getUserIdentityUserIdUnderlyingReturnValue = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
open var getUserIdentityUserIdClosure: ((String) async throws -> UserIdentity?)?
|
||||||
|
|
||||||
|
open override func getUserIdentity(userId: String) async throws -> UserIdentity? {
|
||||||
|
if let error = getUserIdentityUserIdThrowableError {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
getUserIdentityUserIdCallsCount += 1
|
||||||
|
getUserIdentityUserIdReceivedUserId = userId
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.getUserIdentityUserIdReceivedInvocations.append(userId)
|
||||||
|
}
|
||||||
|
if let getUserIdentityUserIdClosure = getUserIdentityUserIdClosure {
|
||||||
|
return try await getUserIdentityUserIdClosure(userId)
|
||||||
|
} else {
|
||||||
|
return getUserIdentityUserIdReturnValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//MARK: - isLastDevice
|
//MARK: - isLastDevice
|
||||||
|
|
||||||
open var isLastDeviceThrowableError: Error?
|
open var isLastDeviceThrowableError: Error?
|
||||||
@@ -20854,6 +20929,122 @@ open class UnreadNotificationsCountSDKMock: MatrixRustSDK.UnreadNotificationsCou
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
open class UserIdentitySDKMock: MatrixRustSDK.UserIdentity {
|
||||||
|
init() {
|
||||||
|
super.init(noPointer: .init())
|
||||||
|
}
|
||||||
|
|
||||||
|
public required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) {
|
||||||
|
fatalError("init(unsafeFromRawPointer:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate var pointer: UnsafeMutableRawPointer!
|
||||||
|
|
||||||
|
//MARK: - masterKey
|
||||||
|
|
||||||
|
var masterKeyUnderlyingCallsCount = 0
|
||||||
|
open var masterKeyCallsCount: Int {
|
||||||
|
get {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
return masterKeyUnderlyingCallsCount
|
||||||
|
} else {
|
||||||
|
var returnValue: Int? = nil
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
returnValue = masterKeyUnderlyingCallsCount
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
masterKeyUnderlyingCallsCount = newValue
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
masterKeyUnderlyingCallsCount = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
open var masterKeyCalled: Bool {
|
||||||
|
return masterKeyCallsCount > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var masterKeyUnderlyingReturnValue: String?
|
||||||
|
open var masterKeyReturnValue: String? {
|
||||||
|
get {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
return masterKeyUnderlyingReturnValue
|
||||||
|
} else {
|
||||||
|
var returnValue: String?? = nil
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
returnValue = masterKeyUnderlyingReturnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
masterKeyUnderlyingReturnValue = newValue
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
masterKeyUnderlyingReturnValue = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
open var masterKeyClosure: (() -> String?)?
|
||||||
|
|
||||||
|
open override func masterKey() -> String? {
|
||||||
|
masterKeyCallsCount += 1
|
||||||
|
if let masterKeyClosure = masterKeyClosure {
|
||||||
|
return masterKeyClosure()
|
||||||
|
} else {
|
||||||
|
return masterKeyReturnValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: - pin
|
||||||
|
|
||||||
|
open var pinThrowableError: Error?
|
||||||
|
var pinUnderlyingCallsCount = 0
|
||||||
|
open var pinCallsCount: Int {
|
||||||
|
get {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
return pinUnderlyingCallsCount
|
||||||
|
} else {
|
||||||
|
var returnValue: Int? = nil
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
returnValue = pinUnderlyingCallsCount
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
pinUnderlyingCallsCount = newValue
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
pinUnderlyingCallsCount = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
open var pinCalled: Bool {
|
||||||
|
return pinCallsCount > 0
|
||||||
|
}
|
||||||
|
open var pinClosure: (() async throws -> Void)?
|
||||||
|
|
||||||
|
open override func pin() async throws {
|
||||||
|
if let error = pinThrowableError {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
pinCallsCount += 1
|
||||||
|
try await pinClosure?()
|
||||||
|
}
|
||||||
|
}
|
||||||
open class WidgetDriverSDKMock: MatrixRustSDK.WidgetDriver {
|
open class WidgetDriverSDKMock: MatrixRustSDK.WidgetDriver {
|
||||||
init() {
|
init() {
|
||||||
super.init(noPointer: .init())
|
super.init(noPointer: .init())
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ extension MediaProviderMock {
|
|||||||
return .success(data)
|
return .success(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
loadFileFromSourceBodyReturnValue = .failure(.failedRetrievingFile)
|
loadFileFromSourceFilenameReturnValue = .failure(.failedRetrievingFile)
|
||||||
|
|
||||||
loadImageRetryingOnReconnectionSizeClosure = { _, _ in
|
loadImageRetryingOnReconnectionSizeClosure = { _, _ in
|
||||||
Task {
|
Task {
|
||||||
|
|||||||
@@ -386,7 +386,7 @@ struct LoadableImage_Previews: PreviewProvider, TestablePreview {
|
|||||||
|
|
||||||
if isLoading {
|
if isLoading {
|
||||||
mediaProvider.imageFromSourceSizeClosure = { _, _ in nil }
|
mediaProvider.imageFromSourceSizeClosure = { _, _ in nil }
|
||||||
mediaProvider.loadFileFromSourceBodyClosure = { _, _ in .failure(.failedRetrievingFile) }
|
mediaProvider.loadFileFromSourceFilenameClosure = { _, _ in .failure(.failedRetrievingFile) }
|
||||||
mediaProvider.loadImageDataFromSourceClosure = { _ in .failure(.failedRetrievingImage) }
|
mediaProvider.loadImageDataFromSourceClosure = { _ in .failure(.failedRetrievingImage) }
|
||||||
mediaProvider.loadImageFromSourceSizeClosure = { _, _ in .failure(.failedRetrievingImage) }
|
mediaProvider.loadImageFromSourceSizeClosure = { _, _ in .failure(.failedRetrievingImage) }
|
||||||
mediaProvider.loadThumbnailForSourceSourceSizeClosure = { _, _ in .failure(.failedRetrievingThumbnail) }
|
mediaProvider.loadThumbnailForSourceSourceSizeClosure = { _, _ in .failure(.failedRetrievingThumbnail) }
|
||||||
|
|||||||
@@ -206,16 +206,26 @@ struct MessageComposer_Previews: PreviewProvider, TestablePreview {
|
|||||||
static let replyTypes: [TimelineItemReplyDetails] = [
|
static let replyTypes: [TimelineItemReplyDetails] = [
|
||||||
.loaded(sender: .init(id: "Dave"),
|
.loaded(sender: .init(id: "Dave"),
|
||||||
eventID: "123",
|
eventID: "123",
|
||||||
eventContent: .message(.audio(.init(body: "Audio: Ride the lightning", duration: 100, waveform: nil, source: nil, contentType: nil)))),
|
eventContent: .message(.audio(.init(filename: "lightning.mp3",
|
||||||
|
caption: "Audio: Ride the lightning",
|
||||||
|
duration: 100,
|
||||||
|
waveform: nil,
|
||||||
|
source: nil,
|
||||||
|
contentType: nil)))),
|
||||||
.loaded(sender: .init(id: "James"),
|
.loaded(sender: .init(id: "James"),
|
||||||
eventID: "123",
|
eventID: "123",
|
||||||
eventContent: .message(.emote(.init(body: "Emote: James thinks he's the phantom lord")))),
|
eventContent: .message(.emote(.init(body: "Emote: James thinks he's the phantom lord")))),
|
||||||
.loaded(sender: .init(id: "Robert"),
|
.loaded(sender: .init(id: "Robert"),
|
||||||
eventID: "123",
|
eventID: "123",
|
||||||
eventContent: .message(.file(.init(body: "File: Crash course in brain surgery.pdf", source: nil, thumbnailSource: nil, contentType: nil)))),
|
eventContent: .message(.file(.init(filename: "brain-surgery.pdf",
|
||||||
|
caption: "File: Crash course in brain surgery",
|
||||||
|
source: nil,
|
||||||
|
thumbnailSource: nil,
|
||||||
|
contentType: nil)))),
|
||||||
.loaded(sender: .init(id: "Cliff"),
|
.loaded(sender: .init(id: "Cliff"),
|
||||||
eventID: "123",
|
eventID: "123",
|
||||||
eventContent: .message(.image(.init(body: "Image: Pushead",
|
eventContent: .message(.image(.init(filename: "head.png",
|
||||||
|
caption: "Image: Pushead",
|
||||||
source: .init(url: .picturesDirectory, mimeType: nil),
|
source: .init(url: .picturesDirectory, mimeType: nil),
|
||||||
thumbnailSource: .init(url: .picturesDirectory, mimeType: nil))))),
|
thumbnailSource: .init(url: .picturesDirectory, mimeType: nil))))),
|
||||||
.loaded(sender: .init(id: "Jason"),
|
.loaded(sender: .init(id: "Jason"),
|
||||||
@@ -226,7 +236,8 @@ struct MessageComposer_Previews: PreviewProvider, TestablePreview {
|
|||||||
eventContent: .message(.text(.init(body: "Text: Where the wild things are")))),
|
eventContent: .message(.text(.init(body: "Text: Where the wild things are")))),
|
||||||
.loaded(sender: .init(id: "Lars"),
|
.loaded(sender: .init(id: "Lars"),
|
||||||
eventID: "123",
|
eventID: "123",
|
||||||
eventContent: .message(.video(.init(body: "Video: Through the never",
|
eventContent: .message(.video(.init(filename: "never.mov",
|
||||||
|
caption: "Video: Through the never",
|
||||||
duration: 100,
|
duration: 100,
|
||||||
source: nil,
|
source: nil,
|
||||||
thumbnailSource: .init(url: .picturesDirectory, mimeType: nil))))),
|
thumbnailSource: .init(url: .picturesDirectory, mimeType: nil))))),
|
||||||
|
|||||||
@@ -532,30 +532,35 @@ class TimelineInteractionHandler {
|
|||||||
|
|
||||||
private func displayMediaActionIfPossible(timelineItem: RoomTimelineItemProtocol) async -> RoomTimelineControllerAction {
|
private func displayMediaActionIfPossible(timelineItem: RoomTimelineItemProtocol) async -> RoomTimelineControllerAction {
|
||||||
var source: MediaSourceProxy?
|
var source: MediaSourceProxy?
|
||||||
var body: String
|
var filename: String
|
||||||
|
var caption: String?
|
||||||
|
|
||||||
switch timelineItem {
|
switch timelineItem {
|
||||||
case let item as ImageRoomTimelineItem:
|
case let item as ImageRoomTimelineItem:
|
||||||
source = item.content.source
|
source = item.content.source
|
||||||
body = item.content.body
|
filename = item.content.filename
|
||||||
|
caption = item.content.caption
|
||||||
case let item as VideoRoomTimelineItem:
|
case let item as VideoRoomTimelineItem:
|
||||||
source = item.content.source
|
source = item.content.source
|
||||||
body = item.content.body
|
filename = item.content.filename
|
||||||
|
caption = item.content.caption
|
||||||
case let item as FileRoomTimelineItem:
|
case let item as FileRoomTimelineItem:
|
||||||
source = item.content.source
|
source = item.content.source
|
||||||
body = item.content.body
|
filename = item.content.filename
|
||||||
|
caption = item.content.caption
|
||||||
case let item as AudioRoomTimelineItem:
|
case let item as AudioRoomTimelineItem:
|
||||||
// For now we are just displaying audio messages with the File preview until we create a timeline player for them.
|
// For now we are just displaying audio messages with the File preview until we create a timeline player for them.
|
||||||
source = item.content.source
|
source = item.content.source
|
||||||
body = item.content.body
|
filename = item.content.filename
|
||||||
|
caption = item.content.caption
|
||||||
default:
|
default:
|
||||||
return .none
|
return .none
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let source else { return .none }
|
guard let source else { return .none }
|
||||||
switch await mediaProvider.loadFileFromSource(source, body: body) {
|
switch await mediaProvider.loadFileFromSource(source, filename: filename) {
|
||||||
case .success(let file):
|
case .success(let file):
|
||||||
return .displayMediaFile(file: file, title: body)
|
return .displayMediaFile(file: file, title: caption ?? filename)
|
||||||
case .failure:
|
case .failure:
|
||||||
return .none
|
return .none
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ struct TimelineReplyView: View {
|
|||||||
switch content {
|
switch content {
|
||||||
case .audio(let content):
|
case .audio(let content):
|
||||||
ReplyView(sender: sender,
|
ReplyView(sender: sender,
|
||||||
plainBody: content.body,
|
plainBody: content.caption ?? content.filename,
|
||||||
formattedBody: nil,
|
formattedBody: content.formattedCaption,
|
||||||
icon: .init(kind: .systemIcon("waveform"), cornerRadii: iconCornerRadii))
|
icon: .init(kind: .systemIcon("waveform"), cornerRadii: iconCornerRadii))
|
||||||
case .emote(let content):
|
case .emote(let content):
|
||||||
ReplyView(sender: sender,
|
ReplyView(sender: sender,
|
||||||
@@ -35,13 +35,13 @@ struct TimelineReplyView: View {
|
|||||||
formattedBody: content.formattedBody)
|
formattedBody: content.formattedBody)
|
||||||
case .file(let content):
|
case .file(let content):
|
||||||
ReplyView(sender: sender,
|
ReplyView(sender: sender,
|
||||||
plainBody: content.body,
|
plainBody: content.caption ?? content.filename,
|
||||||
formattedBody: nil,
|
formattedBody: content.formattedCaption,
|
||||||
icon: .init(kind: .icon(\.document), cornerRadii: iconCornerRadii))
|
icon: .init(kind: .icon(\.document), cornerRadii: iconCornerRadii))
|
||||||
case .image(let content):
|
case .image(let content):
|
||||||
ReplyView(sender: sender,
|
ReplyView(sender: sender,
|
||||||
plainBody: content.body,
|
plainBody: content.caption ?? content.filename,
|
||||||
formattedBody: nil,
|
formattedBody: content.formattedCaption,
|
||||||
icon: .init(kind: .mediaSource(content.thumbnailSource ?? content.source), cornerRadii: iconCornerRadii))
|
icon: .init(kind: .mediaSource(content.thumbnailSource ?? content.source), cornerRadii: iconCornerRadii))
|
||||||
case .notice(let content):
|
case .notice(let content):
|
||||||
ReplyView(sender: sender,
|
ReplyView(sender: sender,
|
||||||
@@ -53,8 +53,8 @@ struct TimelineReplyView: View {
|
|||||||
formattedBody: content.formattedBody)
|
formattedBody: content.formattedBody)
|
||||||
case .video(let content):
|
case .video(let content):
|
||||||
ReplyView(sender: sender,
|
ReplyView(sender: sender,
|
||||||
plainBody: content.body,
|
plainBody: content.caption ?? content.filename,
|
||||||
formattedBody: nil,
|
formattedBody: content.formattedCaption,
|
||||||
icon: content.thumbnailSource.map { .init(kind: .mediaSource($0), cornerRadii: iconCornerRadii) })
|
icon: content.thumbnailSource.map { .init(kind: .mediaSource($0), cornerRadii: iconCornerRadii) })
|
||||||
case .voice:
|
case .voice:
|
||||||
ReplyView(sender: sender,
|
ReplyView(sender: sender,
|
||||||
@@ -247,7 +247,8 @@ struct TimelineReplyView_Previews: PreviewProvider, TestablePreview {
|
|||||||
TimelineReplyView(placement: .timeline,
|
TimelineReplyView(placement: .timeline,
|
||||||
timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
||||||
eventID: "123",
|
eventID: "123",
|
||||||
eventContent: .message(.audio(.init(body: "Some audio",
|
eventContent: .message(.audio(.init(filename: "audio.m4a",
|
||||||
|
caption: "Some audio",
|
||||||
duration: 0,
|
duration: 0,
|
||||||
waveform: nil,
|
waveform: nil,
|
||||||
source: nil,
|
source: nil,
|
||||||
@@ -256,7 +257,8 @@ struct TimelineReplyView_Previews: PreviewProvider, TestablePreview {
|
|||||||
TimelineReplyView(placement: .timeline,
|
TimelineReplyView(placement: .timeline,
|
||||||
timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
||||||
eventID: "123",
|
eventID: "123",
|
||||||
eventContent: .message(.file(.init(body: "Some file",
|
eventContent: .message(.file(.init(filename: "file.txt",
|
||||||
|
caption: "Some file",
|
||||||
source: nil,
|
source: nil,
|
||||||
thumbnailSource: nil,
|
thumbnailSource: nil,
|
||||||
contentType: nil))))),
|
contentType: nil))))),
|
||||||
@@ -264,14 +266,16 @@ struct TimelineReplyView_Previews: PreviewProvider, TestablePreview {
|
|||||||
TimelineReplyView(placement: .timeline,
|
TimelineReplyView(placement: .timeline,
|
||||||
timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
||||||
eventID: "123",
|
eventID: "123",
|
||||||
eventContent: .message(.image(.init(body: "Some image",
|
eventContent: .message(.image(.init(filename: "image.jpg",
|
||||||
|
caption: "Some image",
|
||||||
source: imageSource,
|
source: imageSource,
|
||||||
thumbnailSource: imageSource))))),
|
thumbnailSource: imageSource))))),
|
||||||
|
|
||||||
TimelineReplyView(placement: .timeline,
|
TimelineReplyView(placement: .timeline,
|
||||||
timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
||||||
eventID: "123",
|
eventID: "123",
|
||||||
eventContent: .message(.video(.init(body: "Some video",
|
eventContent: .message(.video(.init(filename: "video.mp4",
|
||||||
|
caption: "Some video",
|
||||||
duration: 0,
|
duration: 0,
|
||||||
source: nil,
|
source: nil,
|
||||||
thumbnailSource: imageSource))))),
|
thumbnailSource: imageSource))))),
|
||||||
@@ -283,7 +287,8 @@ struct TimelineReplyView_Previews: PreviewProvider, TestablePreview {
|
|||||||
TimelineReplyView(placement: .timeline,
|
TimelineReplyView(placement: .timeline,
|
||||||
timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
||||||
eventID: "123",
|
eventID: "123",
|
||||||
eventContent: .message(.voice(.init(body: "Some voice message",
|
eventContent: .message(.voice(.init(filename: "voice-message.ogg",
|
||||||
|
caption: "Some voice message",
|
||||||
duration: 0,
|
duration: 0,
|
||||||
waveform: nil,
|
waveform: nil,
|
||||||
source: nil,
|
source: nil,
|
||||||
|
|||||||
+124
-197
@@ -355,7 +355,7 @@ private extension View {
|
|||||||
struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview {
|
struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview {
|
||||||
static let viewModel = TimelineViewModel.mock
|
static let viewModel = TimelineViewModel.mock
|
||||||
static let viewModelWithPins: TimelineViewModel = {
|
static let viewModelWithPins: TimelineViewModel = {
|
||||||
let roomProxy = JoinedRoomProxyMock(.init(name: "Preview Room", pinnedEventIDs: [""]))
|
let roomProxy = JoinedRoomProxyMock(.init(name: "Preview Room", pinnedEventIDs: ["pinned"]))
|
||||||
return TimelineViewModel(roomProxy: roomProxy,
|
return TimelineViewModel(roomProxy: roomProxy,
|
||||||
focussedEventID: nil,
|
focussedEventID: nil,
|
||||||
timelineController: MockRoomTimelineController(),
|
timelineController: MockRoomTimelineController(),
|
||||||
@@ -385,113 +385,6 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
|
|||||||
.snapshotPreferences(delay: 2.0)
|
.snapshotPreferences(delay: 2.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// These always include a reply
|
|
||||||
static var threads: some View {
|
|
||||||
ScrollView {
|
|
||||||
RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(uniqueID: ""),
|
|
||||||
timestamp: "10:42",
|
|
||||||
isOutgoing: true,
|
|
||||||
isEditable: false,
|
|
||||||
canBeRepliedTo: true,
|
|
||||||
isThreaded: true,
|
|
||||||
sender: .init(id: "whoever"),
|
|
||||||
content: .init(body: "A long message that should be on multiple lines."),
|
|
||||||
replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
|
||||||
eventID: "123",
|
|
||||||
eventContent: .message(.text(.init(body: "Short"))))),
|
|
||||||
groupStyle: .single))
|
|
||||||
|
|
||||||
AudioRoomTimelineView(timelineItem: .init(id: .init(uniqueID: ""),
|
|
||||||
timestamp: "10:42",
|
|
||||||
isOutgoing: true,
|
|
||||||
isEditable: false,
|
|
||||||
canBeRepliedTo: true,
|
|
||||||
isThreaded: true,
|
|
||||||
sender: .init(id: ""),
|
|
||||||
content: .init(body: "audio.ogg",
|
|
||||||
duration: 100,
|
|
||||||
waveform: EstimatedWaveform.mockWaveform,
|
|
||||||
source: nil,
|
|
||||||
contentType: nil),
|
|
||||||
replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
|
||||||
eventID: "123",
|
|
||||||
eventContent: .message(.text(.init(body: "Short"))))))
|
|
||||||
|
|
||||||
FileRoomTimelineView(timelineItem: .init(id: .init(uniqueID: ""),
|
|
||||||
timestamp: "10:42",
|
|
||||||
isOutgoing: false,
|
|
||||||
isEditable: false,
|
|
||||||
canBeRepliedTo: true,
|
|
||||||
isThreaded: true,
|
|
||||||
sender: .init(id: ""),
|
|
||||||
content: .init(body: "File",
|
|
||||||
source: nil,
|
|
||||||
thumbnailSource: nil,
|
|
||||||
contentType: nil),
|
|
||||||
replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
|
||||||
eventID: "123",
|
|
||||||
eventContent: .message(.text(.init(body: "Short"))))))
|
|
||||||
ImageRoomTimelineView(timelineItem: .init(id: .init(uniqueID: ""),
|
|
||||||
timestamp: "10:42",
|
|
||||||
isOutgoing: true,
|
|
||||||
isEditable: true,
|
|
||||||
canBeRepliedTo: true,
|
|
||||||
isThreaded: true,
|
|
||||||
sender: .init(id: ""),
|
|
||||||
content: .init(body: "Some image", source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"), thumbnailSource: nil),
|
|
||||||
replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
|
||||||
eventID: "123",
|
|
||||||
eventContent: .message(.text(.init(body: "Short"))))))
|
|
||||||
LocationRoomTimelineView(timelineItem: .init(id: .random,
|
|
||||||
timestamp: "Now",
|
|
||||||
isOutgoing: false,
|
|
||||||
isEditable: false,
|
|
||||||
canBeRepliedTo: true,
|
|
||||||
isThreaded: true,
|
|
||||||
sender: .init(id: "Bob"),
|
|
||||||
content: .init(body: "Fallback geo uri description",
|
|
||||||
geoURI: .init(latitude: 41.902782,
|
|
||||||
longitude: 12.496366),
|
|
||||||
description: "Location description description description description description description description description"),
|
|
||||||
replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
|
||||||
eventID: "123",
|
|
||||||
eventContent: .message(.text(.init(body: "Short"))))))
|
|
||||||
LocationRoomTimelineView(timelineItem: .init(id: .random,
|
|
||||||
timestamp: "Now",
|
|
||||||
isOutgoing: false,
|
|
||||||
isEditable: false,
|
|
||||||
canBeRepliedTo: true,
|
|
||||||
isThreaded: true,
|
|
||||||
sender: .init(id: "Bob"),
|
|
||||||
content: .init(body: "Fallback geo uri description",
|
|
||||||
geoURI: .init(latitude: 41.902782, longitude: 12.496366), description: nil),
|
|
||||||
replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
|
||||||
eventID: "123",
|
|
||||||
eventContent: .message(.text(.init(body: "Short"))))))
|
|
||||||
|
|
||||||
VoiceMessageRoomTimelineView(timelineItem: .init(id: .init(uniqueID: ""),
|
|
||||||
timestamp: "10:42",
|
|
||||||
isOutgoing: true,
|
|
||||||
isEditable: false,
|
|
||||||
canBeRepliedTo: true,
|
|
||||||
isThreaded: true,
|
|
||||||
sender: .init(id: ""),
|
|
||||||
content: .init(body: "audio.ogg",
|
|
||||||
duration: 100,
|
|
||||||
waveform: EstimatedWaveform.mockWaveform,
|
|
||||||
source: nil,
|
|
||||||
contentType: nil),
|
|
||||||
replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
|
||||||
eventID: "123",
|
|
||||||
eventContent: .message(.text(.init(body: "Short"))))),
|
|
||||||
playerState: AudioPlayerState(id: .timelineItemIdentifier(.random),
|
|
||||||
title: L10n.commonVoiceMessage,
|
|
||||||
duration: 10,
|
|
||||||
waveform: EstimatedWaveform.mockWaveform))
|
|
||||||
}
|
|
||||||
.environmentObject(viewModel.context)
|
|
||||||
}
|
|
||||||
|
|
||||||
static var mockTimeline: some View {
|
static var mockTimeline: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
@@ -502,7 +395,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
|
|||||||
}
|
}
|
||||||
.environmentObject(viewModel.context)
|
.environmentObject(viewModel.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
static var replies: some View {
|
static var replies: some View {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(uniqueID: ""),
|
RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(uniqueID: ""),
|
||||||
@@ -533,7 +426,21 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
|
|||||||
}
|
}
|
||||||
.environmentObject(viewModel.context)
|
.environmentObject(viewModel.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static var threads: some View {
|
||||||
|
ScrollView {
|
||||||
|
MockTimelineContent(isThreaded: true)
|
||||||
|
}
|
||||||
|
.environmentObject(viewModel.context)
|
||||||
|
}
|
||||||
|
|
||||||
|
static var pinned: some View {
|
||||||
|
ScrollView {
|
||||||
|
MockTimelineContent(isPinned: true)
|
||||||
|
}
|
||||||
|
.environmentObject(viewModelWithPins.context)
|
||||||
|
}
|
||||||
|
|
||||||
static var encryptionAuthenticity: some View {
|
static var encryptionAuthenticity: some View {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(uniqueID: ""),
|
RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(uniqueID: ""),
|
||||||
@@ -588,7 +495,9 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
|
|||||||
canBeRepliedTo: true,
|
canBeRepliedTo: true,
|
||||||
isThreaded: false,
|
isThreaded: false,
|
||||||
sender: .init(id: "Bob"),
|
sender: .init(id: "Bob"),
|
||||||
content: .init(body: "Some other image", source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"), thumbnailSource: nil),
|
content: .init(filename: "other.png",
|
||||||
|
source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"),
|
||||||
|
thumbnailSource: nil),
|
||||||
|
|
||||||
properties: RoomTimelineItemProperties(encryptionAuthenticity: .notGuaranteed(color: .gray))))
|
properties: RoomTimelineItemProperties(encryptionAuthenticity: .notGuaranteed(color: .gray))))
|
||||||
|
|
||||||
@@ -599,7 +508,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
|
|||||||
canBeRepliedTo: true,
|
canBeRepliedTo: true,
|
||||||
isThreaded: true,
|
isThreaded: true,
|
||||||
sender: .init(id: ""),
|
sender: .init(id: ""),
|
||||||
content: .init(body: "audio.ogg",
|
content: .init(filename: "audio.ogg",
|
||||||
duration: 100,
|
duration: 100,
|
||||||
waveform: EstimatedWaveform.mockWaveform,
|
waveform: EstimatedWaveform.mockWaveform,
|
||||||
source: nil,
|
source: nil,
|
||||||
@@ -612,96 +521,114 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
|
|||||||
}
|
}
|
||||||
.environmentObject(viewModel.context)
|
.environmentObject(viewModel.context)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
static var pinned: some View {
|
|
||||||
ScrollView {
|
|
||||||
RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(uniqueID: "", eventOrTransactionID: .eventId(eventId: "")),
|
|
||||||
timestamp: "10:42",
|
|
||||||
isOutgoing: true,
|
|
||||||
isEditable: false,
|
|
||||||
canBeRepliedTo: true,
|
|
||||||
isThreaded: false,
|
|
||||||
sender: .init(id: "whoever"),
|
|
||||||
content: .init(body: "A long message that should be on multiple lines."),
|
|
||||||
replyDetails: nil),
|
|
||||||
groupStyle: .single))
|
|
||||||
|
|
||||||
AudioRoomTimelineView(timelineItem: .init(id: .init(uniqueID: "", eventOrTransactionID: .eventId(eventId: "")),
|
private struct MockTimelineContent: View {
|
||||||
timestamp: "10:42",
|
var isThreaded = false
|
||||||
isOutgoing: true,
|
var isPinned = false
|
||||||
isEditable: false,
|
|
||||||
canBeRepliedTo: true,
|
var body: some View {
|
||||||
isThreaded: false,
|
RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: makeItemIdentifier(),
|
||||||
sender: .init(id: ""),
|
timestamp: "10:42",
|
||||||
content: .init(body: "audio.ogg",
|
isOutgoing: true,
|
||||||
duration: 100,
|
isEditable: false,
|
||||||
waveform: EstimatedWaveform.mockWaveform,
|
canBeRepliedTo: true,
|
||||||
source: nil,
|
isThreaded: isThreaded,
|
||||||
contentType: nil),
|
sender: .init(id: "whoever"),
|
||||||
replyDetails: nil))
|
content: .init(body: "A long message that should be on multiple lines."),
|
||||||
|
replyDetails: replyDetails),
|
||||||
FileRoomTimelineView(timelineItem: .init(id: .init(uniqueID: "", eventOrTransactionID: .eventId(eventId: "")),
|
groupStyle: .single))
|
||||||
timestamp: "10:42",
|
|
||||||
|
AudioRoomTimelineView(timelineItem: .init(id: makeItemIdentifier(),
|
||||||
|
timestamp: "10:42",
|
||||||
|
isOutgoing: true,
|
||||||
|
isEditable: false,
|
||||||
|
canBeRepliedTo: true,
|
||||||
|
isThreaded: isThreaded,
|
||||||
|
sender: .init(id: ""),
|
||||||
|
content: .init(filename: "audio.ogg",
|
||||||
|
duration: 100,
|
||||||
|
waveform: EstimatedWaveform.mockWaveform,
|
||||||
|
source: nil,
|
||||||
|
contentType: nil),
|
||||||
|
replyDetails: replyDetails))
|
||||||
|
|
||||||
|
FileRoomTimelineView(timelineItem: .init(id: makeItemIdentifier(),
|
||||||
|
timestamp: "10:42",
|
||||||
|
isOutgoing: false,
|
||||||
|
isEditable: false,
|
||||||
|
canBeRepliedTo: true,
|
||||||
|
isThreaded: isThreaded,
|
||||||
|
sender: .init(id: ""),
|
||||||
|
content: .init(filename: "file.txt",
|
||||||
|
caption: "File",
|
||||||
|
source: nil,
|
||||||
|
thumbnailSource: nil,
|
||||||
|
contentType: nil),
|
||||||
|
replyDetails: replyDetails))
|
||||||
|
|
||||||
|
ImageRoomTimelineView(timelineItem: .init(id: makeItemIdentifier(),
|
||||||
|
timestamp: "10:42",
|
||||||
|
isOutgoing: true,
|
||||||
|
isEditable: true,
|
||||||
|
canBeRepliedTo: true,
|
||||||
|
isThreaded: isThreaded,
|
||||||
|
sender: .init(id: ""),
|
||||||
|
content: .init(filename: "image.jpg",
|
||||||
|
source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"),
|
||||||
|
thumbnailSource: nil),
|
||||||
|
replyDetails: replyDetails))
|
||||||
|
|
||||||
|
LocationRoomTimelineView(timelineItem: .init(id: makeItemIdentifier(),
|
||||||
|
timestamp: "Now",
|
||||||
isOutgoing: false,
|
isOutgoing: false,
|
||||||
isEditable: false,
|
isEditable: false,
|
||||||
canBeRepliedTo: true,
|
canBeRepliedTo: true,
|
||||||
isThreaded: false,
|
isThreaded: isThreaded,
|
||||||
sender: .init(id: ""),
|
sender: .init(id: "Bob"),
|
||||||
content: .init(body: "File",
|
content: .init(body: "Fallback geo uri description",
|
||||||
source: nil,
|
geoURI: .init(latitude: 41.902782,
|
||||||
thumbnailSource: nil,
|
longitude: 12.496366),
|
||||||
contentType: nil),
|
description: "Location description description description description description description description description"),
|
||||||
replyDetails: nil))
|
replyDetails: replyDetails))
|
||||||
ImageRoomTimelineView(timelineItem: .init(id: .init(uniqueID: "", eventOrTransactionID: .eventId(eventId: "")),
|
|
||||||
timestamp: "10:42",
|
LocationRoomTimelineView(timelineItem: .init(id: makeItemIdentifier(),
|
||||||
isOutgoing: true,
|
timestamp: "Now",
|
||||||
isEditable: true,
|
isOutgoing: false,
|
||||||
canBeRepliedTo: true,
|
isEditable: false,
|
||||||
isThreaded: false,
|
canBeRepliedTo: true,
|
||||||
sender: .init(id: ""),
|
isThreaded: isThreaded,
|
||||||
content: .init(body: "Some image", source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"), thumbnailSource: nil),
|
sender: .init(id: "Bob"),
|
||||||
replyDetails: nil))
|
content: .init(body: "Fallback geo uri description",
|
||||||
LocationRoomTimelineView(timelineItem: .init(id: .init(uniqueID: "", eventOrTransactionID: .eventId(eventId: "")),
|
geoURI: .init(latitude: 41.902782, longitude: 12.496366), description: nil),
|
||||||
timestamp: "Now",
|
replyDetails: replyDetails))
|
||||||
isOutgoing: false,
|
|
||||||
|
VoiceMessageRoomTimelineView(timelineItem: .init(id: makeItemIdentifier(),
|
||||||
|
timestamp: "10:42",
|
||||||
|
isOutgoing: true,
|
||||||
isEditable: false,
|
isEditable: false,
|
||||||
canBeRepliedTo: true,
|
canBeRepliedTo: true,
|
||||||
isThreaded: false,
|
isThreaded: isThreaded,
|
||||||
sender: .init(id: "Bob"),
|
sender: .init(id: ""),
|
||||||
content: .init(body: "Fallback geo uri description",
|
content: .init(filename: "audio.ogg",
|
||||||
geoURI: .init(latitude: 41.902782,
|
duration: 100,
|
||||||
longitude: 12.496366),
|
waveform: EstimatedWaveform.mockWaveform,
|
||||||
description: "Location description description description description description description description description"),
|
source: nil,
|
||||||
replyDetails: nil))
|
contentType: nil),
|
||||||
LocationRoomTimelineView(timelineItem: .init(id: .init(uniqueID: "", eventOrTransactionID: .eventId(eventId: "")),
|
replyDetails: replyDetails),
|
||||||
timestamp: "Now",
|
playerState: AudioPlayerState(id: .timelineItemIdentifier(.random),
|
||||||
isOutgoing: false,
|
title: L10n.commonVoiceMessage,
|
||||||
isEditable: false,
|
duration: 10,
|
||||||
canBeRepliedTo: true,
|
waveform: EstimatedWaveform.mockWaveform))
|
||||||
isThreaded: false,
|
}
|
||||||
sender: .init(id: "Bob"),
|
|
||||||
content: .init(body: "Fallback geo uri description",
|
func makeItemIdentifier() -> TimelineItemIdentifier {
|
||||||
geoURI: .init(latitude: 41.902782, longitude: 12.496366), description: nil),
|
isPinned ? .init(uniqueID: "", eventOrTransactionID: .eventId(eventId: "pinned")) : .random
|
||||||
replyDetails: nil))
|
}
|
||||||
|
|
||||||
VoiceMessageRoomTimelineView(timelineItem: .init(id: .init(uniqueID: "", eventOrTransactionID: .eventId(eventId: "")),
|
var replyDetails: TimelineItemReplyDetails? {
|
||||||
timestamp: "10:42",
|
isThreaded ? .loaded(sender: .init(id: "", displayName: "Alice"),
|
||||||
isOutgoing: true,
|
eventID: "123",
|
||||||
isEditable: false,
|
eventContent: .message(.text(.init(body: "Short")))) : nil
|
||||||
canBeRepliedTo: true,
|
|
||||||
isThreaded: false,
|
|
||||||
sender: .init(id: ""),
|
|
||||||
content: .init(body: "audio.ogg",
|
|
||||||
duration: 100,
|
|
||||||
waveform: EstimatedWaveform.mockWaveform,
|
|
||||||
source: nil,
|
|
||||||
contentType: nil),
|
|
||||||
replyDetails: nil),
|
|
||||||
playerState: AudioPlayerState(id: .timelineItemIdentifier(.random),
|
|
||||||
title: L10n.commonVoiceMessage,
|
|
||||||
duration: 10,
|
|
||||||
waveform: EstimatedWaveform.mockWaveform))
|
|
||||||
}
|
|
||||||
.environmentObject(viewModelWithPins.context)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -41,6 +41,10 @@ struct AudioRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
|||||||
canBeRepliedTo: true,
|
canBeRepliedTo: true,
|
||||||
isThreaded: false,
|
isThreaded: false,
|
||||||
sender: .init(id: "Bob"),
|
sender: .init(id: "Bob"),
|
||||||
content: .init(body: "audio.ogg", duration: 300, waveform: nil, source: nil, contentType: nil)))
|
content: .init(filename: "audio.ogg",
|
||||||
|
duration: 300,
|
||||||
|
waveform: nil,
|
||||||
|
source: nil,
|
||||||
|
contentType: nil)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-3
@@ -42,7 +42,10 @@ struct FileRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
|||||||
canBeRepliedTo: true,
|
canBeRepliedTo: true,
|
||||||
isThreaded: false,
|
isThreaded: false,
|
||||||
sender: .init(id: "Bob"),
|
sender: .init(id: "Bob"),
|
||||||
content: .init(body: "document.pdf", source: nil, thumbnailSource: nil, contentType: nil)))
|
content: .init(filename: "document.pdf",
|
||||||
|
source: nil,
|
||||||
|
thumbnailSource: nil,
|
||||||
|
contentType: nil)))
|
||||||
|
|
||||||
FileRoomTimelineView(timelineItem: FileRoomTimelineItem(id: .random,
|
FileRoomTimelineView(timelineItem: FileRoomTimelineItem(id: .random,
|
||||||
timestamp: "Now",
|
timestamp: "Now",
|
||||||
@@ -51,7 +54,10 @@ struct FileRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
|||||||
canBeRepliedTo: true,
|
canBeRepliedTo: true,
|
||||||
isThreaded: false,
|
isThreaded: false,
|
||||||
sender: .init(id: "Bob"),
|
sender: .init(id: "Bob"),
|
||||||
content: .init(body: "document.docx", source: nil, thumbnailSource: nil, contentType: nil)))
|
content: .init(filename: "document.docx",
|
||||||
|
source: nil,
|
||||||
|
thumbnailSource: nil,
|
||||||
|
contentType: nil)))
|
||||||
|
|
||||||
FileRoomTimelineView(timelineItem: FileRoomTimelineItem(id: .random,
|
FileRoomTimelineView(timelineItem: FileRoomTimelineItem(id: .random,
|
||||||
timestamp: "Now",
|
timestamp: "Now",
|
||||||
@@ -60,7 +66,10 @@ struct FileRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
|||||||
canBeRepliedTo: true,
|
canBeRepliedTo: true,
|
||||||
isThreaded: false,
|
isThreaded: false,
|
||||||
sender: .init(id: "Bob"),
|
sender: .init(id: "Bob"),
|
||||||
content: .init(body: "document.txt", source: nil, thumbnailSource: nil, contentType: nil)))
|
content: .init(filename: "document.txt",
|
||||||
|
source: nil,
|
||||||
|
thumbnailSource: nil,
|
||||||
|
contentType: nil)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-3
@@ -59,7 +59,9 @@ struct ImageRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
|||||||
canBeRepliedTo: true,
|
canBeRepliedTo: true,
|
||||||
isThreaded: false,
|
isThreaded: false,
|
||||||
sender: .init(id: "Bob"),
|
sender: .init(id: "Bob"),
|
||||||
content: .init(body: "Some image", source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"), thumbnailSource: nil)))
|
content: .init(filename: "image.jpg",
|
||||||
|
source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/jpg"),
|
||||||
|
thumbnailSource: nil)))
|
||||||
|
|
||||||
ImageRoomTimelineView(timelineItem: ImageRoomTimelineItem(id: .random,
|
ImageRoomTimelineView(timelineItem: ImageRoomTimelineItem(id: .random,
|
||||||
timestamp: "Now",
|
timestamp: "Now",
|
||||||
@@ -68,7 +70,9 @@ struct ImageRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
|||||||
canBeRepliedTo: true,
|
canBeRepliedTo: true,
|
||||||
isThreaded: false,
|
isThreaded: false,
|
||||||
sender: .init(id: "Bob"),
|
sender: .init(id: "Bob"),
|
||||||
content: .init(body: "Some other image", source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"), thumbnailSource: nil)))
|
content: .init(filename: "other.png",
|
||||||
|
source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"),
|
||||||
|
thumbnailSource: nil)))
|
||||||
|
|
||||||
ImageRoomTimelineView(timelineItem: ImageRoomTimelineItem(id: .random,
|
ImageRoomTimelineView(timelineItem: ImageRoomTimelineItem(id: .random,
|
||||||
timestamp: "Now",
|
timestamp: "Now",
|
||||||
@@ -77,7 +81,7 @@ struct ImageRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
|||||||
canBeRepliedTo: true,
|
canBeRepliedTo: true,
|
||||||
isThreaded: false,
|
isThreaded: false,
|
||||||
sender: .init(id: "Bob"),
|
sender: .init(id: "Bob"),
|
||||||
content: .init(body: "Blurhashed image",
|
content: .init(filename: "Blurhashed.jpg",
|
||||||
source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/gif"),
|
source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/gif"),
|
||||||
thumbnailSource: nil,
|
thumbnailSource: nil,
|
||||||
aspectRatio: 0.7,
|
aspectRatio: 0.7,
|
||||||
|
|||||||
+14
-3
@@ -70,7 +70,10 @@ struct VideoRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
|||||||
canBeRepliedTo: true,
|
canBeRepliedTo: true,
|
||||||
isThreaded: false,
|
isThreaded: false,
|
||||||
sender: .init(id: "Bob"),
|
sender: .init(id: "Bob"),
|
||||||
content: .init(body: "Some video", duration: 21, source: nil, thumbnailSource: nil)))
|
content: .init(filename: "video.mp4",
|
||||||
|
duration: 21,
|
||||||
|
source: nil,
|
||||||
|
thumbnailSource: nil)))
|
||||||
|
|
||||||
VideoRoomTimelineView(timelineItem: VideoRoomTimelineItem(id: .random,
|
VideoRoomTimelineView(timelineItem: VideoRoomTimelineItem(id: .random,
|
||||||
timestamp: "Now",
|
timestamp: "Now",
|
||||||
@@ -79,7 +82,10 @@ struct VideoRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
|||||||
canBeRepliedTo: true,
|
canBeRepliedTo: true,
|
||||||
isThreaded: false,
|
isThreaded: false,
|
||||||
sender: .init(id: "Bob"),
|
sender: .init(id: "Bob"),
|
||||||
content: .init(body: "Some other video", duration: 22, source: nil, thumbnailSource: nil)))
|
content: .init(filename: "other.mp4",
|
||||||
|
duration: 22,
|
||||||
|
source: nil,
|
||||||
|
thumbnailSource: nil)))
|
||||||
|
|
||||||
VideoRoomTimelineView(timelineItem: VideoRoomTimelineItem(id: .random,
|
VideoRoomTimelineView(timelineItem: VideoRoomTimelineItem(id: .random,
|
||||||
timestamp: "Now",
|
timestamp: "Now",
|
||||||
@@ -88,7 +94,12 @@ struct VideoRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
|||||||
canBeRepliedTo: true,
|
canBeRepliedTo: true,
|
||||||
isThreaded: false,
|
isThreaded: false,
|
||||||
sender: .init(id: "Bob"),
|
sender: .init(id: "Bob"),
|
||||||
content: .init(body: "Blurhashed video", duration: 23, source: nil, thumbnailSource: nil, aspectRatio: 0.7, blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW")))
|
content: .init(filename: "Blurhashed.mp4",
|
||||||
|
duration: 23,
|
||||||
|
source: nil,
|
||||||
|
thumbnailSource: nil,
|
||||||
|
aspectRatio: 0.7,
|
||||||
|
blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -929,8 +929,8 @@ extension ClientProxy: MediaLoaderProtocol {
|
|||||||
try await mediaLoader.loadMediaThumbnailForSource(source, width: width, height: height)
|
try await mediaLoader.loadMediaThumbnailForSource(source, width: width, height: height)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadMediaFileForSource(_ source: MediaSourceProxy, body: String?) async throws -> MediaFileHandleProxy {
|
func loadMediaFileForSource(_ source: MediaSourceProxy, filename: String?) async throws -> MediaFileHandleProxy {
|
||||||
try await mediaLoader.loadMediaFileForSource(source, body: body)
|
try await mediaLoader.loadMediaFileForSource(source, filename: filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ actor MediaLoader: MediaLoaderProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadMediaFileForSource(_ source: MediaSourceProxy, body: String?) async throws -> MediaFileHandleProxy {
|
func loadMediaFileForSource(_ source: MediaSourceProxy, filename: String?) async throws -> MediaFileHandleProxy {
|
||||||
let result = try await client.getMediaFile(mediaSource: source.underlyingSource, body: body, mimeType: source.mimeType ?? "application/octet-stream", useCache: true, tempDir: nil)
|
let result = try await client.getMediaFile(mediaSource: source.underlyingSource, body: filename, mimeType: source.mimeType ?? "application/octet-stream", useCache: true, tempDir: nil)
|
||||||
|
|
||||||
return MediaFileHandleProxy(handle: result)
|
return MediaFileHandleProxy(handle: result)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,5 +13,5 @@ protocol MediaLoaderProtocol {
|
|||||||
|
|
||||||
func loadMediaThumbnailForSource(_ source: MediaSourceProxy, width: UInt, height: UInt) async throws -> Data
|
func loadMediaThumbnailForSource(_ source: MediaSourceProxy, width: UInt, height: UInt) async throws -> Data
|
||||||
|
|
||||||
func loadMediaFileForSource(_ source: MediaSourceProxy, body: String?) async throws -> MediaFileHandleProxy
|
func loadMediaFileForSource(_ source: MediaSourceProxy, filename: String?) async throws -> MediaFileHandleProxy
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,9 +117,9 @@ struct MediaProvider: MediaProviderProtocol {
|
|||||||
|
|
||||||
// MARK: Files
|
// MARK: Files
|
||||||
|
|
||||||
func loadFileFromSource(_ source: MediaSourceProxy, body: String?) async -> Result<MediaFileHandleProxy, MediaProviderError> {
|
func loadFileFromSource(_ source: MediaSourceProxy, filename: String?) async -> Result<MediaFileHandleProxy, MediaProviderError> {
|
||||||
do {
|
do {
|
||||||
let file = try await mediaLoader.loadMediaFileForSource(source, body: body)
|
let file = try await mediaLoader.loadMediaFileForSource(source, filename: filename)
|
||||||
return .success(file)
|
return .success(file)
|
||||||
} catch {
|
} catch {
|
||||||
MXLog.error("Failed retrieving file with error: \(error)")
|
MXLog.error("Failed retrieving file with error: \(error)")
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ protocol MediaProviderProtocol {
|
|||||||
|
|
||||||
func loadThumbnailForSource(source: MediaSourceProxy, size: CGSize) async -> Result<Data, MediaProviderError>
|
func loadThumbnailForSource(source: MediaSourceProxy, size: CGSize) async -> Result<Data, MediaProviderError>
|
||||||
|
|
||||||
func loadFileFromSource(_ source: MediaSourceProxy, body: String?) async -> Result<MediaFileHandleProxy, MediaProviderError>
|
func loadFileFromSource(_ source: MediaSourceProxy, filename: String?) async -> Result<MediaFileHandleProxy, MediaProviderError>
|
||||||
}
|
}
|
||||||
|
|
||||||
extension MediaProviderProtocol {
|
extension MediaProviderProtocol {
|
||||||
@@ -38,6 +38,6 @@ extension MediaProviderProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func loadFileFromSource(_ source: MediaSourceProxy) async -> Result<MediaFileHandleProxy, MediaProviderError> {
|
func loadFileFromSource(_ source: MediaSourceProxy) async -> Result<MediaFileHandleProxy, MediaProviderError> {
|
||||||
await loadFileFromSource(source, body: nil)
|
await loadFileFromSource(source, filename: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ enum RoomTimelineItemFixtures {
|
|||||||
canBeRepliedTo: true,
|
canBeRepliedTo: true,
|
||||||
isThreaded: false,
|
isThreaded: false,
|
||||||
sender: .init(id: ""),
|
sender: .init(id: ""),
|
||||||
content: .init(body: "video",
|
content: .init(filename: "video.mp4",
|
||||||
duration: 100,
|
duration: 100,
|
||||||
source: .init(url: .picturesDirectory, mimeType: nil),
|
source: .init(url: .picturesDirectory, mimeType: nil),
|
||||||
thumbnailSource: .init(url: .picturesDirectory, mimeType: nil),
|
thumbnailSource: .init(url: .picturesDirectory, mimeType: nil),
|
||||||
@@ -272,7 +272,7 @@ enum RoomTimelineItemFixtures {
|
|||||||
canBeRepliedTo: true,
|
canBeRepliedTo: true,
|
||||||
isThreaded: false,
|
isThreaded: false,
|
||||||
sender: .init(id: ""),
|
sender: .init(id: ""),
|
||||||
content: .init(body: "image",
|
content: .init(filename: "image.jpg",
|
||||||
source: .init(url: .picturesDirectory, mimeType: nil),
|
source: .init(url: .picturesDirectory, mimeType: nil),
|
||||||
thumbnailSource: nil,
|
thumbnailSource: nil,
|
||||||
width: 5120,
|
width: 5120,
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ struct AudioRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatable {
|
|||||||
var properties = RoomTimelineItemProperties()
|
var properties = RoomTimelineItemProperties()
|
||||||
|
|
||||||
var body: String {
|
var body: String {
|
||||||
content.body
|
content.caption ?? content.filename
|
||||||
}
|
}
|
||||||
|
|
||||||
var contentType: EventBasedMessageTimelineItemContentType {
|
var contentType: EventBasedMessageTimelineItemContentType {
|
||||||
|
|||||||
+5
-1
@@ -9,7 +9,11 @@ import UIKit
|
|||||||
import UniformTypeIdentifiers
|
import UniformTypeIdentifiers
|
||||||
|
|
||||||
struct AudioRoomTimelineItemContent: Hashable {
|
struct AudioRoomTimelineItemContent: Hashable {
|
||||||
let body: String
|
let filename: String
|
||||||
|
var caption: String?
|
||||||
|
var formattedCaption: AttributedString?
|
||||||
|
/// The original textual representation of the formatted caption directly from the event (usually HTML code)
|
||||||
|
var formattedCaptionHTMLString: String?
|
||||||
let duration: TimeInterval
|
let duration: TimeInterval
|
||||||
let waveform: EstimatedWaveform?
|
let waveform: EstimatedWaveform?
|
||||||
let source: MediaSourceProxy?
|
let source: MediaSourceProxy?
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,7 @@ struct FileRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatable {
|
|||||||
var properties = RoomTimelineItemProperties()
|
var properties = RoomTimelineItemProperties()
|
||||||
|
|
||||||
var body: String {
|
var body: String {
|
||||||
content.body
|
content.caption ?? content.filename
|
||||||
}
|
}
|
||||||
|
|
||||||
var contentType: EventBasedMessageTimelineItemContentType {
|
var contentType: EventBasedMessageTimelineItemContentType {
|
||||||
|
|||||||
+5
-1
@@ -9,7 +9,11 @@ import Foundation
|
|||||||
import UniformTypeIdentifiers
|
import UniformTypeIdentifiers
|
||||||
|
|
||||||
struct FileRoomTimelineItemContent: Hashable {
|
struct FileRoomTimelineItemContent: Hashable {
|
||||||
let body: String
|
let filename: String
|
||||||
|
var caption: String?
|
||||||
|
var formattedCaption: AttributedString?
|
||||||
|
/// The original textual representation of the formatted caption directly from the event (usually HTML code)
|
||||||
|
var formattedCaptionHTMLString: String?
|
||||||
let source: MediaSourceProxy?
|
let source: MediaSourceProxy?
|
||||||
let thumbnailSource: MediaSourceProxy?
|
let thumbnailSource: MediaSourceProxy?
|
||||||
let contentType: UTType?
|
let contentType: UTType?
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ struct ImageRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatable {
|
|||||||
var properties = RoomTimelineItemProperties()
|
var properties = RoomTimelineItemProperties()
|
||||||
|
|
||||||
var body: String {
|
var body: String {
|
||||||
content.body
|
content.caption ?? content.filename
|
||||||
}
|
}
|
||||||
|
|
||||||
var contentType: EventBasedMessageTimelineItemContentType {
|
var contentType: EventBasedMessageTimelineItemContentType {
|
||||||
|
|||||||
+5
-1
@@ -9,7 +9,11 @@ import Foundation
|
|||||||
import UniformTypeIdentifiers
|
import UniformTypeIdentifiers
|
||||||
|
|
||||||
struct ImageRoomTimelineItemContent: Hashable {
|
struct ImageRoomTimelineItemContent: Hashable {
|
||||||
let body: String
|
let filename: String
|
||||||
|
var caption: String?
|
||||||
|
var formattedCaption: AttributedString?
|
||||||
|
/// The original textual representation of the formatted caption directly from the event (usually HTML code)
|
||||||
|
var formattedCaptionHTMLString: String?
|
||||||
let source: MediaSourceProxy
|
let source: MediaSourceProxy
|
||||||
let thumbnailSource: MediaSourceProxy?
|
let thumbnailSource: MediaSourceProxy?
|
||||||
var width: CGFloat?
|
var width: CGFloat?
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ struct VideoRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatable {
|
|||||||
var properties = RoomTimelineItemProperties()
|
var properties = RoomTimelineItemProperties()
|
||||||
|
|
||||||
var body: String {
|
var body: String {
|
||||||
content.body
|
content.caption ?? content.filename
|
||||||
}
|
}
|
||||||
|
|
||||||
var contentType: EventBasedMessageTimelineItemContentType {
|
var contentType: EventBasedMessageTimelineItemContentType {
|
||||||
|
|||||||
+5
-1
@@ -9,7 +9,11 @@ import Foundation
|
|||||||
import UniformTypeIdentifiers
|
import UniformTypeIdentifiers
|
||||||
|
|
||||||
struct VideoRoomTimelineItemContent: Hashable {
|
struct VideoRoomTimelineItemContent: Hashable {
|
||||||
let body: String
|
let filename: String
|
||||||
|
var caption: String?
|
||||||
|
var formattedCaption: AttributedString?
|
||||||
|
/// The original textual representation of the formatted caption directly from the event (usually HTML code)
|
||||||
|
var formattedCaptionHTMLString: String?
|
||||||
let duration: TimeInterval
|
let duration: TimeInterval
|
||||||
let source: MediaSourceProxy?
|
let source: MediaSourceProxy?
|
||||||
let thumbnailSource: MediaSourceProxy?
|
let thumbnailSource: MediaSourceProxy?
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ struct VoiceMessageRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equa
|
|||||||
var properties = RoomTimelineItemProperties()
|
var properties = RoomTimelineItemProperties()
|
||||||
|
|
||||||
var body: String {
|
var body: String {
|
||||||
content.body
|
content.caption ?? content.filename
|
||||||
}
|
}
|
||||||
|
|
||||||
var contentType: EventBasedMessageTimelineItemContentType {
|
var contentType: EventBasedMessageTimelineItemContentType {
|
||||||
|
|||||||
+1
-1
@@ -63,7 +63,7 @@ struct VoiceMessageRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
|||||||
canBeRepliedTo: true,
|
canBeRepliedTo: true,
|
||||||
isThreaded: false,
|
isThreaded: false,
|
||||||
sender: .init(id: "Bob"),
|
sender: .init(id: "Bob"),
|
||||||
content: .init(body: "audio.ogg",
|
content: .init(filename: "audio.ogg",
|
||||||
duration: 300,
|
duration: 300,
|
||||||
waveform: EstimatedWaveform.mockWaveform,
|
waveform: EstimatedWaveform.mockWaveform,
|
||||||
source: nil,
|
source: nil,
|
||||||
|
|||||||
@@ -490,12 +490,18 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func buildAudioTimelineItemContent(_ messageContent: AudioMessageContent) -> AudioRoomTimelineItemContent {
|
private func buildAudioTimelineItemContent(_ messageContent: AudioMessageContent) -> AudioRoomTimelineItemContent {
|
||||||
|
let htmlCaption = messageContent.formattedCaption?.format == .html ? messageContent.formattedCaption?.body : nil
|
||||||
|
let formattedCaption = htmlCaption != nil ? attributedStringBuilder.fromHTML(htmlCaption) : attributedStringBuilder.fromPlain(messageContent.caption)
|
||||||
|
|
||||||
var waveform: EstimatedWaveform?
|
var waveform: EstimatedWaveform?
|
||||||
if let audioWaveform = messageContent.audio?.waveform {
|
if let audioWaveform = messageContent.audio?.waveform {
|
||||||
waveform = EstimatedWaveform(data: audioWaveform)
|
waveform = EstimatedWaveform(data: audioWaveform)
|
||||||
}
|
}
|
||||||
|
|
||||||
return AudioRoomTimelineItemContent(body: messageContent.body,
|
return AudioRoomTimelineItemContent(filename: messageContent.filename,
|
||||||
|
caption: messageContent.caption,
|
||||||
|
formattedCaption: formattedCaption,
|
||||||
|
formattedCaptionHTMLString: htmlCaption,
|
||||||
duration: messageContent.audio?.duration ?? 0,
|
duration: messageContent.audio?.duration ?? 0,
|
||||||
waveform: waveform,
|
waveform: waveform,
|
||||||
source: MediaSourceProxy(source: messageContent.source, mimeType: messageContent.info?.mimetype),
|
source: MediaSourceProxy(source: messageContent.source, mimeType: messageContent.info?.mimetype),
|
||||||
@@ -503,6 +509,9 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func buildImageTimelineItemContent(_ messageContent: ImageMessageContent) -> ImageRoomTimelineItemContent {
|
private func buildImageTimelineItemContent(_ messageContent: ImageMessageContent) -> ImageRoomTimelineItemContent {
|
||||||
|
let htmlCaption = messageContent.formattedCaption?.format == .html ? messageContent.formattedCaption?.body : nil
|
||||||
|
let formattedCaption = htmlCaption != nil ? attributedStringBuilder.fromHTML(htmlCaption) : attributedStringBuilder.fromPlain(messageContent.caption)
|
||||||
|
|
||||||
let thumbnailSource = messageContent.info?.thumbnailSource.map { MediaSourceProxy(source: $0, mimeType: messageContent.info?.thumbnailInfo?.mimetype) }
|
let thumbnailSource = messageContent.info?.thumbnailSource.map { MediaSourceProxy(source: $0, mimeType: messageContent.info?.thumbnailInfo?.mimetype) }
|
||||||
let width = messageContent.info?.width.map(CGFloat.init)
|
let width = messageContent.info?.width.map(CGFloat.init)
|
||||||
let height = messageContent.info?.height.map(CGFloat.init)
|
let height = messageContent.info?.height.map(CGFloat.init)
|
||||||
@@ -512,7 +521,10 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
|||||||
aspectRatio = width / height
|
aspectRatio = width / height
|
||||||
}
|
}
|
||||||
|
|
||||||
return .init(body: messageContent.body,
|
return .init(filename: messageContent.filename,
|
||||||
|
caption: messageContent.caption,
|
||||||
|
formattedCaption: formattedCaption,
|
||||||
|
formattedCaptionHTMLString: htmlCaption,
|
||||||
source: MediaSourceProxy(source: messageContent.source, mimeType: messageContent.info?.mimetype),
|
source: MediaSourceProxy(source: messageContent.source, mimeType: messageContent.info?.mimetype),
|
||||||
thumbnailSource: thumbnailSource,
|
thumbnailSource: thumbnailSource,
|
||||||
width: width,
|
width: width,
|
||||||
@@ -523,6 +535,9 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func buildVideoTimelineItemContent(_ messageContent: VideoMessageContent) -> VideoRoomTimelineItemContent {
|
private func buildVideoTimelineItemContent(_ messageContent: VideoMessageContent) -> VideoRoomTimelineItemContent {
|
||||||
|
let htmlCaption = messageContent.formattedCaption?.format == .html ? messageContent.formattedCaption?.body : nil
|
||||||
|
let formattedCaption = htmlCaption != nil ? attributedStringBuilder.fromHTML(htmlCaption) : attributedStringBuilder.fromPlain(messageContent.caption)
|
||||||
|
|
||||||
let thumbnailSource = messageContent.info?.thumbnailSource.map { MediaSourceProxy(source: $0, mimeType: messageContent.info?.thumbnailInfo?.mimetype) }
|
let thumbnailSource = messageContent.info?.thumbnailSource.map { MediaSourceProxy(source: $0, mimeType: messageContent.info?.thumbnailInfo?.mimetype) }
|
||||||
let width = messageContent.info?.width.map(CGFloat.init)
|
let width = messageContent.info?.width.map(CGFloat.init)
|
||||||
let height = messageContent.info?.height.map(CGFloat.init)
|
let height = messageContent.info?.height.map(CGFloat.init)
|
||||||
@@ -532,7 +547,10 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
|||||||
aspectRatio = width / height
|
aspectRatio = width / height
|
||||||
}
|
}
|
||||||
|
|
||||||
return .init(body: messageContent.body,
|
return .init(filename: messageContent.filename,
|
||||||
|
caption: messageContent.caption,
|
||||||
|
formattedCaption: formattedCaption,
|
||||||
|
formattedCaptionHTMLString: htmlCaption,
|
||||||
duration: messageContent.info?.duration ?? 0,
|
duration: messageContent.info?.duration ?? 0,
|
||||||
source: MediaSourceProxy(source: messageContent.source, mimeType: messageContent.info?.mimetype),
|
source: MediaSourceProxy(source: messageContent.source, mimeType: messageContent.info?.mimetype),
|
||||||
thumbnailSource: thumbnailSource,
|
thumbnailSource: thumbnailSource,
|
||||||
@@ -550,9 +568,15 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func buildFileTimelineItemContent(_ messageContent: FileMessageContent) -> FileRoomTimelineItemContent {
|
private func buildFileTimelineItemContent(_ messageContent: FileMessageContent) -> FileRoomTimelineItemContent {
|
||||||
|
let htmlCaption = messageContent.formattedCaption?.format == .html ? messageContent.formattedCaption?.body : nil
|
||||||
|
let formattedCaption = htmlCaption != nil ? attributedStringBuilder.fromHTML(htmlCaption) : attributedStringBuilder.fromPlain(messageContent.caption)
|
||||||
|
|
||||||
let thumbnailSource = messageContent.info?.thumbnailSource.map { MediaSourceProxy(source: $0, mimeType: messageContent.info?.thumbnailInfo?.mimetype) }
|
let thumbnailSource = messageContent.info?.thumbnailSource.map { MediaSourceProxy(source: $0, mimeType: messageContent.info?.thumbnailInfo?.mimetype) }
|
||||||
|
|
||||||
return .init(body: messageContent.body,
|
return .init(filename: messageContent.filename,
|
||||||
|
caption: messageContent.caption,
|
||||||
|
formattedCaption: formattedCaption,
|
||||||
|
formattedCaptionHTMLString: htmlCaption,
|
||||||
source: MediaSourceProxy(source: messageContent.source, mimeType: messageContent.info?.mimetype),
|
source: MediaSourceProxy(source: messageContent.source, mimeType: messageContent.info?.mimetype),
|
||||||
thumbnailSource: thumbnailSource,
|
thumbnailSource: thumbnailSource,
|
||||||
contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.body))
|
contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.body))
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class VoiceMessageMediaManager: VoiceMessageMediaManagerProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, load the file from source
|
// Otherwise, load the file from source
|
||||||
guard case .success(let fileHandle) = await mediaProvider.loadFileFromSource(source, body: body) else {
|
guard case .success(let fileHandle) = await mediaProvider.loadFileFromSource(source, filename: body) else {
|
||||||
throw MediaProviderError.failedRetrievingFile
|
throw MediaProviderError.failedRetrievingFile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:9b0e4caaf122d984b137f3d7bfebf701aa63def993cf2681ed06ddcdf4805af4
|
oid sha256:6a034b807916e062e25c5fb59ecd09a47d0e1c7c822534b35e992fd9c839ab07
|
||||||
size 197604
|
size 196481
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:9b0e4caaf122d984b137f3d7bfebf701aa63def993cf2681ed06ddcdf4805af4
|
oid sha256:6a034b807916e062e25c5fb59ecd09a47d0e1c7c822534b35e992fd9c839ab07
|
||||||
size 197604
|
size 196481
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:f54b2d9bafaf2e9f2fd304dfa8e1956d079a7280e9075d9ef1f1b3005314ae3a
|
oid sha256:ffe1ceda422b0bccc1e587036ea047bebb4ee4643f54bdf25ff2b3b530b6f7e2
|
||||||
size 200745
|
size 199662
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:f54b2d9bafaf2e9f2fd304dfa8e1956d079a7280e9075d9ef1f1b3005314ae3a
|
oid sha256:ffe1ceda422b0bccc1e587036ea047bebb4ee4643f54bdf25ff2b3b530b6f7e2
|
||||||
size 200745
|
size 199662
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:d81827ae7b6798e844365ed7f0971d56df662cded25c03a300cf8a817afdbf51
|
oid sha256:91bef32e5248f8084995b237b671cea005ce0eb9253a325165dd066a43934bfa
|
||||||
size 136742
|
size 135848
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:d81827ae7b6798e844365ed7f0971d56df662cded25c03a300cf8a817afdbf51
|
oid sha256:91bef32e5248f8084995b237b671cea005ce0eb9253a325165dd066a43934bfa
|
||||||
size 136742
|
size 135848
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:f16f475a1f4fd5e3c2a00e294103721df1b8bd38f69ccac9f4b295efac0e8af5
|
oid sha256:c5fd3ee0cc6bb3cf124cc66877d87cde800a3da7c10f8e26d6e19d884f4ca40e
|
||||||
size 139891
|
size 139138
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:f16f475a1f4fd5e3c2a00e294103721df1b8bd38f69ccac9f4b295efac0e8af5
|
oid sha256:c5fd3ee0cc6bb3cf124cc66877d87cde800a3da7c10f8e26d6e19d884f4ca40e
|
||||||
size 139891
|
size 139138
|
||||||
|
|||||||
@@ -149,7 +149,10 @@ class LoggingTests: XCTestCase {
|
|||||||
canBeRepliedTo: true,
|
canBeRepliedTo: true,
|
||||||
isThreaded: false,
|
isThreaded: false,
|
||||||
sender: .init(id: "sender"),
|
sender: .init(id: "sender"),
|
||||||
content: .init(body: "ImageString", source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/gif"), thumbnailSource: nil))
|
content: .init(filename: "ImageString",
|
||||||
|
caption: "ImageString",
|
||||||
|
source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/gif"),
|
||||||
|
thumbnailSource: nil))
|
||||||
let videoMessage = VideoRoomTimelineItem(id: .random,
|
let videoMessage = VideoRoomTimelineItem(id: .random,
|
||||||
timestamp: "",
|
timestamp: "",
|
||||||
isOutgoing: false,
|
isOutgoing: false,
|
||||||
@@ -157,7 +160,11 @@ class LoggingTests: XCTestCase {
|
|||||||
canBeRepliedTo: true,
|
canBeRepliedTo: true,
|
||||||
isThreaded: false,
|
isThreaded: false,
|
||||||
sender: .init(id: "sender"),
|
sender: .init(id: "sender"),
|
||||||
content: .init(body: "VideoString", duration: 0, source: nil, thumbnailSource: nil))
|
content: .init(filename: "VideoString",
|
||||||
|
caption: "VideoString",
|
||||||
|
duration: 0,
|
||||||
|
source: nil,
|
||||||
|
thumbnailSource: nil))
|
||||||
let fileMessage = FileRoomTimelineItem(id: .random,
|
let fileMessage = FileRoomTimelineItem(id: .random,
|
||||||
timestamp: "",
|
timestamp: "",
|
||||||
isOutgoing: false,
|
isOutgoing: false,
|
||||||
@@ -165,7 +172,11 @@ class LoggingTests: XCTestCase {
|
|||||||
canBeRepliedTo: true,
|
canBeRepliedTo: true,
|
||||||
isThreaded: false,
|
isThreaded: false,
|
||||||
sender: .init(id: "sender"),
|
sender: .init(id: "sender"),
|
||||||
content: .init(body: "FileString", source: nil, thumbnailSource: nil, contentType: nil))
|
content: .init(filename: "FileString",
|
||||||
|
caption: "FileString",
|
||||||
|
source: nil,
|
||||||
|
thumbnailSource: nil,
|
||||||
|
contentType: nil))
|
||||||
|
|
||||||
// When logging that value
|
// When logging that value
|
||||||
MXLog.configure(currentTarget: "tests", filePrefix: nil, logLevel: .info)
|
MXLog.configure(currentTarget: "tests", filePrefix: nil, logLevel: .info)
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class VoiceMessageMediaManagerTests: XCTestCase {
|
|||||||
|
|
||||||
voiceMessageCache.fileURLForReturnValue = nil
|
voiceMessageCache.fileURLForReturnValue = nil
|
||||||
let mediaSource = MediaSourceProxy(url: someURL, mimeType: "audio/ogg; codecs=opus")
|
let mediaSource = MediaSourceProxy(url: someURL, mimeType: "audio/ogg; codecs=opus")
|
||||||
mediaProvider.loadFileFromSourceBodyReturnValue = .success(MediaFileHandleProxy.unmanaged(url: loadedFile))
|
mediaProvider.loadFileFromSourceFilenameReturnValue = .success(MediaFileHandleProxy.unmanaged(url: loadedFile))
|
||||||
voiceMessageCache.cacheMediaSourceUsingMoveReturnValue = .success(cachedConvertedFileURL)
|
voiceMessageCache.cacheMediaSourceUsingMoveReturnValue = .success(cachedConvertedFileURL)
|
||||||
|
|
||||||
voiceMessageMediaManager = VoiceMessageMediaManager(mediaProvider: mediaProvider,
|
voiceMessageMediaManager = VoiceMessageMediaManager(mediaProvider: mediaProvider,
|
||||||
@@ -103,7 +103,7 @@ class VoiceMessageMediaManagerTests: XCTestCase {
|
|||||||
// Check if the file is not already present in cache
|
// Check if the file is not already present in cache
|
||||||
voiceMessageCache.fileURLForReturnValue = nil
|
voiceMessageCache.fileURLForReturnValue = nil
|
||||||
let mediaSource = MediaSourceProxy(url: someURL, mimeType: audioOGGMimeType)
|
let mediaSource = MediaSourceProxy(url: someURL, mimeType: audioOGGMimeType)
|
||||||
mediaProvider.loadFileFromSourceBodyReturnValue = .success(MediaFileHandleProxy.unmanaged(url: loadedFile))
|
mediaProvider.loadFileFromSourceFilenameReturnValue = .success(MediaFileHandleProxy.unmanaged(url: loadedFile))
|
||||||
let audioConverter = AudioConverterMock()
|
let audioConverter = AudioConverterMock()
|
||||||
voiceMessageCache.cacheMediaSourceUsingMoveReturnValue = .success(cachedConvertedFileURL)
|
voiceMessageCache.cacheMediaSourceUsingMoveReturnValue = .success(cachedConvertedFileURL)
|
||||||
voiceMessageMediaManager = VoiceMessageMediaManager(mediaProvider: mediaProvider,
|
voiceMessageMediaManager = VoiceMessageMediaManager(mediaProvider: mediaProvider,
|
||||||
@@ -139,7 +139,7 @@ class VoiceMessageMediaManagerTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let audioConverter = AudioConverterMock()
|
let audioConverter = AudioConverterMock()
|
||||||
mediaProvider.loadFileFromSourceBodyReturnValue = .success(MediaFileHandleProxy.unmanaged(url: loadedFile))
|
mediaProvider.loadFileFromSourceFilenameReturnValue = .success(MediaFileHandleProxy.unmanaged(url: loadedFile))
|
||||||
|
|
||||||
voiceMessageMediaManager = VoiceMessageMediaManager(mediaProvider: mediaProvider,
|
voiceMessageMediaManager = VoiceMessageMediaManager(mediaProvider: mediaProvider,
|
||||||
voiceMessageCache: voiceMessageCache,
|
voiceMessageCache: voiceMessageCache,
|
||||||
|
|||||||
Reference in New Issue
Block a user