Commit 16824003 authored by Leonardo Aramaki's avatar Leonardo Aramaki

Honor UseRealName setting and apply most common system messages

parent e358a7c5
package chat.rocket.android.chatroom.presentation package chat.rocket.android.chatroom.presentation
import chat.rocket.android.chatroom.viewmodel.MessageViewModelMapper
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.server.domain.GetCurrentServerInteractor import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.GetSettingsInteractor import chat.rocket.android.server.domain.GetSettingsInteractor
...@@ -40,7 +41,8 @@ class ChatRoomPresenter @Inject constructor(private val view: ChatRoomView, ...@@ -40,7 +41,8 @@ class ChatRoomPresenter @Inject constructor(private val view: ChatRoomView,
synchronized(roomMessages) { synchronized(roomMessages) {
roomMessages.addAll(messages) roomMessages.addAll(messages)
} }
view.showMessages(messages, serverInteractor.get()!!, settings) val messagesViewModels = MessageViewModelMapper.mapToViewModelList(messages, settings)
view.showMessages(messagesViewModels, serverInteractor.get()!!)
} catch (ex: Exception) { } catch (ex: Exception) {
ex.printStackTrace() ex.printStackTrace()
ex.message?.let { ex.message?.let {
...@@ -106,15 +108,16 @@ class ChatRoomPresenter @Inject constructor(private val view: ChatRoomView, ...@@ -106,15 +108,16 @@ class ChatRoomPresenter @Inject constructor(private val view: ChatRoomView,
private fun updateMessage(streamedMessage: Message) { private fun updateMessage(streamedMessage: Message) {
launchUI(strategy) { launchUI(strategy) {
synchronized(roomMessages) { synchronized(roomMessages) {
val viewModelStreamedMessage = MessageViewModelMapper.mapToViewModel(streamedMessage, settings)
val index = roomMessages.indexOfFirst { msg -> msg.id == streamedMessage.id } val index = roomMessages.indexOfFirst { msg -> msg.id == streamedMessage.id }
if (index != -1) { if (index != -1) {
Timber.d("Updatind message at $index") Timber.d("Updatind message at $index")
roomMessages[index] = streamedMessage roomMessages[index] = streamedMessage
view.dispatchUpdateMessage(index, streamedMessage) view.dispatchUpdateMessage(index, viewModelStreamedMessage)
} else { } else {
Timber.d("Adding new message") Timber.d("Adding new message")
roomMessages.add(0, streamedMessage) roomMessages.add(0, streamedMessage)
view.showNewMessage(streamedMessage) view.showNewMessage(viewModelStreamedMessage)
} }
} }
} }
......
package chat.rocket.android.chatroom.presentation package chat.rocket.android.chatroom.presentation
import chat.rocket.android.chatroom.viewmodel.MessageViewModel
import chat.rocket.android.core.behaviours.LoadingView import chat.rocket.android.core.behaviours.LoadingView
import chat.rocket.android.core.behaviours.MessageView import chat.rocket.android.core.behaviours.MessageView
import chat.rocket.core.model.Message
import chat.rocket.core.model.Value
interface ChatRoomView : LoadingView, MessageView { interface ChatRoomView : LoadingView, MessageView {
...@@ -12,9 +11,8 @@ interface ChatRoomView : LoadingView, MessageView { ...@@ -12,9 +11,8 @@ interface ChatRoomView : LoadingView, MessageView {
* *
* @param dataSet The data set to show. * @param dataSet The data set to show.
* @param serverUrl The server URL. * @param serverUrl The server URL.
* @param settings The server settings.
*/ */
fun showMessages(dataSet: List<Message>, serverUrl: String, settings: Map<String, Value<Any>>?) fun showMessages(dataSet: List<MessageViewModel>, serverUrl: String)
/** /**
* Send a message to a chat room. * Send a message to a chat room.
...@@ -28,14 +26,14 @@ interface ChatRoomView : LoadingView, MessageView { ...@@ -28,14 +26,14 @@ interface ChatRoomView : LoadingView, MessageView {
* *
* @param message The (recent) message sent to a chat room. * @param message The (recent) message sent to a chat room.
*/ */
fun showNewMessage(message: Message) fun showNewMessage(message: MessageViewModel)
/** /**
* Dispatch a update to the recycler views adapter about a changed message. * Dispatch a update to the recycler views adapter about a changed message.
* *
* @param index The index of the changed message * @param index The index of the changed message
*/ */
fun dispatchUpdateMessage(index: Int, message: Message) fun dispatchUpdateMessage(index: Int, message: MessageViewModel)
fun disableMessageInput() fun disableMessageInput()
......
package chat.rocket.android.chatroom.ui package chat.rocket.android.chatroom.ui
import DateTimeHelper
import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.support.v7.widget.RecyclerView import android.support.v7.widget.RecyclerView
import android.text.Spannable
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.helper.UrlHelper import chat.rocket.android.chatroom.viewmodel.MessageViewModel
import chat.rocket.android.server.domain.USE_REALNAME
import chat.rocket.android.util.inflate import chat.rocket.android.util.inflate
import chat.rocket.android.util.setVisibility import chat.rocket.android.util.setVisibility
import chat.rocket.android.util.textContent
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
import chat.rocket.core.model.Message
import chat.rocket.core.model.MessageType
import chat.rocket.core.model.Value
import com.facebook.drawee.view.SimpleDraweeView import com.facebook.drawee.view.SimpleDraweeView
import kotlinx.android.synthetic.main.avatar.view.* import kotlinx.android.synthetic.main.avatar.view.*
import kotlinx.android.synthetic.main.item_message.view.* import kotlinx.android.synthetic.main.item_message.view.*
class ChatRoomAdapter(private val context: Context, class ChatRoomAdapter(private val serverUrl: String) : RecyclerView.Adapter<ChatRoomAdapter.ViewHolder>() {
private val serverUrl: String,
private val settings: Map<String, Value<Any>>?) : RecyclerView.Adapter<ChatRoomAdapter.ViewHolder>() {
init { init {
setHasStableIds(true) setHasStableIds(true)
} }
val dataSet = ArrayList<Message>() val dataSet = ArrayList<MessageViewModel>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder = ViewHolder(parent.inflate(R.layout.item_message)) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder =
ViewHolder(parent.inflate(R.layout.item_message), serverUrl)
override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(dataSet[position]) override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(dataSet[position])
...@@ -49,18 +34,18 @@ class ChatRoomAdapter(private val context: Context, ...@@ -49,18 +34,18 @@ class ChatRoomAdapter(private val context: Context,
override fun getItemViewType(position: Int): Int = position override fun getItemViewType(position: Int): Int = position
fun addDataSet(dataSet: List<Message>) { fun addDataSet(dataSet: List<MessageViewModel>) {
val previousDataSetSize = this.dataSet.size val previousDataSetSize = this.dataSet.size
this.dataSet.addAll(previousDataSetSize, dataSet) this.dataSet.addAll(previousDataSetSize, dataSet)
notifyItemRangeInserted(previousDataSetSize, dataSet.size) notifyItemRangeInserted(previousDataSetSize, dataSet.size)
} }
fun addItem(message: Message) { fun addItem(message: MessageViewModel) {
dataSet.add(0, message) dataSet.add(0, message)
notifyItemInserted(0) notifyItemInserted(0)
} }
fun updateItem(index: Int, message: Message) { fun updateItem(index: Int, message: MessageViewModel) {
dataSet[index] = message dataSet[index] = message
notifyItemChanged(index) notifyItemChanged(index)
} }
...@@ -69,73 +54,19 @@ class ChatRoomAdapter(private val context: Context, ...@@ -69,73 +54,19 @@ class ChatRoomAdapter(private val context: Context,
return dataSet[position].id.hashCode().toLong() return dataSet[position].id.hashCode().toLong()
} }
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { class ViewHolder(itemView: View, val serverUrl: String) : RecyclerView.ViewHolder(itemView) {
fun bind(message: Message) = with(itemView) { fun bind(message: MessageViewModel) = with(itemView) {
bindUserAvatar(message, image_avatar, image_unknown_avatar) bindUserAvatar(message, image_avatar, image_unknown_avatar)
bindUserName(message, text_user_name) text_user_name.text = message.sender
bindTime(message, text_message_time) text_message_time.text = message.time
bindContent(message, text_content) text_content.text = message.content
} }
private fun bindUserAvatar(message: Message, drawee: SimpleDraweeView, imageUnknownAvatar: ImageView) = message.sender?.username.let { private fun bindUserAvatar(message: MessageViewModel, drawee: SimpleDraweeView, imageUnknownAvatar: ImageView) = message.getAvatarUrl(serverUrl).let {
drawee.setImageURI(UrlHelper.getAvatarUrl(serverUrl, it.toString())) drawee.setImageURI(it.toString())
}.ifNull { }.ifNull {
imageUnknownAvatar.setVisibility(true) imageUnknownAvatar.setVisibility(true)
} }
private fun bindUserName(message: Message, textView: TextView) {
val useRealName = settings?.get(USE_REALNAME)?.value as Boolean
val username = message.sender?.username
val realName = message.sender?.name
val senderName = if (useRealName) realName else username
senderName.let {
// TODO: Fallback to username if real name happens to be null. ATM this could happen if the
// present message is a system message. We should handle that on the SDK
textView.textContent = if (senderName == null) username.toString() else it.toString()
}.ifNull {
textView.textContent = context.getString(R.string.msg_unknown)
}
}
private fun bindTime(message: Message, textView: TextView) {
textView.textContent = DateTimeHelper.getTime(DateTimeHelper.getLocalDateTime(message.timestamp))
}
private fun bindContent(message: Message, textView: TextView) {
when (message.type) {
//TODO: Add implementation for other types.
//TODO: Move all those strings to xml. Refer to https://github.com/RocketChat/Rocket.Chat.Android/blob/develop/app/src/main/res/values/system_message_strings.xml
MessageType.MESSAGE_REMOVED -> setSystemMessage(message, textView,
"Message removed")
MessageType.USER_JOINED -> setSystemMessage(message, textView,
"Has joined the channel.")
MessageType.USER_LEFT -> setSystemMessage(message, textView,
"Has left the channel.")
MessageType.USER_ADDED -> setSystemMessage(message, textView,
"User ${message.message} added by ${message.sender?.username}")
else -> textView.textContent = message.message
}
}
private fun setSystemMessage(message: Message, textView: TextView, msg: String) {
val spannableMsg = SpannableString(msg)
spannableMsg.setSpan(StyleSpan(Typeface.ITALIC), 0, spannableMsg.length,
0)
spannableMsg.setSpan(ForegroundColorSpan(Color.GRAY), 0, spannableMsg.length,
0)
if (message.type == MessageType.USER_ADDED) {
val userAddedStartIndex = 5
val userAddedLastIndex = userAddedStartIndex + message.message.length
val addedByStartIndex = userAddedLastIndex + 10
val addedByLastIndex = addedByStartIndex + message.sender?.username!!.length
spannableMsg.setSpan(StyleSpan(Typeface.BOLD_ITALIC), userAddedStartIndex, userAddedLastIndex,
0)
spannableMsg.setSpan(StyleSpan(Typeface.BOLD_ITALIC), addedByStartIndex, addedByLastIndex,
0)
}
textView.text = spannableMsg
}
} }
} }
\ No newline at end of file
...@@ -12,12 +12,11 @@ import android.widget.Toast ...@@ -12,12 +12,11 @@ import android.widget.Toast
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.chatroom.presentation.ChatRoomPresenter import chat.rocket.android.chatroom.presentation.ChatRoomPresenter
import chat.rocket.android.chatroom.presentation.ChatRoomView import chat.rocket.android.chatroom.presentation.ChatRoomView
import chat.rocket.android.chatroom.viewmodel.MessageViewModel
import chat.rocket.android.helper.EndlessRecyclerViewScrollListener import chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import chat.rocket.android.util.inflate import chat.rocket.android.util.inflate
import chat.rocket.android.util.setVisibility import chat.rocket.android.util.setVisibility
import chat.rocket.android.util.textContent import chat.rocket.android.util.textContent
import chat.rocket.core.model.Message
import chat.rocket.core.model.Value
import dagger.android.support.AndroidSupportInjection import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_chat_room.* import kotlinx.android.synthetic.main.fragment_chat_room.*
import kotlinx.android.synthetic.main.message_composer.* import kotlinx.android.synthetic.main.message_composer.*
...@@ -77,10 +76,10 @@ class ChatRoomFragment : Fragment(), ChatRoomView { ...@@ -77,10 +76,10 @@ class ChatRoomFragment : Fragment(), ChatRoomView {
super.onDestroyView() super.onDestroyView()
} }
override fun showMessages(dataSet: List<Message>, serverUrl: String, settings: Map<String, Value<Any>>?) { override fun showMessages(dataSet: List<MessageViewModel>, serverUrl: String) {
activity?.apply { activity?.apply {
if (recycler_view.adapter == null) { if (recycler_view.adapter == null) {
adapter = ChatRoomAdapter(this, serverUrl, settings) adapter = ChatRoomAdapter(serverUrl)
recycler_view.adapter = adapter recycler_view.adapter = adapter
val linearLayoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, true) val linearLayoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, true)
recycler_view.layoutManager = linearLayoutManager recycler_view.layoutManager = linearLayoutManager
...@@ -104,7 +103,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView { ...@@ -104,7 +103,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView {
} }
} }
override fun showNewMessage(message: Message) { override fun showNewMessage(message: MessageViewModel) {
text_message.textContent = "" text_message.textContent = ""
adapter.addItem(message) adapter.addItem(message)
recycler_view.smoothScrollToPosition(0) recycler_view.smoothScrollToPosition(0)
...@@ -121,7 +120,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView { ...@@ -121,7 +120,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView {
if (clear) text_message.textContent = "" if (clear) text_message.textContent = ""
} }
override fun dispatchUpdateMessage(index: Int, message: Message) { override fun dispatchUpdateMessage(index: Int, message: MessageViewModel) {
adapter.updateItem(index, message) adapter.updateItem(index, message)
} }
......
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