mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-05 03:48:27 +00:00
Bump the RustSDK to v1.0.67 (#3512)
* Bump the RustSDK to v1.0.67 * PR comments --------- Co-authored-by: Doug <douglase@element.io>
This commit is contained in:
@@ -811,13 +811,14 @@ class ClientProxy: ClientProxyProtocol {
|
||||
do {
|
||||
let syncService = try await client
|
||||
.syncService()
|
||||
.withCrossProcessLock(appIdentifier: "MainApp")
|
||||
.withCrossProcessLock()
|
||||
.withUtdHook(delegate: ClientDecryptionErrorDelegate(actionsSubject: actionsSubject))
|
||||
.finish()
|
||||
|
||||
let roomListService = syncService.roomListService()
|
||||
|
||||
let roomMessageEventStringBuilder = RoomMessageEventStringBuilder(attributedStringBuilder: AttributedStringBuilder(cacheKey: "roomList",
|
||||
mentionBuilder: PlainMentionBuilder()), prefix: .senderName)
|
||||
mentionBuilder: PlainMentionBuilder()), destination: .roomList)
|
||||
let eventStringBuilder = RoomEventStringBuilder(stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID, shouldDisambiguateDisplayNames: false),
|
||||
messageEventStringBuilder: roomMessageEventStringBuilder,
|
||||
shouldDisambiguateDisplayNames: false,
|
||||
|
||||
@@ -315,47 +315,22 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func resend(itemID: TimelineItemIdentifier) async -> Result<Void, RoomProxyError> {
|
||||
guard let transactionID = itemID.transactionID else {
|
||||
MXLog.error("Attempting to resend an item that has no transaction ID: \(itemID)")
|
||||
return .failure(.missingTransactionID)
|
||||
}
|
||||
|
||||
func ignoreDeviceTrustAndResend(devices: [String: [String]], sendHandle: SendHandleProxy) async -> Result<Void, RoomProxyError> {
|
||||
do {
|
||||
try await room.tryResend(transactionId: transactionID)
|
||||
try await room.ignoreDeviceTrustAndResend(devices: devices, sendHandle: sendHandle.underlyingHandle)
|
||||
return .success(())
|
||||
} catch {
|
||||
MXLog.error("Failed resending \(transactionID) with error: \(error)")
|
||||
MXLog.error("Failed trusting devices \(devices) and resending \(sendHandle.itemID) with error: \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
|
||||
func ignoreDeviceTrustAndResend(devices: [String: [String]], itemID: TimelineItemIdentifier) async -> Result<Void, RoomProxyError> {
|
||||
guard let transactionID = itemID.transactionID else {
|
||||
MXLog.error("Attempting to resend an item that has no transaction ID: \(itemID)")
|
||||
return .failure(.missingTransactionID)
|
||||
}
|
||||
|
||||
func withdrawVerificationAndResend(userIDs: [String], sendHandle: SendHandleProxy) async -> Result<Void, RoomProxyError> {
|
||||
do {
|
||||
try await room.ignoreDeviceTrustAndResend(devices: devices, transactionId: transactionID)
|
||||
try await room.withdrawVerificationAndResend(userIds: userIDs, sendHandle: sendHandle.underlyingHandle)
|
||||
return .success(())
|
||||
} catch {
|
||||
MXLog.error("Failed trusting devices \(devices) and resending \(transactionID) with error: \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
|
||||
func withdrawVerificationAndResend(userIDs: [String], itemID: TimelineItemIdentifier) async -> Result<Void, RoomProxyError> {
|
||||
guard let transactionID = itemID.transactionID else {
|
||||
MXLog.error("Attempting to resend an item that has no transaction ID: \(itemID)")
|
||||
return .failure(.missingTransactionID)
|
||||
}
|
||||
|
||||
do {
|
||||
try await room.withdrawVerificationAndResend(userIds: userIDs, transactionId: transactionID)
|
||||
return .success(())
|
||||
} catch {
|
||||
MXLog.error("Failed withdrawing verification of \(userIDs) and resending \(transactionID) with error: \(error)")
|
||||
MXLog.error("Failed withdrawing verification of \(userIDs) and resending \(sendHandle.itemID) with error: \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,11 +97,9 @@ protocol JoinedRoomProxyProtocol: RoomProxyProtocol {
|
||||
/// https://spec.matrix.org/v1.9/client-server-api/#typing-notifications
|
||||
@discardableResult func sendTypingNotification(isTyping: Bool) async -> Result<Void, RoomProxyError>
|
||||
|
||||
func resend(itemID: TimelineItemIdentifier) async -> Result<Void, RoomProxyError>
|
||||
func ignoreDeviceTrustAndResend(devices: [String: [String]], sendHandle: SendHandleProxy) async -> Result<Void, RoomProxyError>
|
||||
|
||||
func ignoreDeviceTrustAndResend(devices: [String: [String]], itemID: TimelineItemIdentifier) async -> Result<Void, RoomProxyError>
|
||||
|
||||
func withdrawVerificationAndResend(userIDs: [String], itemID: TimelineItemIdentifier) async -> Result<Void, RoomProxyError>
|
||||
func withdrawVerificationAndResend(userIDs: [String], sendHandle: SendHandleProxy) async -> Result<Void, RoomProxyError>
|
||||
|
||||
// MARK: - Room Flags
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ struct RoomEventStringBuilder {
|
||||
case .redactedMessage:
|
||||
return prefix(L10n.commonMessageRemoved, with: displayName)
|
||||
case .sticker:
|
||||
if messageEventStringBuilder.prefix == .messageType {
|
||||
if messageEventStringBuilder.destination == .pinnedEvent {
|
||||
var string = AttributedString(L10n.commonSticker)
|
||||
string.bold()
|
||||
return string
|
||||
@@ -49,7 +49,7 @@ struct RoomEventStringBuilder {
|
||||
return stateEventStringBuilder
|
||||
.buildString(for: state, sender: sender, isOutgoing: isOutgoing)
|
||||
.map(AttributedString.init)
|
||||
case .roomMembership(let userID, let displayName, let change):
|
||||
case .roomMembership(let userID, let displayName, let change, _):
|
||||
return stateEventStringBuilder
|
||||
.buildString(for: change, memberUserID: userID, memberDisplayName: displayName, sender: sender, isOutgoing: isOutgoing)
|
||||
.map(AttributedString.init)
|
||||
@@ -63,7 +63,7 @@ struct RoomEventStringBuilder {
|
||||
memberIsYou: isOutgoing)
|
||||
.map(AttributedString.init)
|
||||
case .poll(let question, _, _, _, _, _, _):
|
||||
if messageEventStringBuilder.prefix == .messageType {
|
||||
if messageEventStringBuilder.destination == .pinnedEvent {
|
||||
let questionPlaceholder = "{question}"
|
||||
var finalString = AttributedString(L10n.commonPollSummary(questionPlaceholder))
|
||||
finalString.bold()
|
||||
@@ -96,7 +96,7 @@ struct RoomEventStringBuilder {
|
||||
RoomEventStringBuilder(stateEventStringBuilder: .init(userID: userID,
|
||||
shouldDisambiguateDisplayNames: false),
|
||||
messageEventStringBuilder: .init(attributedStringBuilder: AttributedStringBuilder(cacheKey: "pinnedEvents", mentionBuilder: PlainMentionBuilder()),
|
||||
prefix: .messageType),
|
||||
destination: .pinnedEvent),
|
||||
shouldDisambiguateDisplayNames: false,
|
||||
shouldPrefixSenderName: false)
|
||||
}
|
||||
|
||||
@@ -9,42 +9,46 @@ import Foundation
|
||||
import MatrixRustSDK
|
||||
|
||||
struct RoomMessageEventStringBuilder {
|
||||
enum Prefix {
|
||||
case senderName
|
||||
case messageType
|
||||
case none
|
||||
enum Destination {
|
||||
/// Strings show on the room list as the last message
|
||||
/// The sender will be prefixed in bold
|
||||
case roomList
|
||||
/// Events pinned to the banner on the top of the timeline
|
||||
/// The message type will be prefixed in bold
|
||||
case pinnedEvent
|
||||
/// Shown in push notifications
|
||||
/// No prefix
|
||||
case notification
|
||||
}
|
||||
|
||||
let attributedStringBuilder: AttributedStringBuilderProtocol
|
||||
let prefix: Prefix
|
||||
let destination: Destination
|
||||
|
||||
func buildAttributedString(for messageType: MessageType, senderDisplayName: String) -> AttributedString {
|
||||
let message: AttributedString
|
||||
switch messageType {
|
||||
// Message types that don't need a prefix.
|
||||
case .emote(content: let content):
|
||||
if let attributedMessage = attributedMessageFrom(formattedBody: content.formatted) {
|
||||
return AttributedString(L10n.commonEmote(senderDisplayName, String(attributedMessage.characters)))
|
||||
} else {
|
||||
return AttributedString(L10n.commonEmote(senderDisplayName, content.body))
|
||||
}
|
||||
// Message types that should be prefixed with the sender's name.
|
||||
case .audio(content: let content):
|
||||
let isVoiceMessage = content.voice != nil
|
||||
var content = AttributedString(isVoiceMessage ? L10n.commonVoiceMessage : L10n.commonAudio)
|
||||
if prefix == .messageType {
|
||||
if destination == .pinnedEvent {
|
||||
content.bold()
|
||||
}
|
||||
message = content
|
||||
case .image(let content):
|
||||
message = prefix == .messageType ? prefix(AttributedString(content.body), with: L10n.commonImage) : AttributedString("\(L10n.commonImage) - \(content.body)")
|
||||
message = buildMessage(for: destination, caption: content.caption, type: L10n.commonImage)
|
||||
case .video(let content):
|
||||
message = prefix == .messageType ? prefix(AttributedString(content.body), with: L10n.commonVideo) : AttributedString("\(L10n.commonVideo) - \(content.body)")
|
||||
message = buildMessage(for: destination, caption: content.caption, type: L10n.commonVideo)
|
||||
case .file(let content):
|
||||
message = prefix == .messageType ? prefix(AttributedString(content.body), with: L10n.commonFile) : AttributedString("\(L10n.commonFile) - \(content.body)")
|
||||
message = buildMessage(for: destination, caption: content.caption, type: L10n.commonFile)
|
||||
case .location:
|
||||
var content = AttributedString(L10n.commonSharedLocation)
|
||||
if prefix == .messageType {
|
||||
if destination == .pinnedEvent {
|
||||
content.bold()
|
||||
}
|
||||
message = content
|
||||
@@ -64,13 +68,25 @@ struct RoomMessageEventStringBuilder {
|
||||
message = AttributedString(body)
|
||||
}
|
||||
|
||||
if prefix == .senderName {
|
||||
if destination == .roomList {
|
||||
return prefix(message, with: senderDisplayName)
|
||||
} else {
|
||||
return message
|
||||
}
|
||||
}
|
||||
|
||||
private func buildMessage(for destination: Destination, caption: String?, type: String) -> AttributedString {
|
||||
guard let caption else {
|
||||
return AttributedString(type)
|
||||
}
|
||||
|
||||
if destination == .pinnedEvent {
|
||||
return prefix(AttributedString(caption), with: type)
|
||||
} else {
|
||||
return AttributedString("\(type) - \(caption)")
|
||||
}
|
||||
}
|
||||
|
||||
private func prefix(_ eventSummary: AttributedString, with textToBold: String) -> AttributedString {
|
||||
let attributedEventSummary = AttributedString(eventSummary.string.trimmingCharacters(in: .whitespacesAndNewlines))
|
||||
|
||||
|
||||
@@ -104,6 +104,10 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {
|
||||
func debugInfo(for itemID: TimelineItemIdentifier) -> TimelineItemDebugInfo {
|
||||
.init(model: "Mock debug description", originalJSON: nil, latestEditJSON: nil)
|
||||
}
|
||||
|
||||
func sendHandle(for itemID: TimelineItemIdentifier) -> SendHandleProxy? {
|
||||
nil
|
||||
}
|
||||
|
||||
func retryDecryption(for sessionID: String) async { }
|
||||
|
||||
|
||||
@@ -308,6 +308,21 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
return .init(model: "Unknown item", originalJSON: nil, latestEditJSON: nil)
|
||||
}
|
||||
|
||||
func sendHandle(for itemID: TimelineItemIdentifier) -> SendHandleProxy? {
|
||||
for timelineItemProxy in activeTimelineProvider.itemProxies {
|
||||
switch timelineItemProxy {
|
||||
case .event(let item):
|
||||
if item.id == itemID {
|
||||
return item.sendHandle.map { .init(itemID: itemID, underlyingHandle: $0) }
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func retryDecryption(for sessionID: String) async {
|
||||
await activeTimeline.retryDecryption(for: sessionID)
|
||||
}
|
||||
|
||||
+2
@@ -68,6 +68,8 @@ protocol RoomTimelineControllerProtocol {
|
||||
|
||||
func debugInfo(for itemID: TimelineItemIdentifier) -> TimelineItemDebugInfo
|
||||
|
||||
func sendHandle(for itemID: TimelineItemIdentifier) -> SendHandleProxy?
|
||||
|
||||
func retryDecryption(for sessionID: String) async
|
||||
|
||||
func eventTimestamp(for itemID: TimelineItemIdentifier) -> Date?
|
||||
|
||||
@@ -135,6 +135,8 @@ class EventTimelineItemProxy {
|
||||
|
||||
lazy var shieldState = item.lazyProvider.getShields(strict: false)
|
||||
|
||||
lazy var sendHandle = item.lazyProvider.getSendHandle()
|
||||
|
||||
lazy var readReceipts = item.readReceipts
|
||||
}
|
||||
|
||||
@@ -179,6 +181,40 @@ struct TimelineItemDebugInfo: Identifiable, CustomStringConvertible {
|
||||
}
|
||||
}
|
||||
|
||||
struct SendHandleProxy: Hashable {
|
||||
enum Error: Swift.Error {
|
||||
case sdkError(Swift.Error)
|
||||
}
|
||||
|
||||
let itemID: TimelineItemIdentifier
|
||||
let underlyingHandle: SendHandle
|
||||
|
||||
func resend() async -> Result<Void, Error> {
|
||||
do {
|
||||
try await underlyingHandle.tryResend()
|
||||
return .success(())
|
||||
} catch {
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Hashable
|
||||
|
||||
static func == (lhs: SendHandleProxy, rhs: SendHandleProxy) -> Bool {
|
||||
lhs.itemID == rhs.itemID
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(itemID)
|
||||
}
|
||||
|
||||
static var mock: SendHandleProxy {
|
||||
.init(itemID: .event(uniqueID: .init(id: UUID().uuidString),
|
||||
eventOrTransactionID: .eventId(eventId: UUID().uuidString)),
|
||||
underlyingHandle: .init(noPointer: .init()))
|
||||
}
|
||||
}
|
||||
|
||||
extension Receipt {
|
||||
var dateTimestamp: Date? {
|
||||
guard let timestamp else {
|
||||
|
||||
@@ -50,7 +50,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
return nil
|
||||
}
|
||||
return buildStateTimelineItem(for: eventItemProxy, state: content, isOutgoing: isOutgoing)
|
||||
case .roomMembership(userId: let userID, let displayName, change: let change):
|
||||
case .roomMembership(userId: let userID, let displayName, change: let change, _):
|
||||
if isDM, change == .joined, userID == self.userID {
|
||||
return nil
|
||||
}
|
||||
@@ -511,7 +511,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
duration: messageContent.audio?.duration ?? 0,
|
||||
waveform: waveform,
|
||||
source: MediaSourceProxy(source: messageContent.source, mimeType: messageContent.info?.mimetype),
|
||||
contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.body))
|
||||
contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.filename))
|
||||
}
|
||||
|
||||
private func buildImageTimelineItemContent(_ messageContent: ImageMessageContent) -> ImageRoomTimelineItemContent {
|
||||
@@ -537,7 +537,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
height: height,
|
||||
aspectRatio: aspectRatio,
|
||||
blurhash: messageContent.info?.blurhash,
|
||||
contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.body))
|
||||
contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.filename))
|
||||
}
|
||||
|
||||
private func buildVideoTimelineItemContent(_ messageContent: VideoMessageContent) -> VideoRoomTimelineItemContent {
|
||||
@@ -564,7 +564,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
height: height,
|
||||
aspectRatio: aspectRatio,
|
||||
blurhash: messageContent.info?.blurhash,
|
||||
contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.body))
|
||||
contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.filename))
|
||||
}
|
||||
|
||||
private func buildLocationTimelineItemContent(_ locationContent: LocationContent) -> LocationRoomTimelineItemContent {
|
||||
@@ -585,7 +585,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
formattedCaptionHTMLString: htmlCaption,
|
||||
source: MediaSourceProxy(source: messageContent.source, mimeType: messageContent.info?.mimetype),
|
||||
thumbnailSource: thumbnailSource,
|
||||
contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.body))
|
||||
contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.filename))
|
||||
}
|
||||
|
||||
private func buildNoticeTimelineItemContent(_ messageContent: NoticeMessageContent) -> NoticeRoomTimelineItemContent {
|
||||
|
||||
Reference in New Issue
Block a user