Skip to content
This repository has been archived by the owner on Jun 7, 2020. It is now read-only.

Highlight the searched word in the result. #2115

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package chat.rocket.android.chatroom.adapter

import android.graphics.Color
import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.text.Spannable
import android.text.SpannableString
import android.text.method.LinkMovementMethod
import android.text.style.BackgroundColorSpan
import android.text.style.ForegroundColorSpan
import android.text.style.ImageSpan
import android.text.style.StyleSpan
import android.view.View
import androidx.core.view.isVisible
import chat.rocket.android.R
Expand Down Expand Up @@ -49,7 +54,27 @@ class MessageViewHolder(
}
}

text_content.text_content.text = data.content
if (data.isSearchResult) {
fun setHighlightSpaannable(myText: CharSequence): SpannableString {
var spannableContent = SpannableString(myText)
val searchTermStart = data.content.indexOf(data.searchTerm)
val highlightColor = BackgroundColorSpan(Color.rgb(255, 255, 0))
if (searchTermStart > 0) {
spannableContent.setSpan(
highlightColor,
searchTermStart,
searchTermStart + data.searchTerm.length,
Spannable.SPAN_INCLUSIVE_INCLUSIVE
)
}
return spannableContent
}

val myText = data.content
text_content.text_content.text = setHighlightSpaannable(myText)
} else {
text_content.text_content.text = data.content
}

image_avatar.setImageURI(data.avatar)
text_content.setTextColor(if (data.isTemporary) Color.GRAY else Color.BLACK)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,13 @@ class ChatRoomPresenter @Inject constructor(
chatIsBroadcast = it.chatRoom.broadcast ?: false
val roomUiModel = roomMapper.map(it, true)
launchUI(strategy) {
view.onRoomUpdated(roomUiModel = roomUiModel.copy(
broadcast = chatIsBroadcast,
canModerate = canModerate,
writable = roomUiModel.writable || canModerate
))
view.onRoomUpdated(
roomUiModel = roomUiModel.copy(
broadcast = chatIsBroadcast,
canModerate = canModerate,
writable = roomUiModel.writable || canModerate
)
)
}
}

Expand Down Expand Up @@ -217,10 +219,10 @@ class ChatRoomPresenter @Inject constructor(
val localMessages = messagesRepository.getRecentMessages(chatRoomId, 50)
val oldMessages = mapper.map(
localMessages, RoomUiModel(
roles = chatRoles,
// FIXME: Why are we fixing isRoom attribute to true here?
isBroadcast = chatIsBroadcast, isRoom = true
)
roles = chatRoles,
// FIXME: Why are we fixing isRoom attribute to true here?
isBroadcast = chatIsBroadcast, isRoom = true
)
)
val lastSyncDate = messagesRepository.getLastSyncDate(chatRoomId)
if (oldMessages.isNotEmpty() && lastSyncDate != null) {
Expand Down Expand Up @@ -298,7 +300,7 @@ class ChatRoomPresenter @Inject constructor(
mapper.map(
messages,
RoomUiModel(chatRoles, chatIsBroadcast, true)
)
), searchText
)
} catch (ex: Exception) {
Timber.e(ex)
Expand Down Expand Up @@ -601,12 +603,14 @@ class ChatRoomPresenter @Inject constructor(
Timber.d("History: $messages")

if (messages.result.isNotEmpty()) {
val models = mapper.map(messages.result, RoomUiModel(
roles = chatRoles,
isBroadcast = chatIsBroadcast,
// FIXME: Why are we fixing isRoom attribute to true here?
isRoom = true
))
val models = mapper.map(
messages.result, RoomUiModel(
roles = chatRoles,
isBroadcast = chatIsBroadcast,
// FIXME: Why are we fixing isRoom attribute to true here?
isRoom = true
)
)
messagesRepository.saveAll(messages.result)
//if success - saving last synced time
//assume that BE returns ordered messages, the first message is the latest one
Expand Down Expand Up @@ -687,9 +691,9 @@ class ChatRoomPresenter @Inject constructor(
replyMarkdown = "[ ]($currentServer/$chatRoomType/$room?msg=$id) $mention ",
quotedMessage = mapper.map(
message, RoomUiModel(
roles = chatRoles,
isBroadcast = chatIsBroadcast
)
roles = chatRoles,
isBroadcast = chatIsBroadcast
)
).last().preview?.message ?: ""
)
}
Expand Down Expand Up @@ -1031,7 +1035,8 @@ class ChatRoomPresenter @Inject constructor(
val canPost = permissions.canPostToReadOnlyChannels()
dbManager.getRoom(chatRoomId)?.let {
val roomUiModel = roomMapper.map(it, true).copy(
writable = canPost)
writable = canPost
)
view.onJoined(roomUiModel = roomUiModel)
view.onRoomUpdated(roomUiModel = roomUiModel)
}
Expand Down Expand Up @@ -1301,6 +1306,7 @@ class ChatRoomPresenter @Inject constructor(
fun clearDraftMessage() {
localRepository.clear(draftKey)
}

/**
* Get unfinished message from local repository, when user left chat room without
* sending a message and now the user is back.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ interface ChatRoomView : LoadingView, MessageView {
*
* @param dataSet The data set to show.
*/
fun showSearchedMessages(dataSet: List<BaseUiModel<*>>)
fun showSearchedMessages(dataSet: List<BaseUiModel<*>>, searchTerm: String)

/**
* Send a message to a chat room.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@ import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.provider.MediaStore
import android.text.Spannable
import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.text.style.StyleSpan
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.Menu
Expand All @@ -34,12 +38,7 @@ import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.R
import chat.rocket.android.analytics.AnalyticsManager
import chat.rocket.android.analytics.event.ScreenViewEvent
import chat.rocket.android.chatroom.adapter.ChatRoomAdapter
import chat.rocket.android.chatroom.adapter.CommandSuggestionsAdapter
import chat.rocket.android.chatroom.adapter.EmojiSuggestionsAdapter
import chat.rocket.android.chatroom.adapter.PEOPLE
import chat.rocket.android.chatroom.adapter.PeopleSuggestionsAdapter
import chat.rocket.android.chatroom.adapter.RoomSuggestionsAdapter
import chat.rocket.android.chatroom.adapter.*
import chat.rocket.android.chatroom.presentation.ChatRoomNavigator
import chat.rocket.android.chatroom.presentation.ChatRoomPresenter
import chat.rocket.android.chatroom.presentation.ChatRoomView
Expand Down Expand Up @@ -287,7 +286,14 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
requireNotNull(bundle) { "no arguments supplied when the fragment was instantiated" }
}

adapter = ChatRoomAdapter(chatRoomId, chatRoomType, chatRoomName, this, reactionListener = this, navigator = navigator)
adapter = ChatRoomAdapter(
chatRoomId,
chatRoomType,
chatRoomName,
this,
reactionListener = this,
navigator = navigator
)
}

override fun onCreateView(
Expand Down Expand Up @@ -442,8 +448,13 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
}
}

override fun showSearchedMessages(dataSet: List<BaseUiModel<*>>) {
override fun showSearchedMessages(dataSet: List<BaseUiModel<*>>, searchTerm: String) {
recycler_view.removeOnScrollListener(endlessRecyclerViewScrollListener)
for (dataItem in dataSet) {
dataItem.isSearchResult = true
dataItem.searchTerm = searchTerm
}

adapter.clearData()
adapter.prependData(dataSet)
empty_chat_view.isVisible = adapter.itemCount == 0
Expand Down Expand Up @@ -539,9 +550,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
text_count.text = "99+"
}
text_count.isVisible = true
}

else if (!button_fab.isVisible) {
} else if (!button_fab.isVisible) {
recycler_view.scrollToPosition(0)
}
verticalScrollOffset.set(0)
Expand Down Expand Up @@ -711,7 +720,8 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
}

text_view_usernames.text = requireContext().resources.getQuantityString(
R.plurals.msg_reacted_with_, usernames.size, listing, shortname)
R.plurals.msg_reacted_with_, usernames.size, listing, shortname
)

dialog.show()
}
Expand Down Expand Up @@ -1147,8 +1157,10 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
}

override fun reportMessage(id: String) {
presenter.reportMessage(messageId = id,
description = "This message was reported by a user from the Android app")
presenter.reportMessage(
messageId = id,
description = "This message was reported by a user from the Android app"
)
}

fun openEmojiKeyboard() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,39 @@ import chat.rocket.core.model.attachment.Attachment
import chat.rocket.core.model.attachment.actions.Action

data class AttachmentUiModel(
override val message: Message,
override val rawData: Attachment,
override val messageId: String,
override var reactions: List<ReactionUiModel>,
override var nextDownStreamMessage: BaseUiModel<*>? = null,
override var preview: Message?,
override var isTemporary: Boolean,
override var unread: Boolean?,
override var currentDayMarkerText: String,
override var showDayMarker: Boolean,
override var menuItemsToHide: MutableList<Int> = mutableListOf(),
override var permalink: String,
val id: Long,
val title: CharSequence?,
val description: CharSequence?,
val authorName: CharSequence?,
val text: CharSequence?,
val color: Int?,
val imageUrl: String?,
val videoUrl: String?,
val audioUrl: String?,
val titleLink: String?,
val messageLink: String?,
val type: String?,
// TODO - attachments
val timestamp: CharSequence?,
val authorIcon: String?,
val authorLink: String?,
val fields: CharSequence?,
val buttonAlignment: String?,
val actions: List<Action>?
override val message: Message,
override val rawData: Attachment,
override val messageId: String,
override var reactions: List<ReactionUiModel>,
override var nextDownStreamMessage: BaseUiModel<*>? = null,
override var preview: Message?,
override var isTemporary: Boolean,
override var unread: Boolean?,
override var currentDayMarkerText: String,
override var showDayMarker: Boolean,
override var menuItemsToHide: MutableList<Int> = mutableListOf(),
override var permalink: String,
override var isSearchResult: Boolean = false,
override var searchTerm: String = "",
val id: Long,
val title: CharSequence?,
val description: CharSequence?,
val authorName: CharSequence?,
val text: CharSequence?,
val color: Int?,
val imageUrl: String?,
val videoUrl: String?,
val audioUrl: String?,
val titleLink: String?,
val messageLink: String?,
val type: String?,
// TODO - attachments
val timestamp: CharSequence?,
val authorIcon: String?,
val authorLink: String?,
val fields: CharSequence?,
val buttonAlignment: String?,
val actions: List<Action>?
) : BaseUiModel<Attachment> {
override val viewType: Int
get() = BaseUiModel.ViewType.ATTACHMENT.viewType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ interface BaseUiModel<out T> {
var showDayMarker: Boolean
var menuItemsToHide: MutableList<Int>
var permalink: String
var isSearchResult: Boolean
var searchTerm: String

enum class ViewType(val viewType: Int) {
MESSAGE(0),
Expand All @@ -30,5 +32,5 @@ interface BaseUiModel<out T> {

internal fun Int.toViewType(): BaseUiModel.ViewType {
return BaseUiModel.ViewType.values().firstOrNull { it.viewType == this }
?: throw InvalidParameterException("Invalid viewType: $this for BaseUiModel.ViewType")
?: throw InvalidParameterException("Invalid viewType: $this for BaseUiModel.ViewType")
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ data class MessageReplyUiModel(
override var menuItemsToHide: MutableList<Int> = mutableListOf(),
override var currentDayMarkerText: String,
override var showDayMarker: Boolean,
override var permalink: String
override var permalink: String,
override var isSearchResult: Boolean = false,
override var searchTerm: String = ""
) : BaseUiModel<MessageReply> {
override val viewType: Int
get() = BaseUiModel.ViewType.MESSAGE_REPLY.viewType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ data class MessageUiModel(
override var isTemporary: Boolean = false,
override var menuItemsToHide: MutableList<Int> = mutableListOf(),
override var permalink: String,
val subscriptionId: String
val subscriptionId: String,
override var isSearchResult: Boolean = false,
override var searchTerm: String = ""

) : BaseMessageUiModel<Message> {
override val viewType: Int
get() = BaseUiModel.ViewType.MESSAGE.viewType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ data class UrlPreviewUiModel(
override var menuItemsToHide: MutableList<Int> = mutableListOf(),
override var currentDayMarkerText: String,
override var showDayMarker: Boolean,
override var permalink: String
override var permalink: String,
override var isSearchResult: Boolean = false,
override var searchTerm: String = ""
) : BaseUiModel<Url> {
override val viewType: Int
get() = BaseUiModel.ViewType.URL_PREVIEW.viewType
Expand Down