mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-02-18 04:50:08 +03:00
Show edited annotation in timeline + simple edit history
This commit is contained in:
parent
a5a9fa3750
commit
6f103101b6
10 changed files with 118 additions and 6 deletions
|
@ -1,3 +1,18 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
package im.vector.matrix.android.internal.session.room
|
package im.vector.matrix.android.internal.session.room
|
||||||
|
|
||||||
import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary
|
import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary
|
||||||
|
@ -7,7 +22,9 @@ import im.vector.matrix.android.internal.database.model.EventEntity
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches annotations (reactions, edits...) associated to a given eventEntity from the data layer.
|
||||||
|
*/
|
||||||
internal class EventRelationExtractor {
|
internal class EventRelationExtractor {
|
||||||
|
|
||||||
fun extractFrom(event: EventEntity, realm: Realm = event.realm): EventAnnotationsSummary? {
|
fun extractFrom(event: EventEntity, realm: Realm = event.realm): EventAnnotationsSummary? {
|
||||||
|
|
|
@ -19,8 +19,11 @@
|
||||||
package im.vector.riotredesign.core.resources
|
package im.vector.riotredesign.core.resources
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import androidx.annotation.AttrRes
|
||||||
|
import androidx.annotation.ColorInt
|
||||||
import androidx.annotation.ColorRes
|
import androidx.annotation.ColorRes
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import im.vector.riotredesign.features.themes.ThemeUtils
|
||||||
|
|
||||||
class ColorProvider(private val context: Context) {
|
class ColorProvider(private val context: Context) {
|
||||||
|
|
||||||
|
@ -28,4 +31,16 @@ class ColorProvider(private val context: Context) {
|
||||||
return ContextCompat.getColor(context, colorRes)
|
return ContextCompat.getColor(context, colorRes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translates color attributes to colors
|
||||||
|
*
|
||||||
|
* @param c Context
|
||||||
|
* @param colorAttribute Color Attribute
|
||||||
|
* @return Requested Color
|
||||||
|
*/
|
||||||
|
@ColorInt
|
||||||
|
fun getColorFromAttribute(@AttrRes colorAttribute: Int): Int {
|
||||||
|
return ThemeUtils.getColor(context, colorAttribute)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -18,6 +18,7 @@ package im.vector.riotredesign.features.home
|
||||||
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import im.vector.riotredesign.core.glide.GlideApp
|
import im.vector.riotredesign.core.glide.GlideApp
|
||||||
|
import im.vector.riotredesign.core.resources.ColorProvider
|
||||||
import im.vector.riotredesign.features.autocomplete.command.AutocompleteCommandController
|
import im.vector.riotredesign.features.autocomplete.command.AutocompleteCommandController
|
||||||
import im.vector.riotredesign.features.autocomplete.command.AutocompleteCommandPresenter
|
import im.vector.riotredesign.features.autocomplete.command.AutocompleteCommandPresenter
|
||||||
import im.vector.riotredesign.features.autocomplete.user.AutocompleteUserController
|
import im.vector.riotredesign.features.autocomplete.user.AutocompleteUserController
|
||||||
|
@ -58,7 +59,8 @@ class HomeModule {
|
||||||
val eventHtmlRenderer = EventHtmlRenderer(GlideApp.with(fragment), fragment.requireContext(), get())
|
val eventHtmlRenderer = EventHtmlRenderer(GlideApp.with(fragment), fragment.requireContext(), get())
|
||||||
val timelineDateFormatter = TimelineDateFormatter(get())
|
val timelineDateFormatter = TimelineDateFormatter(get())
|
||||||
val timelineMediaSizeProvider = TimelineMediaSizeProvider()
|
val timelineMediaSizeProvider = TimelineMediaSizeProvider()
|
||||||
val messageItemFactory = MessageItemFactory(get(), timelineMediaSizeProvider, timelineDateFormatter, eventHtmlRenderer)
|
val colorProvider = ColorProvider(fragment.requireContext())
|
||||||
|
val messageItemFactory = MessageItemFactory(colorProvider, timelineMediaSizeProvider, timelineDateFormatter, eventHtmlRenderer)
|
||||||
|
|
||||||
val timelineItemFactory = TimelineItemFactory(messageItemFactory = messageItemFactory,
|
val timelineItemFactory = TimelineItemFactory(messageItemFactory = messageItemFactory,
|
||||||
roomNameItemFactory = RoomNameItemFactory(get()),
|
roomNameItemFactory = RoomNameItemFactory(get()),
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package im.vector.riotredesign.features.home.room.detail
|
package im.vector.riotredesign.features.home.room.detail
|
||||||
|
|
||||||
import com.jaiselrahman.filepicker.model.MediaFile
|
import com.jaiselrahman.filepicker.model.MediaFile
|
||||||
|
import im.vector.matrix.android.api.session.room.model.EditAggregatedSummary
|
||||||
import im.vector.matrix.android.api.session.room.timeline.Timeline
|
import im.vector.matrix.android.api.session.room.timeline.Timeline
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@ sealed class RoomDetailActions {
|
||||||
data class RedactAction(val targetEventId: String, val reason: String? = "") : RoomDetailActions()
|
data class RedactAction(val targetEventId: String, val reason: String? = "") : RoomDetailActions()
|
||||||
data class UndoReaction(val targetEventId: String, val key: String, val reason: String? = "") : RoomDetailActions()
|
data class UndoReaction(val targetEventId: String, val key: String, val reason: String? = "") : RoomDetailActions()
|
||||||
data class UpdateQuickReactAction(val targetEventId: String,val selectedReaction: String,val opposite: String) : RoomDetailActions()
|
data class UpdateQuickReactAction(val targetEventId: String,val selectedReaction: String,val opposite: String) : RoomDetailActions()
|
||||||
|
data class ShowEditHistoryAction(val event: String,val editAggregatedSummary: EditAggregatedSummary) : RoomDetailActions()
|
||||||
object AcceptInvite : RoomDetailActions()
|
object AcceptInvite : RoomDetailActions()
|
||||||
object RejectInvite : RoomDetailActions()
|
object RejectInvite : RoomDetailActions()
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@ import com.otaliastudios.autocomplete.Autocomplete
|
||||||
import com.otaliastudios.autocomplete.AutocompleteCallback
|
import com.otaliastudios.autocomplete.AutocompleteCallback
|
||||||
import com.otaliastudios.autocomplete.CharPolicy
|
import com.otaliastudios.autocomplete.CharPolicy
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
|
import im.vector.matrix.android.api.session.room.model.EditAggregatedSummary
|
||||||
import im.vector.matrix.android.api.session.room.model.Membership
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
import im.vector.matrix.android.api.session.room.model.message.*
|
import im.vector.matrix.android.api.session.room.model.message.*
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
|
@ -177,6 +178,12 @@ class RoomDetailFragment :
|
||||||
textComposerViewModel.subscribe { renderTextComposerState(it) }
|
textComposerViewModel.subscribe { renderTextComposerState(it) }
|
||||||
roomDetailViewModel.sendMessageResultLiveData.observeEvent(this) { renderSendMessageResult(it) }
|
roomDetailViewModel.sendMessageResultLiveData.observeEvent(this) { renderSendMessageResult(it) }
|
||||||
|
|
||||||
|
roomDetailViewModel.nonBlockingPopAlert.observe(this, Observer { liveEvent ->
|
||||||
|
liveEvent.getContentIfNotHandled()?.let {
|
||||||
|
val message = requireContext().getString(it.first, *it.second.toTypedArray())
|
||||||
|
showSnackWithMessage(message, Snackbar.LENGTH_LONG)
|
||||||
|
}
|
||||||
|
})
|
||||||
actionViewModel.actionCommandEvent.observe(this, Observer {
|
actionViewModel.actionCommandEvent.observe(this, Observer {
|
||||||
handleActions(it)
|
handleActions(it)
|
||||||
})
|
})
|
||||||
|
@ -514,6 +521,12 @@ class RoomDetailFragment :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onEditedDecorationClicked(informationData: MessageInformationData, editAggregatedSummary: EditAggregatedSummary?) {
|
||||||
|
editAggregatedSummary?.also {
|
||||||
|
roomDetailViewModel.process(RoomDetailActions.ShowEditHistoryAction(informationData.eventId, it))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
// AutocompleteUserPresenter.Callback
|
// AutocompleteUserPresenter.Callback
|
||||||
|
|
||||||
override fun onQueryUsers(query: CharSequence?) {
|
override fun onQueryUsers(query: CharSequence?) {
|
||||||
|
@ -641,6 +654,12 @@ class RoomDetailFragment :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun showSnackWithMessage(message: String, duration: Int = Snackbar.LENGTH_SHORT) {
|
||||||
|
val snack = Snackbar.make(view!!, message, Snackbar.LENGTH_SHORT)
|
||||||
|
snack.view.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.notification_accent_color))
|
||||||
|
snack.show()
|
||||||
|
}
|
||||||
|
|
||||||
// VectorInviteView.Callback
|
// VectorInviteView.Callback
|
||||||
|
|
||||||
override fun onAcceptInvite() {
|
override fun onAcceptInvite() {
|
||||||
|
|
|
@ -28,6 +28,7 @@ import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||||
import im.vector.matrix.android.api.session.room.model.Membership
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
||||||
import im.vector.matrix.rx.rx
|
import im.vector.matrix.rx.rx
|
||||||
|
import im.vector.riotredesign.R
|
||||||
import im.vector.riotredesign.core.platform.VectorViewModel
|
import im.vector.riotredesign.core.platform.VectorViewModel
|
||||||
import im.vector.riotredesign.core.utils.LiveEvent
|
import im.vector.riotredesign.core.utils.LiveEvent
|
||||||
import im.vector.riotredesign.features.command.CommandParser
|
import im.vector.riotredesign.features.command.CommandParser
|
||||||
|
@ -36,6 +37,8 @@ import im.vector.riotredesign.features.home.room.VisibleRoomStore
|
||||||
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDisplayableEvents
|
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDisplayableEvents
|
||||||
import io.reactivex.rxkotlin.subscribeBy
|
import io.reactivex.rxkotlin.subscribeBy
|
||||||
import org.koin.android.ext.android.get
|
import org.koin.android.ext.android.get
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
class RoomDetailViewModel(initialState: RoomDetailViewState,
|
class RoomDetailViewModel(initialState: RoomDetailViewState,
|
||||||
|
@ -83,10 +86,16 @@ class RoomDetailViewModel(initialState: RoomDetailViewState,
|
||||||
is RoomDetailActions.RedactAction -> handleRedactEvent(action)
|
is RoomDetailActions.RedactAction -> handleRedactEvent(action)
|
||||||
is RoomDetailActions.UndoReaction -> handleUndoReact(action)
|
is RoomDetailActions.UndoReaction -> handleUndoReact(action)
|
||||||
is RoomDetailActions.UpdateQuickReactAction -> handleUpdateQuickReaction(action)
|
is RoomDetailActions.UpdateQuickReactAction -> handleUpdateQuickReaction(action)
|
||||||
|
is RoomDetailActions.ShowEditHistoryAction -> handleShowEditHistoryReaction(action)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private val _nonBlockingPopAlert = MutableLiveData<LiveEvent<Pair<Int, List<Any>>>>()
|
||||||
|
val nonBlockingPopAlert: LiveData<LiveEvent<Pair<Int, List<Any>>>>
|
||||||
|
get() = _nonBlockingPopAlert
|
||||||
|
|
||||||
|
|
||||||
private val _sendMessageResultLiveData = MutableLiveData<LiveEvent<SendMessageResult>>()
|
private val _sendMessageResultLiveData = MutableLiveData<LiveEvent<SendMessageResult>>()
|
||||||
val sendMessageResultLiveData: LiveData<LiveEvent<SendMessageResult>>
|
val sendMessageResultLiveData: LiveData<LiveEvent<SendMessageResult>>
|
||||||
get() = _sendMessageResultLiveData
|
get() = _sendMessageResultLiveData
|
||||||
|
@ -161,6 +170,22 @@ class RoomDetailViewModel(initialState: RoomDetailViewState,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleShowEditHistoryReaction(action: RoomDetailActions.ShowEditHistoryAction) {
|
||||||
|
//TODO temporary implementation
|
||||||
|
val lastReplace = action.editAggregatedSummary.sourceEvents.lastOrNull()?.let {
|
||||||
|
room.getTimeLineEvent(it)
|
||||||
|
} ?: return
|
||||||
|
|
||||||
|
val dateFormat = SimpleDateFormat("EEE, d MMM yyyy HH:mm", Locale.getDefault())
|
||||||
|
_nonBlockingPopAlert.postValue(LiveEvent(
|
||||||
|
Pair(R.string.last_edited_info_message, listOf(
|
||||||
|
lastReplace.senderName ?: "?",
|
||||||
|
dateFormat.format(Date(lastReplace.root.originServerTs ?: 0)))
|
||||||
|
))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun handleChangeTopicSlashCommand(changeTopic: ParsedCommand.ChangeTopic) {
|
private fun handleChangeTopicSlashCommand(changeTopic: ParsedCommand.ChangeTopic) {
|
||||||
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandHandled))
|
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandHandled))
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.airbnb.epoxy.EpoxyController
|
import com.airbnb.epoxy.EpoxyController
|
||||||
import com.airbnb.epoxy.EpoxyModel
|
import com.airbnb.epoxy.EpoxyModel
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
|
import im.vector.matrix.android.api.session.room.model.EditAggregatedSummary
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
import im.vector.matrix.android.api.session.room.model.RoomMember
|
||||||
import im.vector.matrix.android.api.session.room.model.message.*
|
import im.vector.matrix.android.api.session.room.model.message.*
|
||||||
import im.vector.matrix.android.api.session.room.timeline.Timeline
|
import im.vector.matrix.android.api.session.room.timeline.Timeline
|
||||||
|
@ -58,6 +59,7 @@ class TimelineEventController(private val dateFormatter: TimelineDateFormatter,
|
||||||
fun onEventLongClicked(informationData: MessageInformationData, messageContent: MessageContent, view: View): Boolean
|
fun onEventLongClicked(informationData: MessageInformationData, messageContent: MessageContent, view: View): Boolean
|
||||||
fun onAvatarClicked(informationData: MessageInformationData)
|
fun onAvatarClicked(informationData: MessageInformationData)
|
||||||
fun onMemberNameClicked(informationData: MessageInformationData)
|
fun onMemberNameClicked(informationData: MessageInformationData)
|
||||||
|
fun onEditedDecorationClicked(informationData: MessageInformationData, editAggregatedSummary: EditAggregatedSummary?)
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ReactionPillCallback {
|
interface ReactionPillCallback {
|
||||||
|
|
|
@ -51,7 +51,8 @@ class MessageActionsViewModel(initialState: MessageActionState) : VectorViewMode
|
||||||
|
|
||||||
val event = currentSession.getRoom(parcel.roomId)?.getTimeLineEvent(parcel.eventId)
|
val event = currentSession.getRoom(parcel.roomId)?.getTimeLineEvent(parcel.eventId)
|
||||||
return if (event != null) {
|
return if (event != null) {
|
||||||
val messageContent: MessageContent? = event.root.content.toModel()
|
val messageContent: MessageContent? = event.annotations?.editSummary?.aggregatedContent?.toModel()
|
||||||
|
?: event.root.content.toModel()
|
||||||
val originTs = event.root.originServerTs
|
val originTs = event.root.originServerTs
|
||||||
MessageActionState(
|
MessageActionState(
|
||||||
event.root.sender ?: "",
|
event.root.sender ?: "",
|
||||||
|
|
|
@ -16,10 +16,12 @@
|
||||||
|
|
||||||
package im.vector.riotredesign.features.home.room.detail.timeline.factory
|
package im.vector.riotredesign.features.home.room.detail.timeline.factory
|
||||||
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.text.SpannableStringBuilder
|
import android.text.SpannableStringBuilder
|
||||||
import android.text.Spanned
|
import android.text.Spanned
|
||||||
|
import android.text.TextPaint
|
||||||
|
import android.text.style.ClickableSpan
|
||||||
import android.text.style.ForegroundColorSpan
|
import android.text.style.ForegroundColorSpan
|
||||||
|
import android.text.style.RelativeSizeSpan
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.annotation.ColorRes
|
import androidx.annotation.ColorRes
|
||||||
import im.vector.matrix.android.api.permalinks.MatrixLinkify
|
import im.vector.matrix.android.api.permalinks.MatrixLinkify
|
||||||
|
@ -27,6 +29,7 @@ import im.vector.matrix.android.api.permalinks.MatrixPermalinkSpan
|
||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
import im.vector.matrix.android.api.session.events.model.RelationType
|
import im.vector.matrix.android.api.session.events.model.RelationType
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
|
import im.vector.matrix.android.api.session.room.model.EditAggregatedSummary
|
||||||
import im.vector.matrix.android.api.session.room.model.message.*
|
import im.vector.matrix.android.api.session.room.model.message.*
|
||||||
import im.vector.matrix.android.api.session.room.send.SendState
|
import im.vector.matrix.android.api.session.room.send.SendState
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
|
@ -108,7 +111,10 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
|
||||||
// val ev = all.toModel<Event>()
|
// val ev = all.toModel<Event>()
|
||||||
return when (messageContent) {
|
return when (messageContent) {
|
||||||
is MessageEmoteContent -> buildEmoteMessageItem(messageContent, informationData, callback)
|
is MessageEmoteContent -> buildEmoteMessageItem(messageContent, informationData, callback)
|
||||||
is MessageTextContent -> buildTextMessageItem(event.sendState, messageContent, informationData, hasBeenEdited, callback)
|
is MessageTextContent -> buildTextMessageItem(event.sendState, messageContent, informationData, hasBeenEdited,
|
||||||
|
event.annotations?.editSummary,
|
||||||
|
callback
|
||||||
|
)
|
||||||
is MessageImageContent -> buildImageMessageItem(messageContent, informationData, callback)
|
is MessageImageContent -> buildImageMessageItem(messageContent, informationData, callback)
|
||||||
is MessageNoticeContent -> buildNoticeMessageItem(messageContent, informationData, callback)
|
is MessageNoticeContent -> buildNoticeMessageItem(messageContent, informationData, callback)
|
||||||
is MessageVideoContent -> buildVideoMessageItem(messageContent, informationData, callback)
|
is MessageVideoContent -> buildVideoMessageItem(messageContent, informationData, callback)
|
||||||
|
@ -269,6 +275,7 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
|
||||||
private fun buildTextMessageItem(sendState: SendState, messageContent: MessageTextContent,
|
private fun buildTextMessageItem(sendState: SendState, messageContent: MessageTextContent,
|
||||||
informationData: MessageInformationData,
|
informationData: MessageInformationData,
|
||||||
hasBeenEdited: Boolean,
|
hasBeenEdited: Boolean,
|
||||||
|
editSummary: EditAggregatedSummary?,
|
||||||
callback: TimelineEventController.Callback?): MessageTextItem? {
|
callback: TimelineEventController.Callback?): MessageTextItem? {
|
||||||
|
|
||||||
val bodyToUse = messageContent.formattedBody?.let {
|
val bodyToUse = messageContent.formattedBody?.let {
|
||||||
|
@ -284,7 +291,28 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
|
||||||
spannable.append(linkifiedBody)
|
spannable.append(linkifiedBody)
|
||||||
val editedSuffix = "(edited)"
|
val editedSuffix = "(edited)"
|
||||||
spannable.append(" ").append(editedSuffix)
|
spannable.append(" ").append(editedSuffix)
|
||||||
spannable.setSpan(ForegroundColorSpan(Color.LTGRAY), spannable.indexOf(editedSuffix), spannable.indexOf(editedSuffix) + editedSuffix.length, Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
|
val color = colorProvider.getColorFromAttribute(R.attr.vctr_list_header_secondary_text_color)
|
||||||
|
val editStart = spannable.indexOf(editedSuffix)
|
||||||
|
val editEnd = editStart + editedSuffix.length
|
||||||
|
spannable.setSpan(
|
||||||
|
ForegroundColorSpan(color),
|
||||||
|
editStart,
|
||||||
|
editEnd,
|
||||||
|
Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
|
||||||
|
|
||||||
|
spannable.setSpan(RelativeSizeSpan(.9f), editStart, editEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
|
||||||
|
spannable.setSpan(object : ClickableSpan() {
|
||||||
|
override fun onClick(widget: View?) {
|
||||||
|
callback?.onEditedDecorationClicked(informationData, editSummary)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateDrawState(ds: TextPaint?) {
|
||||||
|
//nop
|
||||||
|
}
|
||||||
|
},
|
||||||
|
editStart,
|
||||||
|
editEnd,
|
||||||
|
Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
|
||||||
message(spannable)
|
message(spannable)
|
||||||
} else {
|
} else {
|
||||||
message(linkifiedBody)
|
message(linkifiedBody)
|
||||||
|
|
|
@ -15,5 +15,6 @@
|
||||||
|
|
||||||
<string name="event_redacted_by_user_reason">Event deleted by user</string>
|
<string name="event_redacted_by_user_reason">Event deleted by user</string>
|
||||||
<string name="event_redacted_by_admin_reason">Event moderated by room admin</string>
|
<string name="event_redacted_by_admin_reason">Event moderated by room admin</string>
|
||||||
|
<string name="last_edited_info_message">Last edited by %s on %s</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
Loading…
Add table
Reference in a new issue