forked from GitHub-Mirror/riotX-android
Menu action for non room messages
This commit is contained in:
parent
7409003949
commit
5cf9deb329
@ -23,6 +23,7 @@ import android.view.ViewGroup
|
|||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.lifecycle.ViewModelProviders
|
import androidx.lifecycle.ViewModelProviders
|
||||||
import butterknife.BindView
|
import butterknife.BindView
|
||||||
import butterknife.ButterKnife
|
import butterknife.ButterKnife
|
||||||
@ -35,6 +36,7 @@ import im.vector.riotredesign.R
|
|||||||
import im.vector.riotredesign.core.glide.GlideApp
|
import im.vector.riotredesign.core.glide.GlideApp
|
||||||
import im.vector.riotredesign.features.home.AvatarRenderer
|
import im.vector.riotredesign.features.home.AvatarRenderer
|
||||||
import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
|
import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
|
||||||
|
import kotlinx.android.synthetic.main.bottom_sheet_message_actions.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bottom sheet fragment that shows a message preview with list of contextual actions
|
* Bottom sheet fragment that shows a message preview with list of contextual actions
|
||||||
@ -115,20 +117,27 @@ class MessageActionsBottomSheet : BaseMvRxBottomSheetDialog() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun invalidate() = withState(viewModel) {
|
override fun invalidate() = withState(viewModel) {
|
||||||
senderNameTextView.text = it.senderName
|
if (it.showPreview) {
|
||||||
messageBodyTextView.text = it.messageBody
|
bottom_sheet_message_preview.isVisible = true
|
||||||
messageTimestampText.text = it.ts
|
senderNameTextView.text = it.senderName
|
||||||
|
messageBodyTextView.text = it.messageBody
|
||||||
|
messageTimestampText.text = it.ts
|
||||||
|
|
||||||
GlideApp.with(this).clear(senderAvatarImageView)
|
GlideApp.with(this).clear(senderAvatarImageView)
|
||||||
if (it.senderAvatarPath != null) {
|
if (it.senderAvatarPath != null) {
|
||||||
GlideApp.with(this)
|
GlideApp.with(this)
|
||||||
.load(it.senderAvatarPath)
|
.load(it.senderAvatarPath)
|
||||||
.circleCrop()
|
.circleCrop()
|
||||||
.placeholder(AvatarRenderer.getPlaceholderDrawable(requireContext(), it.userId, it.senderName))
|
.placeholder(AvatarRenderer.getPlaceholderDrawable(requireContext(), it.userId, it.senderName))
|
||||||
.into(senderAvatarImageView)
|
.into(senderAvatarImageView)
|
||||||
|
} else {
|
||||||
|
senderAvatarImageView.setImageDrawable(AvatarRenderer.getPlaceholderDrawable(requireContext(), it.userId, it.senderName))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
senderAvatarImageView.setImageDrawable(AvatarRenderer.getPlaceholderDrawable(requireContext(), it.userId, it.senderName))
|
bottom_sheet_message_preview.isVisible = false
|
||||||
}
|
}
|
||||||
|
quickReactBottomDivider.isVisible = it.canReact
|
||||||
|
bottom_sheet_quick_reaction_container.isVisible = it.canReact
|
||||||
return@withState
|
return@withState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import com.airbnb.mvrx.MvRxState
|
|||||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||||
import com.airbnb.mvrx.ViewModelContext
|
import com.airbnb.mvrx.ViewModelContext
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
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.message.MessageContent
|
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.MessageTextContent
|
||||||
@ -34,10 +35,12 @@ import java.util.*
|
|||||||
|
|
||||||
|
|
||||||
data class MessageActionState(
|
data class MessageActionState(
|
||||||
val userId: String,
|
val userId: String = "",
|
||||||
val senderName: String,
|
val senderName: String = "",
|
||||||
val messageBody: CharSequence,
|
val messageBody: CharSequence? = null,
|
||||||
val ts: String?,
|
val ts: String? = null,
|
||||||
|
val showPreview: Boolean = false,
|
||||||
|
val canReact: Boolean = false,
|
||||||
val senderAvatarPath: String? = null)
|
val senderAvatarPath: String? = null)
|
||||||
: MvRxState
|
: MvRxState
|
||||||
|
|
||||||
@ -59,21 +62,21 @@ class MessageActionsViewModel(initialState: MessageActionState) : VectorViewMode
|
|||||||
val messageContent: MessageContent? = event.annotations?.editSummary?.aggregatedContent?.toModel()
|
val messageContent: MessageContent? = event.annotations?.editSummary?.aggregatedContent?.toModel()
|
||||||
?: event.root.content.toModel()
|
?: event.root.content.toModel()
|
||||||
val originTs = event.root.originServerTs
|
val originTs = event.root.originServerTs
|
||||||
var body: CharSequence = messageContent?.body ?: ""
|
var body: CharSequence? = messageContent?.body
|
||||||
if (messageContent is MessageTextContent && messageContent.format == MessageType.FORMAT_MATRIX_HTML) {
|
if (messageContent is MessageTextContent && messageContent.format == MessageType.FORMAT_MATRIX_HTML) {
|
||||||
val parser = Parser.builder().build()
|
val parser = Parser.builder().build()
|
||||||
val document = parser.parse(messageContent.formattedBody ?: messageContent.body)
|
val document = parser.parse(messageContent.formattedBody ?: messageContent.body)
|
||||||
// val renderer = HtmlRenderer.builder().build()
|
|
||||||
body = Markwon.builder(viewModelContext.activity)
|
body = Markwon.builder(viewModelContext.activity)
|
||||||
.usePlugin(HtmlPlugin.create()).build().render(document)
|
.usePlugin(HtmlPlugin.create()).build().render(document)
|
||||||
// body = renderer.render(document)
|
|
||||||
}
|
}
|
||||||
MessageActionState(
|
MessageActionState(
|
||||||
event.root.sender ?: "",
|
userId = event.root.sender ?: "",
|
||||||
parcel.informationData.memberName.toString(),
|
senderName = parcel.informationData.memberName.toString(),
|
||||||
body,
|
messageBody = body,
|
||||||
dateFormat.format(Date(originTs ?: 0)),
|
ts = dateFormat.format(Date(originTs ?: 0)),
|
||||||
currentSession.contentUrlResolver().resolveFullSize(parcel.informationData.avatarUrl)
|
showPreview = event.root.type == EventType.MESSAGE,
|
||||||
|
canReact = event.root.type == EventType.MESSAGE,
|
||||||
|
senderAvatarPath = currentSession.contentUrlResolver().resolveFullSize(parcel.informationData.avatarUrl)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
//can this happen?
|
//can this happen?
|
||||||
|
@ -73,7 +73,9 @@ class MessageMenuViewModel(initialState: MessageMenuState) : VectorViewModel<Mes
|
|||||||
}
|
}
|
||||||
//TODO is downloading attachement?
|
//TODO is downloading attachement?
|
||||||
|
|
||||||
this.add(SimpleAction(ACTION_ADD_REACTION, R.string.message_add_reaction, R.drawable.ic_add_reaction, event.root.eventId))
|
if (canReact(event, messageContent)) {
|
||||||
|
this.add(SimpleAction(ACTION_ADD_REACTION, R.string.message_add_reaction, R.drawable.ic_add_reaction, event.root.eventId))
|
||||||
|
}
|
||||||
if (canCopy(type)) {
|
if (canCopy(type)) {
|
||||||
//TODO copy images? html? see ClipBoard
|
//TODO copy images? html? see ClipBoard
|
||||||
this.add(SimpleAction(ACTION_COPY, R.string.copy, R.drawable.ic_copy, messageContent!!.body))
|
this.add(SimpleAction(ACTION_COPY, R.string.copy, R.drawable.ic_copy, messageContent!!.body))
|
||||||
@ -125,7 +127,7 @@ class MessageMenuViewModel(initialState: MessageMenuState) : VectorViewModel<Mes
|
|||||||
}
|
}
|
||||||
this.add(SimpleAction(ACTION_COPY_PERMALINK, R.string.permalink, R.drawable.ic_permalink, parcel.eventId))
|
this.add(SimpleAction(ACTION_COPY_PERMALINK, R.string.permalink, R.drawable.ic_permalink, parcel.eventId))
|
||||||
|
|
||||||
if (currentSession.sessionParams.credentials.userId != event.root.sender) {
|
if (currentSession.sessionParams.credentials.userId != event.root.sender && event.root.type == EventType.MESSAGE) {
|
||||||
//not sent by me
|
//not sent by me
|
||||||
this.add(SimpleAction(ACTION_FLAG, R.string.report_content, R.drawable.ic_flag, parcel.eventId))
|
this.add(SimpleAction(ACTION_FLAG, R.string.report_content, R.drawable.ic_flag, parcel.eventId))
|
||||||
}
|
}
|
||||||
@ -149,6 +151,11 @@ class MessageMenuViewModel(initialState: MessageMenuState) : VectorViewModel<Mes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun canReact(event: TimelineEvent, messageContent: MessageContent?): Boolean {
|
||||||
|
//Only event of type Event.EVENT_TYPE_MESSAGE are supported for the moment
|
||||||
|
return event.root.type == EventType.MESSAGE
|
||||||
|
}
|
||||||
|
|
||||||
private fun canQuote(event: TimelineEvent, messageContent: MessageContent?): Boolean {
|
private fun canQuote(event: TimelineEvent, messageContent: MessageContent?): Boolean {
|
||||||
//Only event of type Event.EVENT_TYPE_MESSAGE are supported for the moment
|
//Only event of type Event.EVENT_TYPE_MESSAGE are supported for the moment
|
||||||
if (event.root.type != EventType.MESSAGE) return false
|
if (event.root.type != EventType.MESSAGE) return false
|
||||||
|
@ -32,15 +32,14 @@ enum class TriggleState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data class QuickReactionState(
|
data class QuickReactionState(
|
||||||
val agreeTrigleState: TriggleState,
|
val agreeTrigleState: TriggleState = TriggleState.NONE,
|
||||||
val likeTriggleState: TriggleState,
|
val likeTriggleState: TriggleState = TriggleState.NONE,
|
||||||
/** Pair of 'clickedOn' and current toggles state*/
|
/** Pair of 'clickedOn' and current toggles state*/
|
||||||
val selectionResult: Pair<String, List<String>>? = null,
|
val selectionResult: Pair<String, List<String>>? = null,
|
||||||
val eventId: String) : MvRxState
|
val eventId: String = "") : MvRxState
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Quick reaction view model
|
* Quick reaction view model
|
||||||
* TODO: configure initial state from event
|
|
||||||
*/
|
*/
|
||||||
class QuickReactionViewModel(initialState: QuickReactionState) : VectorViewModel<QuickReactionState>(initialState) {
|
class QuickReactionViewModel(initialState: QuickReactionState) : VectorViewModel<QuickReactionState>(initialState) {
|
||||||
|
|
||||||
@ -88,15 +87,15 @@ class QuickReactionViewModel(initialState: QuickReactionState) : VectorViewModel
|
|||||||
private fun getReactions(state: QuickReactionState, newState1: TriggleState?, newState2: TriggleState?): List<String> {
|
private fun getReactions(state: QuickReactionState, newState1: TriggleState?, newState2: TriggleState?): List<String> {
|
||||||
return ArrayList<String>(4).apply {
|
return ArrayList<String>(4).apply {
|
||||||
when (newState2 ?: state.likeTriggleState) {
|
when (newState2 ?: state.likeTriggleState) {
|
||||||
TriggleState.FIRST -> add(likePositive)
|
TriggleState.FIRST -> add(likePositive)
|
||||||
TriggleState.SECOND -> add(likeNegative)
|
TriggleState.SECOND -> add(likeNegative)
|
||||||
else -> {
|
else -> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
when (newState1 ?: state.agreeTrigleState) {
|
when (newState1 ?: state.agreeTrigleState) {
|
||||||
TriggleState.FIRST -> add(agreePositive)
|
TriggleState.FIRST -> add(agreePositive)
|
||||||
TriggleState.SECOND -> add(agreeNegative)
|
TriggleState.SECOND -> add(agreeNegative)
|
||||||
else -> {
|
else -> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,9 +113,9 @@ class QuickReactionViewModel(initialState: QuickReactionState) : VectorViewModel
|
|||||||
return when (reaction) {
|
return when (reaction) {
|
||||||
agreePositive -> agreeNegative
|
agreePositive -> agreeNegative
|
||||||
agreeNegative -> agreePositive
|
agreeNegative -> agreePositive
|
||||||
likePositive -> likeNegative
|
likePositive -> likeNegative
|
||||||
likeNegative -> likePositive
|
likeNegative -> likePositive
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,6 @@ abstract class NoticeItem : BaseEventItem<NoticeItem.Holder>() {
|
|||||||
@EpoxyAttribute
|
@EpoxyAttribute
|
||||||
var baseCallback: TimelineEventController.BaseCallback? = null
|
var baseCallback: TimelineEventController.BaseCallback? = null
|
||||||
|
|
||||||
|
|
||||||
private var longClickListener = View.OnLongClickListener {
|
private var longClickListener = View.OnLongClickListener {
|
||||||
baseCallback?.onEventLongClicked(informationData, null, it)
|
baseCallback?.onEventLongClicked(informationData, null, it)
|
||||||
baseCallback != null
|
baseCallback != null
|
||||||
|
@ -86,7 +86,8 @@
|
|||||||
tools:text="Friday 8pm" />
|
tools:text="Friday 8pm" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<View
|
||||||
|
android:id="@+id/quickReactTopDivider"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
android:background="?attr/vctr_list_divider_color" />
|
android:background="?attr/vctr_list_divider_color" />
|
||||||
@ -94,18 +95,22 @@
|
|||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/bottom_sheet_quick_reaction_container"
|
android:id="@+id/bottom_sheet_quick_reaction_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content"
|
||||||
|
tools:background="@android:color/holo_green_light"
|
||||||
|
tools:layout_height="180dp" />
|
||||||
|
|
||||||
<LinearLayout
|
<View
|
||||||
|
android:id="@+id/quickReactBottomDivider"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
android:background="?attr/vctr_list_divider_color" />
|
android:background="?attr/vctr_list_divider_color" />
|
||||||
|
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/bottom_sheet_menu_container"
|
android:id="@+id/bottom_sheet_menu_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content"
|
||||||
|
tools:background="@android:color/holo_blue_dark"
|
||||||
|
tools:layout_height="250dp" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
Loading…
Reference in New Issue
Block a user