Merge pull request #2053 from vector-im/feature/fix_poll_reply

Feature/fix poll reply
This commit is contained in:
Benoit Marty 2020-09-08 12:19:32 +02:00 committed by GitHub
commit 00b53ee577
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 73 additions and 25 deletions

View File

@ -7,7 +7,7 @@ Features ✨:
Improvements 🙌:
- You can now join room through permalink and within room directory search
- Add long click gesture to copy userId, user display name, room name, room topic and room alias (#1774)
- Fix several issues when uploading bug files (#1889)
- Fix several issues when uploading big files (#1889)
- Do not propose to verify session if there is only one session and 4S is not configured (#1901)
- Call screen does not use proximity sensor (#1735)
@ -27,6 +27,8 @@ Bugfix 🐛:
- Support for image compression on Android 10
- Verification popup won't show
- Android 6: App crash when read Contact permission is granted (#2064)
- JSON for verification events leaks in to the room list (#1246)
- Replies to poll appears in timeline as unsupported events during sending (#1004)
Translations 🗣:
- The SDK is now using SAS string translations from [Weblate Matrix-doc project](https://translate.riot.im/projects/matrix-doc/) (#1909)

View File

@ -347,7 +347,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(@UserId pr
if (userId == senderId) {
sumModel.myVote = optionIndex
}
Timber.v("## POLL adding vote $optionIndex for user $senderId in poll :$relatedEventId ")
Timber.v("## POLL adding vote $optionIndex for user $senderId in poll :$targetEventId ")
} else {
Timber.v("## POLL Ignoring vote (older than known one) eventId:$eventId ")
}
@ -356,7 +356,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(@UserId pr
if (userId == senderId) {
sumModel.myVote = optionIndex
}
Timber.v("## POLL adding vote $optionIndex for user $senderId in poll :$relatedEventId ")
Timber.v("## POLL adding vote $optionIndex for user $senderId in poll :$targetEventId ")
}
sumModel.votes = votes
if (isLocalEcho) {

View File

@ -17,6 +17,16 @@
package org.matrix.android.sdk.internal.session.room.timeline
import io.realm.OrderedCollectionChangeSet
import io.realm.OrderedRealmCollectionChangeListener
import io.realm.Realm
import io.realm.RealmConfiguration
import io.realm.RealmQuery
import io.realm.RealmResults
import io.realm.Sort
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.session.events.model.EventType
@ -44,16 +54,6 @@ import org.matrix.android.sdk.internal.task.configureWith
import org.matrix.android.sdk.internal.util.Debouncer
import org.matrix.android.sdk.internal.util.createBackgroundHandler
import org.matrix.android.sdk.internal.util.createUIHandler
import io.realm.OrderedCollectionChangeSet
import io.realm.OrderedRealmCollectionChangeListener
import io.realm.Realm
import io.realm.RealmConfiguration
import io.realm.RealmQuery
import io.realm.RealmResults
import io.realm.Sort
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import timber.log.Timber
import java.util.Collections
import java.util.UUID
@ -317,12 +317,15 @@ internal class DefaultTimeline(
@Subscribe(threadMode = ThreadMode.MAIN)
fun onLocalEchoCreated(onLocalEchoCreated: OnLocalEchoCreated) {
if (isLive && onLocalEchoCreated.roomId == roomId) {
listeners.forEach {
it.onNewTimelineEvents(listOf(onLocalEchoCreated.timelineEvent.eventId))
// do not add events that would have been filtered
if (listOf(onLocalEchoCreated.timelineEvent).filterEventsWithSettings().isNotEmpty()) {
listeners.forEach {
it.onNewTimelineEvents(listOf(onLocalEchoCreated.timelineEvent.eventId))
}
Timber.v("On local echo created: ${onLocalEchoCreated.timelineEvent.eventId}")
inMemorySendingEvents.add(0, onLocalEchoCreated.timelineEvent)
postSnapshot()
}
Timber.v("On local echo created: $onLocalEchoCreated")
inMemorySendingEvents.add(0, onLocalEchoCreated.timelineEvent)
postSnapshot()
}
}
@ -778,7 +781,7 @@ internal class DefaultTimeline(
val filterEdits = if (settings.filterEdits && it.root.type == EventType.MESSAGE) {
val messageContent = it.root.content.toModel<MessageContent>()
messageContent?.relatesTo?.type != RelationType.REPLACE
messageContent?.relatesTo?.type != RelationType.REPLACE && messageContent?.relatesTo?.type != RelationType.RESPONSE
} else {
true
}

View File

@ -63,6 +63,7 @@ import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.isAttachmentMessage
import org.matrix.android.sdk.api.session.events.model.LocalEcho
import org.matrix.android.sdk.api.session.events.model.isTextMessage
import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.events.model.toModel
@ -1218,6 +1219,8 @@ class RoomDetailViewModel @AssistedInject constructor(
}
private fun handleReplyToOptions(action: RoomDetailAction.ReplyToOptions) {
// Do not allow to reply to unsent local echo
if (LocalEcho.isLocalEchoId(action.eventId)) return
room.sendOptionsReply(action.eventId, action.optionIndex, action.optionValue)
}

View File

@ -20,15 +20,17 @@ import im.vector.app.EmojiCompatWrapper
import im.vector.app.R
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider
import me.gujun.android.span.span
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.model.message.MessageOptionsContent
import org.matrix.android.sdk.api.session.room.model.message.MessageType
import org.matrix.android.sdk.api.session.room.model.message.OPTION_TYPE_BUTTONS
import org.matrix.android.sdk.api.session.room.model.relation.ReactionContent
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
import org.matrix.android.sdk.api.session.room.timeline.getTextEditableContent
import org.matrix.android.sdk.api.session.room.timeline.isReply
import me.gujun.android.span.span
import javax.inject.Inject
class DisplayableEventFormatter @Inject constructor(
@ -51,16 +53,16 @@ class DisplayableEventFormatter @Inject constructor(
val senderName = timelineEvent.senderInfo.disambiguatedDisplayName
when (timelineEvent.root.getClearType()) {
EventType.STICKER -> {
EventType.STICKER -> {
return simpleFormat(senderName, stringProvider.getString(R.string.send_a_sticker), appendAuthor)
}
EventType.REACTION -> {
EventType.REACTION -> {
timelineEvent.root.getClearContent().toModel<ReactionContent>()?.relatesTo?.let {
val emojiSpanned = emojiCompatWrapper.safeEmojiSpanify(it.key)
val emojiSpanned = emojiCompatWrapper.safeEmojiSpanify(stringProvider.getString(R.string.sent_a_reaction, it.key))
return simpleFormat(senderName, emojiSpanned, appendAuthor)
}
}
EventType.MESSAGE -> {
EventType.MESSAGE -> {
timelineEvent.getLastMessageContent()?.let { messageContent ->
when (messageContent.msgType) {
MessageType.MSGTYPE_VERIFICATION_REQUEST -> {
@ -88,13 +90,45 @@ class DisplayableEventFormatter @Inject constructor(
simpleFormat(senderName, messageContent.body, appendAuthor)
}
}
MessageType.MSGTYPE_RESPONSE -> {
// do not show that?
return span { }
}
MessageType.MSGTYPE_OPTIONS -> {
return when (messageContent) {
is MessageOptionsContent -> {
val previewText = if (messageContent.optionType == OPTION_TYPE_BUTTONS) {
stringProvider.getString(R.string.sent_a_bot_buttons)
} else {
stringProvider.getString(R.string.sent_a_poll)
}
simpleFormat(senderName, previewText, appendAuthor)
}
else -> {
span { }
}
}
}
else -> {
return simpleFormat(senderName, messageContent.body, appendAuthor)
}
}
}
}
else -> {
EventType.KEY_VERIFICATION_CANCEL,
EventType.KEY_VERIFICATION_DONE -> {
// cancel and done can appear in timeline, so should have representation
return simpleFormat(senderName, stringProvider.getString(R.string.sent_verification_conclusion), appendAuthor)
}
EventType.KEY_VERIFICATION_START,
EventType.KEY_VERIFICATION_ACCEPT,
EventType.KEY_VERIFICATION_MAC,
EventType.KEY_VERIFICATION_KEY,
EventType.KEY_VERIFICATION_READY,
EventType.CALL_CANDIDATES -> {
return span { }
}
else -> {
return span {
text = noticeEventFormatter.format(timelineEvent) ?: ""
textStyle = "italic"

View File

@ -75,6 +75,8 @@ abstract class MessagePollItem : AbsMessageItem<MessagePollItem.Holder>() {
optionsContent?.options?.forEachIndexed { index, item ->
if (index < buttons.size) {
buttons[index].let {
// current limitation, have to wait for event to be sent in order to reply
it.isEnabled = informationData?.sendState?.isSent() ?: false
it.text = item.label
it.isVisible = true
}

View File

@ -2067,6 +2067,10 @@
<string name="sent_an_audio_file">Audio</string>
<string name="sent_a_file">File</string>
<string name="send_a_sticker">Sticker</string>
<string name="sent_a_poll">Poll</string>
<string name="sent_a_bot_buttons">Bot Buttons</string>
<string name="sent_a_reaction">Reacted with: %s</string>
<string name="sent_verification_conclusion">Verification Conclusion</string>
<string name="verification_request_waiting">Waiting…</string>
<string name="verification_request_other_cancelled">%s cancelled</string>