diff --git a/Sources/WysiwygComposer/Components/ComposerModelWrapper.swift b/Sources/WysiwygComposer/Components/ComposerModelWrapper.swift
index b132b03..039582f 100644
--- a/Sources/WysiwygComposer/Components/ComposerModelWrapper.swift
+++ b/Sources/WysiwygComposer/Components/ComposerModelWrapper.swift
@@ -21,7 +21,9 @@ protocol ComposerModelWrapperProtocol {
func setContentFromHtml(html: String) -> ComposerUpdate
func setContentFromMarkdown(markdown: String) -> ComposerUpdate
func getContentAsHtml() -> String
+ func getContentAsMessageHtml() -> String
func getContentAsMarkdown() -> String
+ func getContentAsMessageMarkdown() -> String
func getContentAsPlainText() -> String
func clear() -> ComposerUpdate
func select(startUtf16Codeunit: UInt32, endUtf16Codeunit: UInt32) -> ComposerUpdate
@@ -78,10 +80,18 @@ final class ComposerModelWrapper: ComposerModelWrapperProtocol {
model.getContentAsHtml()
}
+ func getContentAsMessageHtml() -> String {
+ model.getContentAsMessageHtml()
+ }
+
func getContentAsMarkdown() -> String {
model.getContentAsMarkdown()
}
+ func getContentAsMessageMarkdown() -> String {
+ model.getContentAsMessageMarkdown()
+ }
+
func getContentAsPlainText() -> String {
model.getContentAsPlainText()
}
@@ -129,6 +139,14 @@ final class ComposerModelWrapper: ComposerModelWrapperProtocol {
func insertMentionAtSuggestion(url: String, text: String, suggestion: SuggestionPattern, attributes: [Attribute]) -> ComposerUpdate {
execute { try $0.insertMentionAtSuggestion(url: url, text: text, suggestion: suggestion, attributes: attributes) }
}
+
+ func insertAtRoomMention() -> ComposerUpdate {
+ execute { try $0.insertAtRoomMention() }
+ }
+
+ func insertAtRoomMentionAtSuggestion(_ suggestion: SuggestionPattern) -> ComposerUpdate {
+ execute { try $0.insertAtRoomMentionAtSuggestion(suggestion: suggestion) }
+ }
func removeLinks() -> ComposerUpdate {
execute { try $0.removeLinks() }
diff --git a/Sources/WysiwygComposer/Components/WysiwygComposerView/WysiwygComposerViewModel.swift b/Sources/WysiwygComposer/Components/WysiwygComposerView/WysiwygComposerViewModel.swift
index 8fb7b65..486ff80 100644
--- a/Sources/WysiwygComposer/Components/WysiwygComposerView/WysiwygComposerViewModel.swift
+++ b/Sources/WysiwygComposer/Components/WysiwygComposerView/WysiwygComposerViewModel.swift
@@ -108,8 +108,8 @@ public class WysiwygComposerViewModel: WysiwygComposerViewModelProtocol, Observa
if plainTextMode {
_ = model.setContentFromMarkdown(markdown: computeMarkdownContent())
}
- return WysiwygComposerContent(markdown: model.getContentAsMarkdown(),
- html: model.getContentAsHtml())
+ return WysiwygComposerContent(markdown: model.getContentAsMessageMarkdown(),
+ html: model.getContentAsMessageHtml())
}
// MARK: - Private
@@ -251,6 +251,18 @@ public extension WysiwygComposerViewModel {
applyUpdate(update)
hasPendingFormats = true
}
+
+ /// Sets the @room mention at the suggestion position
+ func setAtRoomMention() {
+ let update: ComposerUpdate
+ if let suggestionPattern, suggestionPattern.key == .at {
+ update = model.insertAtRoomMentionAtSuggestion(suggestionPattern)
+ } else {
+ update = model.insertAtRoomMention()
+ }
+ applyUpdate(update)
+ hasPendingFormats = true
+ }
/// Set a command with `Slash` pattern.
///
diff --git a/Sources/WysiwygComposer/Components/WysiwygComposerView/WysiwygTextView.swift b/Sources/WysiwygComposer/Components/WysiwygComposerView/WysiwygTextView.swift
index 29f2c6c..c6a532a 100644
--- a/Sources/WysiwygComposer/Components/WysiwygComposerView/WysiwygTextView.swift
+++ b/Sources/WysiwygComposer/Components/WysiwygComposerView/WysiwygTextView.swift
@@ -41,7 +41,7 @@ protocol WysiwygTextViewDelegate: AnyObject {
}
/// A markdown protocol used to provide additional context to the text view when displaying mentions through the text attachment provider
-public protocol MentionDisplayHelper {}
+public protocol MentionDisplayHelper { }
public class WysiwygTextView: UITextView {
/// Internal delegate for the text view.
diff --git a/Tests/WysiwygComposerTests/Components/WysiwygComposerView/WysiwygComposerViewModelTests+Suggestions.swift b/Tests/WysiwygComposerTests/Components/WysiwygComposerView/WysiwygComposerViewModelTests+Suggestions.swift
index b323ec3..60266cf 100644
--- a/Tests/WysiwygComposerTests/Components/WysiwygComposerView/WysiwygComposerViewModelTests+Suggestions.swift
+++ b/Tests/WysiwygComposerTests/Components/WysiwygComposerView/WysiwygComposerViewModelTests+Suggestions.swift
@@ -54,7 +54,18 @@ extension WysiwygComposerViewModelTests {
XCTAssertEqual(
viewModel.content.html,
"""
- Alice\u{00A0}
+ Alice\u{00A0}
+ """
+ )
+ }
+
+ func testAtRoomSuggestionCanBeUsed() {
+ _ = viewModel.replaceText(range: .zero, replacementText: "@ro")
+ viewModel.setAtRoomMention()
+ XCTAssertEqual(
+ viewModel.content.html,
+ """
+ @room\u{00A0}
"""
)
}
@@ -68,10 +79,25 @@ extension WysiwygComposerViewModelTests {
XCTAssertEqual(
viewModel.content.html,
"""
- TextAlice\u{00A0}
+ TextAlice\u{00A0}
"""
)
}
+
+ func testAtRoomMentionWithNoSuggestion() {
+ _ = viewModel.replaceText(range: .zero, replacementText: "Text")
+ viewModel.select(range: .init(location: 0, length: 4))
+ viewModel.setAtRoomMention()
+ // Text is not removed, and the
+ // mention is added after the text
+ XCTAssertEqual(
+ viewModel.content.html,
+ """
+ Text@room\u{00A0}
+ """
+ )
+ }
+
func testAtMentionWithNoSuggestionAtLeading() {
_ = viewModel.replaceText(range: .zero, replacementText: "Text")
@@ -81,7 +107,20 @@ extension WysiwygComposerViewModelTests {
XCTAssertEqual(
viewModel.content.html,
"""
- AliceText
+ AliceText
+ """
+ )
+ }
+
+ func testAtRoomMentionWithNoSuggestionAtLeading() {
+ _ = viewModel.replaceText(range: .zero, replacementText: "Text")
+ viewModel.select(range: .init(location: 0, length: 0))
+ viewModel.setAtRoomMention()
+ // Text is not removed, and the mention is added before the text
+ XCTAssertEqual(
+ viewModel.content.html,
+ """
+ @roomText
"""
)
}
@@ -92,7 +131,7 @@ extension WysiwygComposerViewModelTests {
XCTAssertEqual(
viewModel.content.html,
"""
- Room 1\u{00A0}
+ #room1:matrix.org\u{00A0}
"""
)
}
@@ -104,7 +143,7 @@ extension WysiwygComposerViewModelTests {
XCTAssertEqual(
viewModel.content.html,
"""
- TextRoom 1\u{00A0}
+ Text#room1:matrix.org\u{00A0}
"""
)
}
@@ -116,7 +155,7 @@ extension WysiwygComposerViewModelTests {
XCTAssertEqual(
viewModel.content.html,
"""
- Room 1Text
+ #room1:matrix.orgText
"""
)
}
diff --git a/Tests/WysiwygComposerTests/WysiwygComposerTests+Suggestions.swift b/Tests/WysiwygComposerTests/WysiwygComposerTests+Suggestions.swift
index ab85e43..818df42 100644
--- a/Tests/WysiwygComposerTests/WysiwygComposerTests+Suggestions.swift
+++ b/Tests/WysiwygComposerTests/WysiwygComposerTests+Suggestions.swift
@@ -75,6 +75,40 @@ extension WysiwygComposerTests {
)
.assertSelection(start: 8, end: 8)
}
+
+ func testSuggestionForAtRoomPattern() {
+ let model = ComposerModelWrapper()
+ let update = model.replaceText(newText: "@roo")
+
+ guard case .suggestion(suggestionPattern: let suggestionPattern) = update.menuAction() else {
+ XCTFail("No user suggestion found")
+ return
+ }
+
+ model
+ .action {
+ $0.insertAtRoomMentionAtSuggestion(suggestionPattern)
+ }
+ .assertHtml("@room ")
+ .assertSelection(start: 2, end: 2)
+ }
+
+ func testForNonLeadingSuggestionForAtRoomPattern() {
+ let model = ComposerModelWrapper()
+ let update = model.replaceText(newText: "Hello @roo")
+
+ guard case .suggestion(suggestionPattern: let suggestionPattern) = update.menuAction() else {
+ XCTFail("No user suggestion found")
+ return
+ }
+
+ model
+ .action {
+ $0.insertAtRoomMentionAtSuggestion(suggestionPattern)
+ }
+ .assertHtml("Hello @room ")
+ .assertSelection(start: 8, end: 8)
+ }
func testSuggestionForHashPattern() {
let model = ComposerModelWrapper()