mirror of
https://github.com/element-hq/element-android
synced 2024-11-23 18:05:36 +03:00
Fix / impure reducer in action view model
This commit is contained in:
parent
a9dd06562a
commit
f83491fdfc
4 changed files with 71 additions and 61 deletions
|
@ -152,6 +152,8 @@ data class Event(
|
|||
mClaimedEd25519Key = decryptionResult.claimedEd25519Key
|
||||
mForwardingCurve25519KeyChain = decryptionResult.forwardingCurve25519KeyChain
|
||||
|
||||
// For encrypted events with relation, the m.relates_to is kept in clear, so we need to put it back
|
||||
// in the clear event
|
||||
try {
|
||||
content?.get("m.relates_to")?.let { clearRelates ->
|
||||
mClearEvent = mClearEvent?.copy(
|
||||
|
|
|
@ -45,8 +45,10 @@ import javax.inject.Inject
|
|||
*/
|
||||
class MessageActionsBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
||||
|
||||
@Inject lateinit var messageActionViewModelFactory: MessageActionsViewModel.Factory
|
||||
@Inject lateinit var avatarRenderer: AvatarRenderer
|
||||
@Inject
|
||||
lateinit var messageActionViewModelFactory: MessageActionsViewModel.Factory
|
||||
@Inject
|
||||
lateinit var avatarRenderer: AvatarRenderer
|
||||
private val viewModel: MessageActionsViewModel by fragmentViewModel(MessageActionsViewModel::class)
|
||||
|
||||
private lateinit var actionHandlerModel: ActionsHandler
|
||||
|
@ -124,17 +126,18 @@ class MessageActionsBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
|||
}
|
||||
|
||||
override fun invalidate() = withState(viewModel) {
|
||||
if (it.showPreview) {
|
||||
val body = viewModel.resolveBody(it)
|
||||
if (body != null) {
|
||||
bottom_sheet_message_preview.isVisible = true
|
||||
senderNameTextView.text = it.senderName
|
||||
messageBodyTextView.text = it.messageBody
|
||||
messageTimestampText.text = it.ts
|
||||
avatarRenderer.render(it.senderAvatarPath, it.userId, it.senderName, senderAvatarImageView)
|
||||
senderNameTextView.text = it.senderName()
|
||||
messageBodyTextView.text = body
|
||||
messageTimestampText.text = it.time()
|
||||
avatarRenderer.render(it.informationData.avatarUrl, it.informationData.senderId, it.senderName(), senderAvatarImageView)
|
||||
} else {
|
||||
bottom_sheet_message_preview.isVisible = false
|
||||
}
|
||||
quickReactBottomDivider.isVisible = it.canReact
|
||||
bottom_sheet_quick_reaction_container.isVisible = it.canReact
|
||||
quickReactBottomDivider.isVisible = it.canReact()
|
||||
bottom_sheet_quick_reaction_container.isVisible = it.canReact()
|
||||
return@withState
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@ import im.vector.matrix.android.api.session.events.model.toModel
|
|||
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||
import im.vector.riotredesign.core.di.HasScreenInjector
|
||||
import im.vector.riotredesign.core.platform.VectorViewModel
|
||||
import im.vector.riotredesign.features.home.room.detail.timeline.format.NoticeEventFormatter
|
||||
import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
|
||||
|
@ -35,21 +37,45 @@ import java.text.SimpleDateFormat
|
|||
import java.util.*
|
||||
|
||||
|
||||
val dateFormat = SimpleDateFormat("EEE, d MMM yyyy HH:mm", Locale.getDefault())
|
||||
|
||||
data class MessageActionState(
|
||||
val roomId: String,
|
||||
val eventId: String,
|
||||
val informationData: MessageInformationData,
|
||||
val userId: String = "",
|
||||
val senderName: String = "",
|
||||
val messageBody: CharSequence? = null,
|
||||
val ts: String? = null,
|
||||
val showPreview: Boolean = false,
|
||||
val canReact: Boolean = false,
|
||||
val senderAvatarPath: String? = null)
|
||||
: MvRxState {
|
||||
val timelineEvent: TimelineEvent?
|
||||
) : MvRxState {
|
||||
|
||||
constructor(args: TimelineEventFragmentArgs) : this(roomId = args.roomId, eventId = args.eventId, informationData = args.informationData)
|
||||
fun senderName(): String = informationData.memberName?.toString() ?: ""
|
||||
|
||||
fun time(): String? = dateFormat.format(Date(timelineEvent?.root?.originServerTs ?: 0))
|
||||
|
||||
fun canReact(): Boolean = timelineEvent?.root?.type == EventType.MESSAGE && timelineEvent.sendState.isSent()
|
||||
|
||||
fun messageBody(eventHtmlRenderer: EventHtmlRenderer?, noticeEventFormatter: NoticeEventFormatter?): CharSequence? {
|
||||
return when (timelineEvent?.root?.getClearType()) {
|
||||
EventType.MESSAGE -> {
|
||||
val messageContent: MessageContent? = timelineEvent.annotations?.editSummary?.aggregatedContent?.toModel()
|
||||
?: timelineEvent.root.getClearContent().toModel()
|
||||
if (messageContent is MessageTextContent && messageContent.format == MessageType.FORMAT_MATRIX_HTML) {
|
||||
eventHtmlRenderer?.render(messageContent.formattedBody
|
||||
?: messageContent.body)
|
||||
} else {
|
||||
messageContent?.body
|
||||
}
|
||||
}
|
||||
EventType.STATE_ROOM_NAME,
|
||||
EventType.STATE_ROOM_TOPIC,
|
||||
EventType.STATE_ROOM_MEMBER,
|
||||
EventType.STATE_HISTORY_VISIBILITY,
|
||||
EventType.CALL_INVITE,
|
||||
EventType.CALL_HANGUP,
|
||||
EventType.CALL_ANSWER -> {
|
||||
noticeEventFormatter?.format(timelineEvent)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,10 +88,6 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted
|
|||
private val noticeEventFormatter: NoticeEventFormatter
|
||||
) : VectorViewModel<MessageActionState>(initialState) {
|
||||
|
||||
private val roomId = initialState.roomId
|
||||
private val eventId = initialState.eventId
|
||||
private val informationData = initialState.informationData
|
||||
|
||||
@AssistedInject.Factory
|
||||
interface Factory {
|
||||
fun create(initialState: MessageActionState): MessageActionsViewModel
|
||||
|
@ -77,47 +99,23 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted
|
|||
val fragment: MessageActionsBottomSheet = (viewModelContext as FragmentViewModelContext).fragment()
|
||||
return fragment.messageActionViewModelFactory.create(state)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
init {
|
||||
setState { reduceState(this) }
|
||||
}
|
||||
|
||||
private fun reduceState(state: MessageActionState): MessageActionState {
|
||||
val dateFormat = SimpleDateFormat("EEE, d MMM yyyy HH:mm", Locale.getDefault())
|
||||
val event = session.getRoom(roomId)?.getTimeLineEvent(eventId) ?: return state
|
||||
var body: CharSequence? = null
|
||||
val originTs = event.root.originServerTs
|
||||
when (event.root.getClearType()) {
|
||||
EventType.MESSAGE -> {
|
||||
val messageContent: MessageContent? = event.annotations?.editSummary?.aggregatedContent?.toModel()
|
||||
?: event.root.getClearContent().toModel()
|
||||
body = messageContent?.body
|
||||
if (messageContent is MessageTextContent && messageContent.format == MessageType.FORMAT_MATRIX_HTML) {
|
||||
body = eventHtmlRenderer.render(messageContent.formattedBody
|
||||
?: messageContent.body)
|
||||
}
|
||||
}
|
||||
EventType.STATE_ROOM_NAME,
|
||||
EventType.STATE_ROOM_TOPIC,
|
||||
EventType.STATE_ROOM_MEMBER,
|
||||
EventType.STATE_HISTORY_VISIBILITY,
|
||||
EventType.CALL_INVITE,
|
||||
EventType.CALL_HANGUP,
|
||||
EventType.CALL_ANSWER -> {
|
||||
body = noticeEventFormatter.format(event)
|
||||
}
|
||||
override fun initialState(viewModelContext: ViewModelContext): MessageActionState? {
|
||||
val session = (viewModelContext.activity as HasScreenInjector).injector().session()
|
||||
val args: TimelineEventFragmentArgs = viewModelContext.args()
|
||||
val event = session.getRoom(args.roomId)?.getTimeLineEvent(args.eventId)
|
||||
return MessageActionState(
|
||||
args.roomId,
|
||||
args.eventId,
|
||||
args.informationData,
|
||||
event
|
||||
)
|
||||
}
|
||||
return state.copy(
|
||||
userId = event.root.senderId ?: "",
|
||||
senderName = informationData.memberName?.toString() ?: "",
|
||||
messageBody = body,
|
||||
ts = dateFormat.format(Date(originTs ?: 0)),
|
||||
showPreview = body != null,
|
||||
canReact = event.root.type == EventType.MESSAGE && event.sendState.isSent(),
|
||||
senderAvatarPath = informationData.avatarUrl
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
fun resolveBody(state: MessageActionState): CharSequence? {
|
||||
return state.messageBody(eventHtmlRenderer, noticeEventFormatter)
|
||||
}
|
||||
|
||||
}
|
|
@ -15,8 +15,10 @@
|
|||
*/
|
||||
package im.vector.riotredesign.features.home.room.detail.timeline.action
|
||||
|
||||
import com.airbnb.mvrx.FragmentViewModelContext
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
|
@ -77,6 +79,11 @@ class MessageMenuViewModel @AssistedInject constructor(@Assisted initialState: M
|
|||
const val ACTION_FLAG = "ACTION_FLAG"
|
||||
const val ACTION_QUICK_REACT = "ACTION_QUICK_REACT"
|
||||
const val ACTION_VIEW_REACTIONS = "ACTION_VIEW_REACTIONS"
|
||||
|
||||
override fun create(viewModelContext: ViewModelContext, state: MessageMenuState): MessageMenuViewModel? {
|
||||
val fragment: MessageMenuFragment = (viewModelContext as FragmentViewModelContext).fragment()
|
||||
return fragment.messageMenuViewModelFactory.create(state)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
|
|
Loading…
Reference in a new issue