diff --git a/Rocket.Chat/Controllers/Chat/MessagesComposerViewModel.swift b/Rocket.Chat/Controllers/Chat/MessagesComposerViewModel.swift index bd2659339e..a7f501c887 100644 --- a/Rocket.Chat/Controllers/Chat/MessagesComposerViewModel.swift +++ b/Rocket.Chat/Controllers/Chat/MessagesComposerViewModel.swift @@ -37,7 +37,7 @@ final class MessagesComposerViewModel { var replyMessageIdentifier = "" var messageToEdit: Message? - let hintPrefixes: [Character] = ["/", "#", "@", ":"] + let hintPrefixes: [Character] = ["/", "#", "@", ":", "+"] var hints: [Hint] = [] var hintPrefixedWord: String = "" @@ -56,6 +56,7 @@ final class MessagesComposerViewModel { } let word = String(word.dropFirst()) + let subprefix = word.first if prefix == "@" { hints = User.search( @@ -97,7 +98,7 @@ final class MessagesComposerViewModel { commands.forEach { hints.append(.command($0)) } - } else if prefix == ":" { + } else if prefix == ":" || (prefix == "+" && subprefix == ":") { let emojis = EmojiSearcher.standard.search(shortname: word.lowercased(), custom: CustomEmoji.emojis()) emojis.forEach { diff --git a/Rocket.Chat/Controllers/Chat/MessagesViewModel.swift b/Rocket.Chat/Controllers/Chat/MessagesViewModel.swift index aa1eee1b58..5c511eae12 100644 --- a/Rocket.Chat/Controllers/Chat/MessagesViewModel.swift +++ b/Rocket.Chat/Controllers/Chat/MessagesViewModel.swift @@ -882,6 +882,12 @@ extension MessagesViewModel { } client.runCommand(command: command, params: params, roomId: subscription.rid) + } else if let lastMessage = subscription.roomLastMessage, let emoji = text.reaction() { + guard let client = API.current()?.client(MessagesClient.self) else { + return Alert.defaultError.present() + } + + client.reactMessage(lastMessage, emoji: emoji) } else { guard let client = API.current()?.client(MessagesClient.self) else { return Alert.defaultError.present() diff --git a/Rocket.Chat/Extensions/StringExtensions.swift b/Rocket.Chat/Extensions/StringExtensions.swift index 727d6d3172..34f9359efd 100644 --- a/Rocket.Chat/Extensions/StringExtensions.swift +++ b/Rocket.Chat/Extensions/StringExtensions.swift @@ -138,6 +138,15 @@ extension String { return (command: command, params: params) } + func reaction() -> String? { + guard self.first == "+" && self.count > 1 else { return nil } + + let emoji = String(self.dropFirst()) + guard emoji.first == ":" && emoji.last == ":" else { return nil } + + return emoji + } + var boolValue: Bool { return NSString(string: self).boolValue } diff --git a/Rocket.Chat/External/RCEmojiKit/EmojiSearcher.swift b/Rocket.Chat/External/RCEmojiKit/EmojiSearcher.swift index f349d35698..462a00e6aa 100644 --- a/Rocket.Chat/External/RCEmojiKit/EmojiSearcher.swift +++ b/Rocket.Chat/External/RCEmojiKit/EmojiSearcher.swift @@ -19,6 +19,10 @@ open class EmojiSearcher { public func search(shortname: String, custom: [Emoji] = []) -> [EmojiSearchResult] { return (emojis + custom).compactMap { emoji -> EmojiSearchResult? in + if shortname.count == 0 { + return (emoji: emoji, suggestion: emoji.shortname) + } + if let suggestion = emoji.shortname.contains(shortname) ? emoji.shortname : emoji.alternates.filter({ $0.contains(shortname) }).first { return (emoji: emoji, suggestion: suggestion.contains(":") ? suggestion : ":\(suggestion):") } diff --git a/Rocket.ChatTests/Extensions/StringExtensionSpec.swift b/Rocket.ChatTests/Extensions/StringExtensionSpec.swift index f17e42854c..6527da68bc 100644 --- a/Rocket.ChatTests/Extensions/StringExtensionSpec.swift +++ b/Rocket.ChatTests/Extensions/StringExtensionSpec.swift @@ -146,4 +146,23 @@ class StringExtensionSpec: XCTestCase { XCTAssertNil(string2.commandAndParams()) } + + func testReaction() { + let string = "+:upside_down:" + + guard let emoji = string.reaction() else { + return XCTFail("string is valid reaction") + } + + XCTAssertEqual(emoji, ":upside_down:") + + let string2 = ":upside_down:" + XCTAssertNil(string2.reaction()) + + let string3 = "+upside_down:" + XCTAssertNil(string3.reaction()) + + let string4 = "+:upside_down" + XCTAssertNil(string4.reaction()) + } } diff --git a/Rocket.ChatTests/External/RCEmojiKit/EmojiSearcherSpec.swift b/Rocket.ChatTests/External/RCEmojiKit/EmojiSearcherSpec.swift index 42310912ff..6462eb0787 100644 --- a/Rocket.ChatTests/External/RCEmojiKit/EmojiSearcherSpec.swift +++ b/Rocket.ChatTests/External/RCEmojiKit/EmojiSearcherSpec.swift @@ -38,5 +38,12 @@ class EmojiSearcherSpec: XCTestCase { XCTAssert(search3.count == 1) XCTAssert(search3[0].emoji.shortname == ":thumbsup:") XCTAssert(search3[0].suggestion == ":+1:") + + let search4 = searcher.search(shortname: "") + XCTAssert(search4.count == 4) + XCTAssert(search4[0].emoji.shortname == ":smiley:") + XCTAssert(search4[1].emoji.shortname == ":thumbsup:") + XCTAssert(search4[2].emoji.shortname == ":sunglasses:") + XCTAssert(search4[3].emoji.shortname == ":radioactive:") } }