mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 01:20:12 +00:00
Reverting RTE to use SDK markdown when in markdown mode (#2327)
This commit is contained in:
@@ -267,8 +267,9 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID)
|
let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID)
|
||||||
let messageContent = messageEventContentFromMarkdown(md: replyText)
|
switch await roomProxy?.timeline.sendMessage(replyText,
|
||||||
switch await roomProxy?.timeline.sendMessageEventContent(messageContent) {
|
html: nil,
|
||||||
|
intentionalMentions: .empty) {
|
||||||
case .success:
|
case .success:
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -2487,12 +2487,12 @@ class TimelineProxyMock: TimelineProxyProtocol {
|
|||||||
var editMessageHtmlOriginalIntentionalMentionsCalled: Bool {
|
var editMessageHtmlOriginalIntentionalMentionsCalled: Bool {
|
||||||
return editMessageHtmlOriginalIntentionalMentionsCallsCount > 0
|
return editMessageHtmlOriginalIntentionalMentionsCallsCount > 0
|
||||||
}
|
}
|
||||||
var editMessageHtmlOriginalIntentionalMentionsReceivedArguments: (message: String, html: String, eventID: String, intentionalMentions: IntentionalMentions)?
|
var editMessageHtmlOriginalIntentionalMentionsReceivedArguments: (message: String, html: String?, eventID: String, intentionalMentions: IntentionalMentions)?
|
||||||
var editMessageHtmlOriginalIntentionalMentionsReceivedInvocations: [(message: String, html: String, eventID: String, intentionalMentions: IntentionalMentions)] = []
|
var editMessageHtmlOriginalIntentionalMentionsReceivedInvocations: [(message: String, html: String?, eventID: String, intentionalMentions: IntentionalMentions)] = []
|
||||||
var editMessageHtmlOriginalIntentionalMentionsReturnValue: Result<Void, TimelineProxyError>!
|
var editMessageHtmlOriginalIntentionalMentionsReturnValue: Result<Void, TimelineProxyError>!
|
||||||
var editMessageHtmlOriginalIntentionalMentionsClosure: ((String, String, String, IntentionalMentions) async -> Result<Void, TimelineProxyError>)?
|
var editMessageHtmlOriginalIntentionalMentionsClosure: ((String, String?, String, IntentionalMentions) async -> Result<Void, TimelineProxyError>)?
|
||||||
|
|
||||||
func editMessage(_ message: String, html: String, original eventID: String, intentionalMentions: IntentionalMentions) async -> Result<Void, TimelineProxyError> {
|
func editMessage(_ message: String, html: String?, original eventID: String, intentionalMentions: IntentionalMentions) async -> Result<Void, TimelineProxyError> {
|
||||||
editMessageHtmlOriginalIntentionalMentionsCallsCount += 1
|
editMessageHtmlOriginalIntentionalMentionsCallsCount += 1
|
||||||
editMessageHtmlOriginalIntentionalMentionsReceivedArguments = (message: message, html: html, eventID: eventID, intentionalMentions: intentionalMentions)
|
editMessageHtmlOriginalIntentionalMentionsReceivedArguments = (message: message, html: html, eventID: eventID, intentionalMentions: intentionalMentions)
|
||||||
editMessageHtmlOriginalIntentionalMentionsReceivedInvocations.append((message: message, html: html, eventID: eventID, intentionalMentions: intentionalMentions))
|
editMessageHtmlOriginalIntentionalMentionsReceivedInvocations.append((message: message, html: html, eventID: eventID, intentionalMentions: intentionalMentions))
|
||||||
@@ -2767,12 +2767,12 @@ class TimelineProxyMock: TimelineProxyProtocol {
|
|||||||
var sendMessageHtmlInReplyToIntentionalMentionsCalled: Bool {
|
var sendMessageHtmlInReplyToIntentionalMentionsCalled: Bool {
|
||||||
return sendMessageHtmlInReplyToIntentionalMentionsCallsCount > 0
|
return sendMessageHtmlInReplyToIntentionalMentionsCallsCount > 0
|
||||||
}
|
}
|
||||||
var sendMessageHtmlInReplyToIntentionalMentionsReceivedArguments: (message: String, html: String, eventID: String?, intentionalMentions: IntentionalMentions)?
|
var sendMessageHtmlInReplyToIntentionalMentionsReceivedArguments: (message: String, html: String?, eventID: String?, intentionalMentions: IntentionalMentions)?
|
||||||
var sendMessageHtmlInReplyToIntentionalMentionsReceivedInvocations: [(message: String, html: String, eventID: String?, intentionalMentions: IntentionalMentions)] = []
|
var sendMessageHtmlInReplyToIntentionalMentionsReceivedInvocations: [(message: String, html: String?, eventID: String?, intentionalMentions: IntentionalMentions)] = []
|
||||||
var sendMessageHtmlInReplyToIntentionalMentionsReturnValue: Result<Void, TimelineProxyError>!
|
var sendMessageHtmlInReplyToIntentionalMentionsReturnValue: Result<Void, TimelineProxyError>!
|
||||||
var sendMessageHtmlInReplyToIntentionalMentionsClosure: ((String, String, String?, IntentionalMentions) async -> Result<Void, TimelineProxyError>)?
|
var sendMessageHtmlInReplyToIntentionalMentionsClosure: ((String, String?, String?, IntentionalMentions) async -> Result<Void, TimelineProxyError>)?
|
||||||
|
|
||||||
func sendMessage(_ message: String, html: String, inReplyTo eventID: String?, intentionalMentions: IntentionalMentions) async -> Result<Void, TimelineProxyError> {
|
func sendMessage(_ message: String, html: String?, inReplyTo eventID: String?, intentionalMentions: IntentionalMentions) async -> Result<Void, TimelineProxyError> {
|
||||||
sendMessageHtmlInReplyToIntentionalMentionsCallsCount += 1
|
sendMessageHtmlInReplyToIntentionalMentionsCallsCount += 1
|
||||||
sendMessageHtmlInReplyToIntentionalMentionsReceivedArguments = (message: message, html: html, eventID: eventID, intentionalMentions: intentionalMentions)
|
sendMessageHtmlInReplyToIntentionalMentionsReceivedArguments = (message: message, html: html, eventID: eventID, intentionalMentions: intentionalMentions)
|
||||||
sendMessageHtmlInReplyToIntentionalMentionsReceivedInvocations.append((message: message, html: html, eventID: eventID, intentionalMentions: intentionalMentions))
|
sendMessageHtmlInReplyToIntentionalMentionsReceivedInvocations.append((message: message, html: html, eventID: eventID, intentionalMentions: intentionalMentions))
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ enum ComposerToolbarVoiceMessageAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum ComposerToolbarViewModelAction {
|
enum ComposerToolbarViewModelAction {
|
||||||
case sendMessage(plain: String, html: String, mode: RoomScreenComposerMode, intentionalMentions: IntentionalMentions)
|
case sendMessage(plain: String, html: String?, mode: RoomScreenComposerMode, intentionalMentions: IntentionalMentions)
|
||||||
case attach(ComposerAttachmentType)
|
case attach(ComposerAttachmentType)
|
||||||
|
|
||||||
case handlePasteOrDrop(provider: NSItemProvider)
|
case handlePasteOrDrop(provider: NSItemProvider)
|
||||||
|
|||||||
@@ -87,11 +87,15 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
|
|||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
|
||||||
appSettings.$richTextEditorEnabled
|
|
||||||
.map { !$0 }
|
|
||||||
.assign(to: &wysiwygViewModel.$plainTextMode)
|
|
||||||
|
|
||||||
completionSuggestionService.suggestionsPublisher
|
completionSuggestionService.suggestionsPublisher
|
||||||
|
.combineLatest(appSettings.$richTextEditorEnabled)
|
||||||
|
.map { suggestions, richTextEditorEnabled in
|
||||||
|
// We ignore user suggestions when RTE is disabled since mentions would not work
|
||||||
|
guard richTextEditorEnabled else {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return suggestions
|
||||||
|
}
|
||||||
.weakAssign(to: \.state.suggestions, on: self)
|
.weakAssign(to: \.state.suggestions, on: self)
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
|
||||||
@@ -111,8 +115,9 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
|
|||||||
case .previewVoiceMessage:
|
case .previewVoiceMessage:
|
||||||
actionsSubject.send(.voiceMessage(.send))
|
actionsSubject.send(.voiceMessage(.send))
|
||||||
default:
|
default:
|
||||||
|
let sendHTML = appSettings.richTextEditorEnabled
|
||||||
actionsSubject.send(.sendMessage(plain: wysiwygViewModel.content.markdown,
|
actionsSubject.send(.sendMessage(plain: wysiwygViewModel.content.markdown,
|
||||||
html: wysiwygViewModel.content.html,
|
html: sendHTML ? wysiwygViewModel.content.html : nil,
|
||||||
mode: state.composerMode,
|
mode: state.composerMode,
|
||||||
intentionalMentions: wysiwygViewModel
|
intentionalMentions: wysiwygViewModel
|
||||||
.getMentionsState()
|
.getMentionsState()
|
||||||
|
|||||||
@@ -461,7 +461,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
|||||||
state.showLoading = false
|
state.showLoading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
private func sendCurrentMessage(_ message: String, html: String, mode: RoomScreenComposerMode, intentionalMentions: IntentionalMentions) async {
|
private func sendCurrentMessage(_ message: String, html: String?, mode: RoomScreenComposerMode, intentionalMentions: IntentionalMentions) async {
|
||||||
guard !message.isEmpty else {
|
guard !message.isEmpty else {
|
||||||
fatalError("This message should never be empty")
|
fatalError("This message should never be empty")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ struct IntentionalMentions: Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension IntentionalMentions {
|
extension IntentionalMentions {
|
||||||
|
static var empty: Self {
|
||||||
|
IntentionalMentions(userIDs: .init(), atRoom: false)
|
||||||
|
}
|
||||||
|
|
||||||
func toRustMentions() -> Mentions {
|
func toRustMentions() -> Mentions {
|
||||||
Mentions(userIds: Array(userIDs), room: atRoom)
|
Mentions(userIds: Array(userIDs), room: atRoom)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -70,14 +70,14 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {
|
|||||||
func processItemDisappearance(_ itemID: TimelineItemIdentifier) async { }
|
func processItemDisappearance(_ itemID: TimelineItemIdentifier) async { }
|
||||||
|
|
||||||
func sendMessage(_ message: String,
|
func sendMessage(_ message: String,
|
||||||
html: String,
|
html: String?,
|
||||||
inReplyTo itemID: TimelineItemIdentifier?,
|
inReplyTo itemID: TimelineItemIdentifier?,
|
||||||
intentionalMentions: IntentionalMentions) async { }
|
intentionalMentions: IntentionalMentions) async { }
|
||||||
|
|
||||||
func toggleReaction(_ reaction: String, to itemID: TimelineItemIdentifier) async { }
|
func toggleReaction(_ reaction: String, to itemID: TimelineItemIdentifier) async { }
|
||||||
|
|
||||||
func editMessage(_ newMessage: String,
|
func editMessage(_ newMessage: String,
|
||||||
html: String,
|
html: String?,
|
||||||
original itemID: TimelineItemIdentifier,
|
original itemID: TimelineItemIdentifier,
|
||||||
intentionalMentions: IntentionalMentions) async { }
|
intentionalMentions: IntentionalMentions) async { }
|
||||||
|
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
|||||||
func processItemDisappearance(_ itemID: TimelineItemIdentifier) { }
|
func processItemDisappearance(_ itemID: TimelineItemIdentifier) { }
|
||||||
|
|
||||||
func sendMessage(_ message: String,
|
func sendMessage(_ message: String,
|
||||||
html: String,
|
html: String?,
|
||||||
inReplyTo itemID: TimelineItemIdentifier?,
|
inReplyTo itemID: TimelineItemIdentifier?,
|
||||||
intentionalMentions: IntentionalMentions) async {
|
intentionalMentions: IntentionalMentions) async {
|
||||||
var inReplyTo: String?
|
var inReplyTo: String?
|
||||||
@@ -155,7 +155,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func editMessage(_ newMessage: String,
|
func editMessage(_ newMessage: String,
|
||||||
html: String,
|
html: String?,
|
||||||
original itemID: TimelineItemIdentifier,
|
original itemID: TimelineItemIdentifier,
|
||||||
intentionalMentions: IntentionalMentions) async {
|
intentionalMentions: IntentionalMentions) async {
|
||||||
MXLog.info("Edit message in \(roomID)")
|
MXLog.info("Edit message in \(roomID)")
|
||||||
|
|||||||
+3
-3
@@ -52,12 +52,12 @@ protocol RoomTimelineControllerProtocol {
|
|||||||
func sendReadReceipt(for itemID: TimelineItemIdentifier) async -> Result<Void, RoomTimelineControllerError>
|
func sendReadReceipt(for itemID: TimelineItemIdentifier) async -> Result<Void, RoomTimelineControllerError>
|
||||||
|
|
||||||
func sendMessage(_ message: String,
|
func sendMessage(_ message: String,
|
||||||
html: String,
|
html: String?,
|
||||||
inReplyTo itemID: TimelineItemIdentifier?,
|
inReplyTo itemID: TimelineItemIdentifier?,
|
||||||
intentionalMentions: IntentionalMentions) async
|
intentionalMentions: IntentionalMentions) async
|
||||||
|
|
||||||
func editMessage(_ newMessage: String,
|
func editMessage(_ newMessage: String,
|
||||||
html: String,
|
html: String?,
|
||||||
original itemID: TimelineItemIdentifier,
|
original itemID: TimelineItemIdentifier,
|
||||||
intentionalMentions: IntentionalMentions) async
|
intentionalMentions: IntentionalMentions) async
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ protocol RoomTimelineControllerProtocol {
|
|||||||
|
|
||||||
extension RoomTimelineControllerProtocol {
|
extension RoomTimelineControllerProtocol {
|
||||||
func sendMessage(_ message: String,
|
func sendMessage(_ message: String,
|
||||||
html: String,
|
html: String?,
|
||||||
intentionalMentions: IntentionalMentions) async {
|
intentionalMentions: IntentionalMentions) async {
|
||||||
await sendMessage(message,
|
await sendMessage(message,
|
||||||
html: html,
|
html: html,
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ final class TimelineProxy: TimelineProxyProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func editMessage(_ message: String,
|
func editMessage(_ message: String,
|
||||||
html: String,
|
html: String?,
|
||||||
original eventID: String,
|
original eventID: String,
|
||||||
intentionalMentions: IntentionalMentions) async -> Result<Void, TimelineProxyError> {
|
intentionalMentions: IntentionalMentions) async -> Result<Void, TimelineProxyError> {
|
||||||
MXLog.info("Editing message with original event ID: \(eventID)")
|
MXLog.info("Editing message with original event ID: \(eventID)")
|
||||||
@@ -390,7 +390,7 @@ final class TimelineProxy: TimelineProxyProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func sendMessage(_ message: String,
|
func sendMessage(_ message: String,
|
||||||
html: String,
|
html: String?,
|
||||||
inReplyTo eventID: String? = nil,
|
inReplyTo eventID: String? = nil,
|
||||||
intentionalMentions: IntentionalMentions) async -> Result<Void, TimelineProxyError> {
|
intentionalMentions: IntentionalMentions) async -> Result<Void, TimelineProxyError> {
|
||||||
if let eventID {
|
if let eventID {
|
||||||
@@ -573,7 +573,7 @@ final class TimelineProxy: TimelineProxyProtocol {
|
|||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
|
|
||||||
private func buildMessageContentFor(_ message: String,
|
private func buildMessageContentFor(_ message: String,
|
||||||
html: String,
|
html: String?,
|
||||||
intentionalMentions: Mentions) -> RoomMessageEventContentWithoutRelation {
|
intentionalMentions: Mentions) -> RoomMessageEventContentWithoutRelation {
|
||||||
let emoteSlashCommand = "/me "
|
let emoteSlashCommand = "/me "
|
||||||
let isEmote: Bool = message.starts(with: emoteSlashCommand)
|
let isEmote: Bool = message.starts(with: emoteSlashCommand)
|
||||||
@@ -581,10 +581,18 @@ final class TimelineProxy: TimelineProxyProtocol {
|
|||||||
let content: RoomMessageEventContentWithoutRelation
|
let content: RoomMessageEventContentWithoutRelation
|
||||||
if isEmote {
|
if isEmote {
|
||||||
let emoteMessage = String(message.dropFirst(emoteSlashCommand.count))
|
let emoteMessage = String(message.dropFirst(emoteSlashCommand.count))
|
||||||
let emoteHtml = String(html.dropFirst(emoteSlashCommand.count))
|
|
||||||
|
var emoteHtml: String?
|
||||||
|
if let html {
|
||||||
|
emoteHtml = String(html.dropFirst(emoteSlashCommand.count))
|
||||||
|
}
|
||||||
content = buildEmoteMessageContentFor(emoteMessage, html: emoteHtml)
|
content = buildEmoteMessageContentFor(emoteMessage, html: emoteHtml)
|
||||||
} else {
|
} else {
|
||||||
content = messageEventContentFromHtml(body: message, htmlBody: html)
|
if let html {
|
||||||
|
content = messageEventContentFromHtml(body: message, htmlBody: html)
|
||||||
|
} else {
|
||||||
|
content = messageEventContentFromMarkdown(md: message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return content.withMentions(mentions: intentionalMentions)
|
return content.withMentions(mentions: intentionalMentions)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ protocol TimelineProxyProtocol {
|
|||||||
func cancelSend(transactionID: String) async
|
func cancelSend(transactionID: String) async
|
||||||
|
|
||||||
func editMessage(_ message: String,
|
func editMessage(_ message: String,
|
||||||
html: String,
|
html: String?,
|
||||||
original eventID: String,
|
original eventID: String,
|
||||||
intentionalMentions: IntentionalMentions) async -> Result<Void, TimelineProxyError>
|
intentionalMentions: IntentionalMentions) async -> Result<Void, TimelineProxyError>
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ protocol TimelineProxyProtocol {
|
|||||||
func sendMessageEventContent(_ messageContent: RoomMessageEventContentWithoutRelation) async -> Result<Void, TimelineProxyError>
|
func sendMessageEventContent(_ messageContent: RoomMessageEventContentWithoutRelation) async -> Result<Void, TimelineProxyError>
|
||||||
|
|
||||||
func sendMessage(_ message: String,
|
func sendMessage(_ message: String,
|
||||||
html: String,
|
html: String?,
|
||||||
inReplyTo eventID: String?,
|
inReplyTo eventID: String?,
|
||||||
intentionalMentions: IntentionalMentions) async -> Result<Void, TimelineProxyError>
|
intentionalMentions: IntentionalMentions) async -> Result<Void, TimelineProxyError>
|
||||||
|
|
||||||
@@ -125,3 +125,14 @@ protocol TimelineProxyProtocol {
|
|||||||
|
|
||||||
func sendPollResponse(pollStartID: String, answers: [String]) async -> Result<Void, TimelineProxyError>
|
func sendPollResponse(pollStartID: String, answers: [String]) async -> Result<Void, TimelineProxyError>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension TimelineProxyProtocol {
|
||||||
|
func sendMessage(_ message: String,
|
||||||
|
html: String?,
|
||||||
|
intentionalMentions: IntentionalMentions) async -> Result<Void, TimelineProxyError> {
|
||||||
|
await sendMessage(message,
|
||||||
|
html: html,
|
||||||
|
inReplyTo: nil,
|
||||||
|
intentionalMentions: intentionalMentions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -179,4 +179,18 @@ class ComposerToolbarViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
try await deferred.fulfill()
|
try await deferred.fulfill()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testSuggestionsAreIgnoredWhenRTEDisabled() async throws {
|
||||||
|
appSettings.richTextEditorEnabled = false
|
||||||
|
let suggestions: [SuggestionItem] = [.user(item: MentionSuggestionItem(id: "@user_mention_1:matrix.org", displayName: "User 1", avatarURL: nil)),
|
||||||
|
.user(item: MentionSuggestionItem(id: "@user_mention_2:matrix.org", displayName: "User 2", avatarURL: URL.documentsDirectory))]
|
||||||
|
let mockCompletionSuggestionService = CompletionSuggestionServiceMock(configuration: .init(suggestions: suggestions))
|
||||||
|
viewModel = ComposerToolbarViewModel(wysiwygViewModel: wysiwygViewModel,
|
||||||
|
completionSuggestionService: mockCompletionSuggestionService,
|
||||||
|
mediaProvider: MockMediaProvider(),
|
||||||
|
appSettings: ServiceLocator.shared.settings,
|
||||||
|
mentionDisplayHelper: ComposerMentionDisplayHelper.mock)
|
||||||
|
|
||||||
|
XCTAssertEqual(viewModel.state.suggestions, [])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
Improved plain text mode stability.
|
||||||
Reference in New Issue
Block a user