mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 19:11:45 +00:00
Implement emotes (/me) (#1841)
* implement emotes (/me) requires matthew/emotes branch of matrix-rust-sdk * changelog + whitespace * remove apparently superfluous swiftlint * fix constness * remove inout params and incorporate review * switch to new api based on sdk PR feedback * Bump the RustSDK to v1.1.21 * Address PR comments --------- Co-authored-by: Stefan Ceriu <stefan.ceriu@gmail.com>
This commit is contained in:
@@ -5801,7 +5801,7 @@
|
|||||||
repositoryURL = "https://github.com/matrix-org/matrix-rust-components-swift";
|
repositoryURL = "https://github.com/matrix-org/matrix-rust-components-swift";
|
||||||
requirement = {
|
requirement = {
|
||||||
kind = exactVersion;
|
kind = exactVersion;
|
||||||
version = 1.1.20;
|
version = 1.1.21;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
821C67C9A7F8CC3FD41B28B4 /* XCRemoteSwiftPackageReference "emojibase-bindings" */ = {
|
821C67C9A7F8CC3FD41B28B4 /* XCRemoteSwiftPackageReference "emojibase-bindings" */ = {
|
||||||
|
|||||||
@@ -129,8 +129,8 @@
|
|||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/matrix-org/matrix-rust-components-swift",
|
"location" : "https://github.com/matrix-org/matrix-rust-components-swift",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "5f3a195f6a461b4d40a8a705a3af8235711f12f5",
|
"revision" : "22461632db17a6dc1193dcdcfa3231614649c517",
|
||||||
"version" : "1.1.20"
|
"version" : "1.1.21"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -615,6 +615,12 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
|||||||
} else {
|
} else {
|
||||||
text = messageTimelineItem.body
|
text = messageTimelineItem.body
|
||||||
}
|
}
|
||||||
|
case .emote(let emoteItem):
|
||||||
|
if ServiceLocator.shared.settings.richTextEditorEnabled, let formattedBodyHTMLString = emoteItem.formattedBodyHTMLString {
|
||||||
|
text = "/me " + formattedBodyHTMLString
|
||||||
|
} else {
|
||||||
|
text = "/me " + messageTimelineItem.body
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
text = messageTimelineItem.body
|
text = messageTimelineItem.body
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -259,12 +259,8 @@ class RoomProxy: RoomProxyProtocol {
|
|||||||
sendMessageBackgroundTask?.stop()
|
sendMessageBackgroundTask?.stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
let messageContent: RoomMessageEventContentWithoutRelation
|
let messageContent = buildMessageContentFor(message, html: html)
|
||||||
if let html {
|
|
||||||
messageContent = messageEventContentFromHtml(body: message, htmlBody: html)
|
|
||||||
} else {
|
|
||||||
messageContent = messageEventContentFromMarkdown(md: message)
|
|
||||||
}
|
|
||||||
return await Task.dispatch(on: messageSendingDispatchQueue) {
|
return await Task.dispatch(on: messageSendingDispatchQueue) {
|
||||||
do {
|
do {
|
||||||
if let eventID {
|
if let eventID {
|
||||||
@@ -435,23 +431,18 @@ class RoomProxy: RoomProxyProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func editMessage(_ newMessage: String, html: String?, original eventID: String) async -> Result<Void, RoomProxyError> {
|
func editMessage(_ message: String, html: String?, original eventID: String) async -> Result<Void, RoomProxyError> {
|
||||||
sendMessageBackgroundTask = await backgroundTaskService.startBackgroundTask(withName: backgroundTaskName, isReusable: true)
|
sendMessageBackgroundTask = await backgroundTaskService.startBackgroundTask(withName: backgroundTaskName, isReusable: true)
|
||||||
defer {
|
defer {
|
||||||
sendMessageBackgroundTask?.stop()
|
sendMessageBackgroundTask?.stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
let newMessageContent: RoomMessageEventContentWithoutRelation
|
let messageContent = buildMessageContentFor(message, html: html)
|
||||||
if let html {
|
|
||||||
newMessageContent = messageEventContentFromHtml(body: newMessage, htmlBody: html)
|
|
||||||
} else {
|
|
||||||
newMessageContent = messageEventContentFromMarkdown(md: newMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
return await Task.dispatch(on: messageSendingDispatchQueue) {
|
return await Task.dispatch(on: messageSendingDispatchQueue) {
|
||||||
do {
|
do {
|
||||||
let originalEvent = try self.room.getEventTimelineItemByEventId(eventId: eventID)
|
let originalEvent = try self.room.getEventTimelineItemByEventId(eventId: eventID)
|
||||||
try self.room.edit(newContent: newMessageContent, editItem: originalEvent)
|
try self.room.edit(newContent: messageContent, editItem: originalEvent)
|
||||||
return .success(())
|
return .success(())
|
||||||
} catch {
|
} catch {
|
||||||
return .failure(.failedEditingMessage)
|
return .failure(.failedEditingMessage)
|
||||||
@@ -708,6 +699,36 @@ class RoomProxy: RoomProxyProtocol {
|
|||||||
|
|
||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
|
|
||||||
|
private func buildMessageContentFor(_ message: String, html: String?) -> RoomMessageEventContentWithoutRelation {
|
||||||
|
let emoteSlashCommand = "/me "
|
||||||
|
let isEmote: Bool = message.starts(with: emoteSlashCommand)
|
||||||
|
|
||||||
|
guard isEmote else {
|
||||||
|
if let html {
|
||||||
|
return messageEventContentFromHtml(body: message, htmlBody: html)
|
||||||
|
} else {
|
||||||
|
return messageEventContentFromMarkdown(md: message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let emoteMessage = String(message.dropFirst(emoteSlashCommand.count))
|
||||||
|
|
||||||
|
var emoteHtml: String?
|
||||||
|
if let html {
|
||||||
|
emoteHtml = String(html.dropFirst(emoteSlashCommand.count))
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildEmoteMessageContentFor(emoteMessage, html: emoteHtml)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func buildEmoteMessageContentFor(_ message: String, html: String?) -> RoomMessageEventContentWithoutRelation {
|
||||||
|
if let html {
|
||||||
|
return messageEventContentFromHtmlAsEmote(body: message, htmlBody: html)
|
||||||
|
} else {
|
||||||
|
return messageEventContentFromMarkdownAsEmote(md: message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Force the timeline to load member details so it can populate sender profiles whenever we add a timeline listener
|
/// Force the timeline to load member details so it can populate sender profiles whenever we add a timeline listener
|
||||||
/// This should become automatic on the RustSDK side at some point
|
/// This should become automatic on the RustSDK side at some point
|
||||||
private func fetchMembers() async {
|
private func fetchMembers() async {
|
||||||
|
|||||||
+2
@@ -19,4 +19,6 @@ import UIKit
|
|||||||
struct EmoteRoomTimelineItemContent: Hashable {
|
struct EmoteRoomTimelineItemContent: Hashable {
|
||||||
let body: String
|
let body: String
|
||||||
var formattedBody: AttributedString?
|
var formattedBody: AttributedString?
|
||||||
|
/// The original textual representation of the formatted body directly from the event (usually HTML code)
|
||||||
|
var formattedBodyHTMLString: String?
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -558,7 +558,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
|||||||
formattedBody = attributedStringBuilder.fromPlain(L10n.commonEmote(name, messageContent.body))
|
formattedBody = attributedStringBuilder.fromPlain(L10n.commonEmote(name, messageContent.body))
|
||||||
}
|
}
|
||||||
|
|
||||||
return .init(body: messageContent.body, formattedBody: formattedBody)
|
return .init(body: messageContent.body, formattedBody: formattedBody, formattedBodyHTMLString: htmlBody)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - State Events
|
// MARK: - State Events
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
Implement /me
|
||||||
+1
-1
@@ -46,7 +46,7 @@ packages:
|
|||||||
# Element/Matrix dependencies
|
# Element/Matrix dependencies
|
||||||
MatrixRustSDK:
|
MatrixRustSDK:
|
||||||
url: https://github.com/matrix-org/matrix-rust-components-swift
|
url: https://github.com/matrix-org/matrix-rust-components-swift
|
||||||
exactVersion: 1.1.20
|
exactVersion: 1.1.21
|
||||||
# path: ../matrix-rust-sdk
|
# path: ../matrix-rust-sdk
|
||||||
DesignKit:
|
DesignKit:
|
||||||
path: DesignKit
|
path: DesignKit
|
||||||
|
|||||||
Reference in New Issue
Block a user