Commit ac013531 authored by Leonardo Aramaki's avatar Leonardo Aramaki

Show reply banner instead of the permalink on broadcast replies

parent 93abd163
...@@ -13,6 +13,7 @@ import chat.rocket.android.chatroom.viewmodel.suggestion.CommandSuggestionViewMo ...@@ -13,6 +13,7 @@ import chat.rocket.android.chatroom.viewmodel.suggestion.CommandSuggestionViewMo
import chat.rocket.android.chatroom.viewmodel.suggestion.PeopleSuggestionViewModel import chat.rocket.android.chatroom.viewmodel.suggestion.PeopleSuggestionViewModel
import chat.rocket.android.core.behaviours.showMessage import chat.rocket.android.core.behaviours.showMessage
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.helper.MessageHelper
import chat.rocket.android.helper.UserHelper import chat.rocket.android.helper.UserHelper
import chat.rocket.android.infrastructure.LocalRepository import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.server.domain.ChatRoomsInteractor import chat.rocket.android.server.domain.ChatRoomsInteractor
...@@ -40,6 +41,9 @@ import chat.rocket.common.model.roomTypeOf ...@@ -40,6 +41,9 @@ import chat.rocket.common.model.roomTypeOf
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
import chat.rocket.core.internal.realtime.setTypingStatus import chat.rocket.core.internal.realtime.setTypingStatus
import chat.rocket.core.internal.realtime.socket.model.State import chat.rocket.core.internal.realtime.socket.model.State
import chat.rocket.core.internal.realtime.subscribeTypingStatus
import chat.rocket.core.internal.realtime.unsubscribe
import chat.rocket.core.internal.rest.chatRoomRoles
import chat.rocket.core.internal.rest.commands import chat.rocket.core.internal.rest.commands
import chat.rocket.core.internal.rest.deleteMessage import chat.rocket.core.internal.rest.deleteMessage
import chat.rocket.core.internal.rest.getMembers import chat.rocket.core.internal.rest.getMembers
...@@ -52,13 +56,12 @@ import chat.rocket.core.internal.rest.pinMessage ...@@ -52,13 +56,12 @@ import chat.rocket.core.internal.rest.pinMessage
import chat.rocket.core.internal.rest.runCommand import chat.rocket.core.internal.rest.runCommand
import chat.rocket.core.internal.rest.sendMessage import chat.rocket.core.internal.rest.sendMessage
import chat.rocket.core.internal.rest.spotlight import chat.rocket.core.internal.rest.spotlight
import chat.rocket.core.internal.rest.starMessage
import chat.rocket.core.internal.rest.toggleReaction import chat.rocket.core.internal.rest.toggleReaction
import chat.rocket.core.internal.rest.unpinMessage import chat.rocket.core.internal.rest.unpinMessage
import chat.rocket.core.internal.rest.unstarMessage
import chat.rocket.core.internal.rest.updateMessage import chat.rocket.core.internal.rest.updateMessage
import chat.rocket.core.internal.rest.uploadFile import chat.rocket.core.internal.rest.uploadFile
import chat.rocket.core.internal.realtime.subscribeTypingStatus
import chat.rocket.core.internal.realtime.unsubscribe
import chat.rocket.core.internal.rest.*
import chat.rocket.core.model.ChatRoomRole import chat.rocket.core.model.ChatRoomRole
import chat.rocket.core.model.Command import chat.rocket.core.model.Command
import chat.rocket.core.model.Message import chat.rocket.core.model.Message
...@@ -87,6 +90,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -87,6 +90,7 @@ class ChatRoomPresenter @Inject constructor(
private val userHelper: UserHelper, private val userHelper: UserHelper,
private val mapper: ViewModelMapper, private val mapper: ViewModelMapper,
private val jobSchedulerInteractor: JobSchedulerInteractor, private val jobSchedulerInteractor: JobSchedulerInteractor,
private val messageHelper: MessageHelper,
getSettingsInteractor: GetSettingsInteractor, getSettingsInteractor: GetSettingsInteractor,
serverInteractor: GetCurrentServerInteractor, serverInteractor: GetCurrentServerInteractor,
factory: ConnectionManagerFactory factory: ConnectionManagerFactory
...@@ -107,7 +111,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -107,7 +111,7 @@ class ChatRoomPresenter @Inject constructor(
private var lastState = manager.state private var lastState = manager.state
private var typingStatusList = arrayListOf<String>() private var typingStatusList = arrayListOf<String>()
fun setupChatRoom(roomId: String, roomName: String, roomType: String) { fun setupChatRoom(roomId: String, roomName: String, roomType: String, chatRoomMessage: String? = null) {
launchUI(strategy) { launchUI(strategy) {
chatRoles = if (roomTypeOf(roomType) !is RoomType.DirectMessage) { chatRoles = if (roomTypeOf(roomType) !is RoomType.DirectMessage) {
client.chatRoomRoles(roomType = roomTypeOf(roomType), roomName = roomName) client.chatRoomRoles(roomType = roomTypeOf(roomType), roomName = roomName)
...@@ -118,6 +122,9 @@ class ChatRoomPresenter @Inject constructor( ...@@ -118,6 +122,9 @@ class ChatRoomPresenter @Inject constructor(
} ?: false } ?: false
view.onRoomUpdated(canPost, chatIsBroadcast) view.onRoomUpdated(canPost, chatIsBroadcast)
loadMessages(roomId, roomType) loadMessages(roomId, roomType)
chatRoomMessage?.let { messageHelper.messageIdFromPermalink(it) }?.let { messageId ->
citeMessage(roomName, messageHelper.roomTypeFromPermalink(chatRoomMessage)!!, messageId, true)
}
} }
} }
...@@ -427,7 +434,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -427,7 +434,7 @@ class ChatRoomPresenter @Inject constructor(
val username = msg.sender?.username ?: "" val username = msg.sender?.username ?: ""
val mention = if (mentionAuthor && me?.username != username) "@$username" else "" val mention = if (mentionAuthor && me?.username != username) "@$username" else ""
val room = if (roomTypeOf(roomType) is RoomType.DirectMessage) username else roomName val room = if (roomTypeOf(roomType) is RoomType.DirectMessage) username else roomName
val chatRoomType = when(roomTypeOf(roomType)) { val chatRoomType = when (roomTypeOf(roomType)) {
is RoomType.DirectMessage -> "direct" is RoomType.DirectMessage -> "direct"
is RoomType.PrivateGroup -> "group" is RoomType.PrivateGroup -> "group"
is RoomType.Channel -> "channel" is RoomType.Channel -> "channel"
...@@ -661,12 +668,11 @@ class ChatRoomPresenter @Inject constructor( ...@@ -661,12 +668,11 @@ class ChatRoomPresenter @Inject constructor(
} }
} }
fun openDirectMessage(roomName: String, permalink: String) { fun openDirectMessage(roomName: String, message: String) {
launchUI(strategy) { launchUI(strategy) {
try { try {
chatRoomsInteractor.getByName(currentServer, roomName)?.let { chatRoomsInteractor.getByName(currentServer, roomName)?.let {
val isDirectMessage = it.type is RoomType.DirectMessage if (it.type is RoomType.DirectMessage) {
if (isDirectMessage) {
navigator.toDirectMessage( navigator.toDirectMessage(
chatRoomId = it.id, chatRoomId = it.id,
chatRoomType = it.type.toString(), chatRoomType = it.type.toString(),
...@@ -675,7 +681,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -675,7 +681,7 @@ class ChatRoomPresenter @Inject constructor(
isChatRoomOwner = false, isChatRoomOwner = false,
isChatRoomReadOnly = false, isChatRoomReadOnly = false,
isChatRoomSubscribed = it.open, isChatRoomSubscribed = it.open,
chatRoomMessage = permalink chatRoomMessage = message
) )
} else { } else {
throw IllegalStateException("Not a direct-message") throw IllegalStateException("Not a direct-message")
......
...@@ -181,7 +181,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -181,7 +181,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
setupToolbar(chatRoomName) setupToolbar(chatRoomName)
presenter.setupChatRoom(chatRoomId, chatRoomName, chatRoomType) presenter.setupChatRoom(chatRoomId, chatRoomName, chatRoomType, chatRoomMessage)
presenter.loadChatRooms() presenter.loadChatRooms()
setupRecyclerView() setupRecyclerView()
setupFab() setupFab()
...@@ -660,10 +660,10 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -660,10 +660,10 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
button_join_chat.setVisible(true) button_join_chat.setVisible(true)
button_join_chat.setOnClickListener { presenter.joinChat(chatRoomId) } button_join_chat.setOnClickListener { presenter.joinChat(chatRoomId) }
} else { } else {
if (chatRoomMessage.orEmpty().isNotEmpty()) { // if (chatRoomMessage.orEmpty().isNotEmpty()) {
text_message.textContent = chatRoomMessage!! // text_message.textContent = chatRoomMessage!!
text_message.setSelection(chatRoomMessage!!.length) // text_message.setSelection(chatRoomMessage!!.length)
} // }
button_send.alpha = 0f button_send.alpha = 0f
button_send.setVisible(false) button_send.setVisible(false)
button_show_attachment_options.alpha = 1f button_show_attachment_options.alpha = 1f
...@@ -760,7 +760,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -760,7 +760,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
} }
setReactionButtonIcon(R.drawable.ic_keyboard_black_24dp) setReactionButtonIcon(R.drawable.ic_keyboard_black_24dp)
} else { } else {
// If popup is showing, simply dismiss it to show the undelying text keyboard // If popup is showing, simply dismiss it to show the underlying text keyboard
emojiKeyboardPopup.dismiss() emojiKeyboardPopup.dismiss()
setReactionButtonIcon(R.drawable.ic_reaction_24dp) setReactionButtonIcon(R.drawable.ic_reaction_24dp)
} }
......
...@@ -14,6 +14,7 @@ import androidx.core.text.color ...@@ -14,6 +14,7 @@ import androidx.core.text.color
import androidx.core.text.scale import androidx.core.text.scale
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.chatroom.domain.MessageReply import chat.rocket.android.chatroom.domain.MessageReply
import chat.rocket.android.helper.MessageHelper
import chat.rocket.android.helper.MessageParser import chat.rocket.android.helper.MessageParser
import chat.rocket.android.infrastructure.LocalRepository import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.server.domain.ChatRoomsInteractor import chat.rocket.android.server.domain.ChatRoomsInteractor
...@@ -25,9 +26,7 @@ import chat.rocket.android.server.domain.useRealName ...@@ -25,9 +26,7 @@ import chat.rocket.android.server.domain.useRealName
import chat.rocket.android.util.extensions.avatarUrl import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.isNotNullNorEmpty import chat.rocket.android.util.extensions.isNotNullNorEmpty
import chat.rocket.android.widget.emoji.EmojiParser import chat.rocket.android.widget.emoji.EmojiParser
import chat.rocket.common.model.RoomType
import chat.rocket.core.model.ChatRoom import chat.rocket.core.model.ChatRoom
import chat.rocket.core.model.ChatRoomRole
import chat.rocket.core.model.Message import chat.rocket.core.model.Message
import chat.rocket.core.model.MessageType import chat.rocket.core.model.MessageType
import chat.rocket.core.model.Value import chat.rocket.core.model.Value
...@@ -52,6 +51,7 @@ class ViewModelMapper @Inject constructor( ...@@ -52,6 +51,7 @@ class ViewModelMapper @Inject constructor(
private val context: Context, private val context: Context,
private val parser: MessageParser, private val parser: MessageParser,
private val roomsInteractor: ChatRoomsInteractor, private val roomsInteractor: ChatRoomsInteractor,
private val messageHelper: MessageHelper,
tokenRepository: TokenRepository, tokenRepository: TokenRepository,
serverInteractor: GetCurrentServerInteractor, serverInteractor: GetCurrentServerInteractor,
getSettingsInteractor: GetSettingsInteractor, getSettingsInteractor: GetSettingsInteractor,
...@@ -132,29 +132,18 @@ class ViewModelMapper @Inject constructor( ...@@ -132,29 +132,18 @@ class ViewModelMapper @Inject constructor(
val name = message.sender?.name val name = message.sender?.name
val roomName = if (settings.useRealName() && name != null) name else message.sender?.username val roomName = if (settings.useRealName() && name != null) name else message.sender?.username
?: "" ?: ""
val permalink = messageHelper.createPermalink(message, chatRoom)
return MessageReplyViewModel( return MessageReplyViewModel(
messageId = message.id, messageId = message.id,
isTemporary = false, isTemporary = false,
reactions = emptyList(), reactions = emptyList(),
message = message, message = message,
preview = mapMessagePreview(message), preview = mapMessagePreview(message),
rawData = MessageReply(roomName = roomName, permalink = makePermalink(message, chatRoom)), rawData = MessageReply(roomName = roomName, permalink = permalink),
nextDownStreamMessage = null nextDownStreamMessage = null
) )
} }
private fun makePermalink(message: Message, chatRoom: ChatRoom): String {
val type = when (chatRoom.type) {
is RoomType.PrivateGroup -> "group"
is RoomType.Channel -> "channel"
is RoomType.DirectMessage -> "direct"
is RoomType.Livechat -> "livechat"
else -> "custom"
}
val name = if (settings.useRealName()) chatRoom.fullName ?: chatRoom.name else chatRoom.name
return "[ ]($currentServer/$type/$name?msg=${message.id}) "
}
private fun mapUrl(message: Message, url: Url): BaseViewModel<*>? { private fun mapUrl(message: Message, url: Url): BaseViewModel<*>? {
if (url.ignoreParse || url.meta == null) return null if (url.ignoreParse || url.meta == null) return null
......
package chat.rocket.android.helper
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.GetSettingsInteractor
import chat.rocket.android.server.domain.PublicSettings
import chat.rocket.android.server.domain.useRealName
import chat.rocket.common.model.RoomType
import chat.rocket.core.model.ChatRoom
import chat.rocket.core.model.Message
import javax.inject.Inject
class MessageHelper @Inject constructor(
getSettingsInteractor: GetSettingsInteractor,
serverInteractor: GetCurrentServerInteractor
) {
private val currentServer = serverInteractor.get()!!
private val settings: PublicSettings = getSettingsInteractor.get(currentServer)
fun createPermalink(message: Message, chatRoom: ChatRoom): String {
val type = when (chatRoom.type) {
is RoomType.PrivateGroup -> "group"
is RoomType.Channel -> "channel"
is RoomType.DirectMessage -> "direct"
is RoomType.Livechat -> "livechat"
else -> "custom"
}
val name = if (settings.useRealName()) chatRoom.fullName ?: chatRoom.name else chatRoom.name
return "[ ]($currentServer/$type/$name?msg=${message.id}) "
}
fun messageIdFromPermalink(permalink: String): String? {
PERMALINK_REGEX.find(permalink.trim())?.let {
if (it.groupValues.size == 4) {
return it.groupValues[3]
}
}
return null
}
fun roomTypeFromPermalink(permalink: String): String? {
PERMALINK_REGEX.find(permalink.trim())?.let {
if (it.groupValues.size == 4) {
val type = it.groupValues[2]
return when(type) {
"group" -> "p"
"channel" -> "c"
"direct" -> "d"
"livechat" -> "l"
else -> type
}
}
}
return null
}
companion object {
val PERMALINK_REGEX = "(?:__|[*#])|\\[(.+?)\\]\\(.+?//.+?/(.+)/.+\\?.*=(.*)\\)".toRegex()
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment