Commit 65434c1d authored by Leonardo Aramaki's avatar Leonardo Aramaki

Add a preview message to all viewmodels with a summarized content of the...

Add a preview message to all viewmodels with a summarized content of the original message to fit properly in places like replies, quotes or the main chat list
parent 202c69db
......@@ -288,7 +288,7 @@ class ChatRoomPresenter @Inject constructor(private val view: ChatRoomView,
view.showReplyingAction(
username = user,
replyMarkdown = "[ ]($serverUrl/$room/$roomName?msg=$id) $mention ",
quotedMessage = m.message
quotedMessage = mapper.map(message).last().preview?.message ?: ""
)
}
}
......
......@@ -12,8 +12,9 @@ data class AudioAttachmentViewModel(
override val attachmentTitle: CharSequence,
override val id: Long,
override var reactions: List<ReactionViewModel>,
override var nextDownStreamMessage: BaseViewModel<*>? = null
) : BaseFileAttachmentViewModel<AudioAttachment> {
override var nextDownStreamMessage: BaseViewModel<*>? = null,
override var preview: Message? = null
) : BaseFileAttachmentViewModel<AudioAttachment> {
override val viewType: Int
get() = BaseViewModel.ViewType.AUDIO_ATTACHMENT.viewType
override val layoutId: Int
......
......@@ -11,6 +11,7 @@ interface BaseViewModel<out T> {
val layoutId: Int
var reactions: List<ReactionViewModel>
var nextDownStreamMessage: BaseViewModel<*>?
var preview: Message?
enum class ViewType(val viewType: Int) {
MESSAGE(0),
......
......@@ -12,7 +12,8 @@ data class ImageAttachmentViewModel(
override val attachmentTitle: CharSequence,
override val id: Long,
override var reactions: List<ReactionViewModel>,
override var nextDownStreamMessage: BaseViewModel<*>? = null
override var nextDownStreamMessage: BaseViewModel<*>? = null,
override var preview: Message? = null
) : BaseFileAttachmentViewModel<ImageAttachment> {
override val viewType: Int
get() = BaseViewModel.ViewType.IMAGE_ATTACHMENT.viewType
......
......@@ -13,7 +13,8 @@ data class MessageAttachmentViewModel(
val isPinned: Boolean,
override var reactions: List<ReactionViewModel>,
override var nextDownStreamMessage: BaseViewModel<*>? = null,
var messageLink: String? = null
var messageLink: String? = null,
override var preview: Message? = null
) : BaseViewModel<Message> {
override val viewType: Int
get() = BaseViewModel.ViewType.MESSAGE_ATTACHMENT.viewType
......
......@@ -14,6 +14,7 @@ data class MessageViewModel(
override val isPinned: Boolean,
override var reactions: List<ReactionViewModel>,
override var nextDownStreamMessage: BaseViewModel<*>? = null,
override var preview: Message? = null,
var isFirstUnread: Boolean
) : BaseMessageViewModel<Message> {
override val viewType: Int
......
......@@ -13,7 +13,8 @@ data class UrlPreviewViewModel(
val description: CharSequence?,
val thumbUrl: String?,
override var reactions: List<ReactionViewModel>,
override var nextDownStreamMessage: BaseViewModel<*>? = null
override var nextDownStreamMessage: BaseViewModel<*>? = null,
override var preview: Message? = null
) : BaseViewModel<Url> {
override val viewType: Int
get() = BaseViewModel.ViewType.URL_PREVIEW.viewType
......
......@@ -12,7 +12,8 @@ data class VideoAttachmentViewModel(
override val attachmentTitle: CharSequence,
override val id: Long,
override var reactions: List<ReactionViewModel>,
override var nextDownStreamMessage: BaseViewModel<*>? = null
override var nextDownStreamMessage: BaseViewModel<*>? = null,
override var preview: Message? = null
) : BaseFileAttachmentViewModel<VideoAttachment> {
override val viewType: Int
get() = BaseViewModel.ViewType.VIDEO_ATTACHMENT.viewType
......
......@@ -11,7 +11,10 @@ import chat.rocket.android.R
import chat.rocket.android.helper.MessageParser
import chat.rocket.android.helper.UrlHelper
import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.server.domain.*
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.GetSettingsInteractor
import chat.rocket.android.server.domain.baseUrl
import chat.rocket.android.server.domain.useRealName
import chat.rocket.android.widget.emoji.EmojiParser
import chat.rocket.core.TokenRepository
import chat.rocket.core.model.Message
......@@ -28,7 +31,6 @@ import javax.inject.Inject
class ViewModelMapper @Inject constructor(private val context: Context,
private val parser: MessageParser,
private val messagesRepository: MessagesRepository,
tokenRepository: TokenRepository,
localRepository: LocalRepository,
serverInteractor: GetCurrentServerInteractor,
......@@ -67,6 +69,7 @@ class ViewModelMapper @Inject constructor(private val context: Context,
}
mapMessage(message).let {
if (list.size > 0) { it.preview = list[0].preview }
list.add(it)
}
......@@ -87,10 +90,10 @@ class ViewModelMapper @Inject constructor(private val context: Context,
val description = url.meta?.description
return UrlPreviewViewModel(message, url, message.id, title, hostname, description, thumb,
getReactions(message))
getReactions(message), preview = message.copy(message = url.url))
}
private fun mapAttachment(message: Message, attachment: Attachment): BaseViewModel<*>? {
private suspend fun mapAttachment(message: Message, attachment: Attachment): BaseViewModel<*>? {
return when (attachment) {
is FileAttachment -> mapFileAttachment(message, attachment)
is MessageAttachment -> mapMessageAttachment(message, attachment)
......@@ -98,19 +101,20 @@ class ViewModelMapper @Inject constructor(private val context: Context,
}
}
private fun mapMessageAttachment(message: Message, attachment: MessageAttachment): MessageAttachmentViewModel {
private suspend fun mapMessageAttachment(message: Message, attachment: MessageAttachment): MessageAttachmentViewModel {
val attachmentAuthor = attachment.author!!
val time = getTime(attachment.timestamp!!)
val attachmentText = when (attachment.attachments.orEmpty().firstOrNull()) {
is ImageAttachment -> context.getString(R.string.msg_quote_photo)
is VideoAttachment -> context.getString(R.string.msg_quote_video)
is AudioAttachment -> context.getString(R.string.msg_quote_audio)
is ImageAttachment -> context.getString(R.string.msg_preview_photo)
is VideoAttachment -> context.getString(R.string.msg_preview_video)
is AudioAttachment -> context.getString(R.string.msg_preview_audio)
else -> attachment.text ?: ""
}
return MessageAttachmentViewModel(message = getMessageWithoutQuoteMarkdown(message), rawData = message,
val content = stripMessageQuotes(message)
return MessageAttachmentViewModel(message = content, rawData = message,
messageId = message.id, time = time, senderName = attachmentAuthor,
content = attachmentText, isPinned = message.pinned, reactions = getReactions(message))
content = attachmentText, isPinned = message.pinned, reactions = getReactions(message),
preview = message.copy(message = content.message))
}
private fun mapFileAttachment(message: Message, attachment: FileAttachment): BaseViewModel<*>? {
......@@ -119,11 +123,14 @@ class ViewModelMapper @Inject constructor(private val context: Context,
val id = attachmentId(message, attachment)
return when (attachment) {
is ImageAttachment -> ImageAttachmentViewModel(message, attachment, message.id,
attachmentUrl, attachmentTitle, id, getReactions(message))
attachmentUrl, attachmentTitle, id, getReactions(message),
preview = message.copy(message = context.getString(R.string.msg_preview_photo)))
is VideoAttachment -> VideoAttachmentViewModel(message, attachment, message.id,
attachmentUrl, attachmentTitle, id, getReactions(message))
attachmentUrl, attachmentTitle, id, getReactions(message),
preview = message.copy(message = context.getString(R.string.msg_preview_video)))
is AudioAttachment -> AudioAttachmentViewModel(message, attachment, message.id,
attachmentUrl, attachmentTitle, id, getReactions(message))
attachmentUrl, attachmentTitle, id, getReactions(message),
preview = message.copy(message = context.getString(R.string.msg_preview_audio)))
else -> null
}
}
......@@ -167,12 +174,20 @@ class ViewModelMapper @Inject constructor(private val context: Context,
val sender = getSenderName(message)
val time = getTime(message.timestamp)
val avatar = getUserAvatar(message)
val preview = mapMessagePreview(message)
val content = getContent(context, getMessageWithoutQuoteMarkdown(message))
MessageViewModel(message = getMessageWithoutQuoteMarkdown(message), rawData = message,
val content = getContent(stripMessageQuotes(message))
MessageViewModel(message = stripMessageQuotes(message), rawData = message,
messageId = message.id, avatar = avatar!!, time = time, senderName = sender,
content = content, isPinned = message.pinned, reactions = getReactions(message),
isFirstUnread = false)
isFirstUnread = false, preview = preview)
}
private suspend fun mapMessagePreview(message: Message): Message {
return when (message.isSystemMessage()) {
false -> stripMessageQuotes(message)
true -> message.copy(message = getSystemMessage(message).toString())
}
}
private fun getReactions(message: Message): List<ReactionViewModel> {
......@@ -194,7 +209,7 @@ class ViewModelMapper @Inject constructor(private val context: Context,
return reactions ?: emptyList()
}
private fun getMessageWithoutQuoteMarkdown(message: Message): Message {
private suspend fun stripMessageQuotes(message: Message): Message {
val baseUrl = settings.baseUrl()
return message.copy(
message = message.message.replace("\\[\\s\\]\\($baseUrl.*\\)".toRegex(), "").trim()
......@@ -225,14 +240,14 @@ class ViewModelMapper @Inject constructor(private val context: Context,
private fun getTime(timestamp: Long) = DateTimeHelper.getTime(DateTimeHelper.getLocalDateTime(timestamp))
private suspend fun getContent(context: Context, message: Message): CharSequence {
private suspend fun getContent(message: Message): CharSequence {
return when (message.isSystemMessage()) {
true -> getSystemMessage(message, context)
true -> getSystemMessage(message)
false -> parser.renderMarkdown(message, currentUsername)
}
}
private fun getSystemMessage(message: Message, context: Context): CharSequence {
private fun getSystemMessage(message: Message): CharSequence {
val content = when (message.type) {
//TODO: Add implementation for Welcome type.
is MessageType.MessageRemoved -> context.getString(R.string.message_removed)
......
package chat.rocket.android.chatrooms.presentation
import chat.rocket.android.chatroom.viewmodel.ViewModelMapper
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.main.presentation.MainNavigator
import chat.rocket.android.server.domain.*
......@@ -30,6 +31,7 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
private val getChatRoomsInteractor: GetChatRoomsInteractor,
private val saveChatRoomsInteractor: SaveChatRoomsInteractor,
private val refreshSettingsInteractor: RefreshSettingsInteractor,
private val viewModelMapper: ViewModelMapper,
settingsRepository: SettingsRepository,
factory: ConnectionManagerFactory) {
private val manager: ConnectionManager = factory.create(serverInteractor.get()!!)
......@@ -89,9 +91,9 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
val chatRoomsCombined = mutableListOf<ChatRoom>()
chatRoomsCombined.addAll(usersToChatRooms(users))
chatRoomsCombined.addAll(roomsToChatRooms(rooms))
view.updateChatRooms(chatRoomsCombined)
view.updateChatRooms(getChatRoomsWithPreviews(chatRoomsCombined.toList()))
} else {
view.updateChatRooms(roomList)
view.updateChatRooms(getChatRoomsWithPreviews(roomList))
}
} catch (ex: RocketChatException) {
Timber.e(ex)
......@@ -125,7 +127,7 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
val sortedRooms = sortRooms(chatRooms)
Timber.d("Loaded rooms: ${sortedRooms.size}")
saveChatRoomsInteractor.save(currentServer, sortedRooms)
return sortedRooms
return getChatRoomsWithPreviews(sortedRooms)
}
private fun sortRooms(chatRooms: List<ChatRoom>): List<ChatRoom> {
......@@ -136,7 +138,17 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
private fun updateRooms() {
Timber.d("Updating Rooms")
launch {
view.updateChatRooms(getChatRoomsInteractor.get(currentServer))
view.updateChatRooms(getChatRoomsWithPreviews(getChatRoomsInteractor.get(currentServer)))
}
}
private suspend fun getChatRoomsWithPreviews(chatRooms: List<ChatRoom>): List<ChatRoom> {
return chatRooms.map {
if (it.lastMessage != null) {
it.copy(lastMessage = viewModelMapper.map(it.lastMessage!!).last().preview)
} else {
it
}
}
}
......
......@@ -69,9 +69,9 @@
<string name="msg_new_password">Informe a nova senha</string>
<string name="msg_confirm_password">Confirme a nova senha</string>
<string name="msg_unread_messages">Mensagens não lidas</string>
<string name="msg_quote_video">Vídeo</string>
<string name="msg_quote_audio">Audio</string>
<string name="msg_quote_photo">Foto</string>
<string name="msg_preview_video">Vídeo</string>
<string name="msg_preview_audio">Audio</string>
<string name="msg_preview_photo">Foto</string>
<!-- System messages -->
<string name="message_room_name_changed">Nome da sala alterado para: %1$s por %2$s</string>
......
......@@ -70,9 +70,9 @@
<string name="msg_new_password">Enter New Password</string>
<string name="msg_confirm_password">Confirm New Password</string>
<string name="msg_unread_messages">Unread messages</string>
<string name="msg_quote_video">Video</string>
<string name="msg_quote_audio">Audio</string>
<string name="msg_quote_photo">Photo</string>
<string name="msg_preview_video">Video</string>
<string name="msg_preview_audio">Audio</string>
<string name="msg_preview_photo">Photo</string>
<!-- System messages -->
<string name="message_room_name_changed">Room name changed to: %1$s by %2$s</string>
......
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