Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Poll Feature - Timeline #4624

Merged
merged 36 commits into from
Dec 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
e0abd99
Merge branch 'feature/ons/poll' into feature/ons/poll_timeline
Nov 9, 2021
94ae3c6
Merge branch 'feature/ons/poll' into feature/ons/poll_timeline
Nov 11, 2021
eb15197
Merge branch 'develop' into feature/ons/poll_timeline
Nov 16, 2021
ebc131f
Implement new poll content.
Dec 3, 2021
7c26930
Allow sending vote and ending poll.
Dec 3, 2021
a3b11b2
Allow removing poll event.
Dec 3, 2021
2a3a558
Aggregate votes and poll end event.
Dec 3, 2021
06485cf
Implement poll in timeline ui.
Dec 3, 2021
32e8a7e
Remove legacy poll ui.
Dec 3, 2021
c62028d
Implement poll actions bottom sheet.
Dec 3, 2021
0a7df44
Add confirmation dialog to end poll.
Dec 3, 2021
435dc9f
Fix room list preview.
Dec 3, 2021
23ad4e5
Remove legacy implementation classes.
Dec 3, 2021
1df6b33
Add labs flag for polls.
Dec 7, 2021
0d3444b
Fix poll option checkbox color.
Dec 7, 2021
75b544a
Support push notification for poll creation event.
Dec 7, 2021
71d7270
Add room list preview for poll response and end events.
Dec 7, 2021
566f633
Set max length for poll options.
Dec 7, 2021
953fade
Merge branch 'develop' into feature/ons/poll_timeline
Dec 7, 2021
0f11e49
Changelog added.
Dec 7, 2021
04a7590
Code review fixes.
Dec 9, 2021
b2e599e
Merge branch 'develop' into feature/ons/poll_timeline
Dec 9, 2021
d5f8931
Support to show hidden poll events as formatted.
Dec 9, 2021
be9e592
Do not allow to vote the same option twice.
Dec 9, 2021
9b2a3cf
Code review fixes.
Dec 10, 2021
c7ad50a
Code and design review fixes.
Dec 13, 2021
f6dcda6
Code review fixes.
Dec 13, 2021
f028f98
Merge branch 'develop' into feature/ons/poll_timeline
Dec 13, 2021
e2bbc3f
Code review fixes.
Dec 13, 2021
c1ea653
Reorder classes so that it follows the poll status logical order
bmarty Dec 13, 2021
eac06d5
Do some renaming
bmarty Dec 13, 2021
10b39cc
Do some renaming
bmarty Dec 13, 2021
da407ef
Avoid lateinit
bmarty Dec 13, 2021
f29e14f
Rename class
bmarty Dec 13, 2021
0981af3
Remove unused attribute
bmarty Dec 13, 2021
db81ec2
Recycle View a bit more
bmarty Dec 13, 2021
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
1 change: 1 addition & 0 deletions changelog.d/4653.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Poll Feature - Render in timeline
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ object EventType {

// Poll
const val POLL_START = "org.matrix.msc3381.poll.start"
const val POLL_RESPONSE = "org.matrix.msc3381.poll.response"
const val POLL_END = "org.matrix.msc3381.poll.end"

// Unwedging
internal const val DUMMY = "m.dummy"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,24 @@ import com.squareup.moshi.JsonClass
*/
@JsonClass(generateAdapter = true)
data class PollSummaryContent(
// Index of my vote
var myVote: Int? = null,
var myVote: String? = null,
Copy link
Member

@bmarty bmarty Dec 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange to see var in a data class. Also there it no @Json annotations on the fields? Is it a Content of a Matrix message? If not if should be renamed to remove the Content suffix.

EDIT: I think it is not the case, so @JsonClass(generateAdapter = true) can also be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, nice catch. Done.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not done. We need it to be able to (de)serialize in DB as String.

// Array of VoteInfo, list is constructed so that there is only one vote by user
// And that optionIndex is valid
var votes: List<VoteInfo>? = null
) {

fun voteCount(): Int {
return votes?.size ?: 0
}
var votes: List<VoteInfo>? = null,
var votesSummary: Map<String, VoteSummary>? = null,
var totalVotes: Int = 0,
var winnerVoteCount: Int = 0
)

fun voteCountForOption(optionIndex: Int): Int {
return votes?.filter { it.optionIndex == optionIndex }?.count() ?: 0
}
}
@JsonClass(generateAdapter = true)
data class VoteSummary(
val total: Int = 0,
val percentage: Double = 0.0
)

@JsonClass(generateAdapter = true)
data class VoteInfo(
val userId: String,
val optionIndex: Int,
val option: String,
val voteTimestamp: Long
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2021 The Matrix.org Foundation C.I.C.
*
* 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 org.matrix.android.sdk.api.session.room.model.message

import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent

/**
* Class representing the org.matrix.msc3381.poll.end event content
*/
@JsonClass(generateAdapter = true)
data class MessageEndPollContent(
@Json(name = "m.relates_to") val relatesTo: RelationDefaultContent? = null
)

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,18 @@ package org.matrix.android.sdk.api.session.room.model.message

import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent

@JsonClass(generateAdapter = true)
data class MessagePollContent(
@Json(name = "org.matrix.msc3381.poll.start") val pollCreationInfo: PollCreationInfo? = null
)
/**
* Local message type, not from server
*/
@Transient
override val msgType: String = MessageType.MSGTYPE_POLL_START,
@Json(name = "body") override val body: String = "",
@Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null,
@Json(name = "m.new_content") override val newContent: Content? = null,
@Json(name = "org.matrix.msc3381.poll.start") val pollCreationInfo: PollCreationInfo? = null
) : MessageContent
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent

/**
* Ref: https://github.com/matrix-org/matrix-doc/pull/2192
*/
@JsonClass(generateAdapter = true)
data class MessagePollResponseContent(
@Json(name = MessageContent.MSG_TYPE_JSON_KEY) override val msgType: String = MessageType.MSGTYPE_RESPONSE,
@Json(name = "body") override val body: String,
/**
* Local message type, not from server
*/
@Transient
override val msgType: String = MessageType.MSGTYPE_POLL_RESPONSE,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not correct. MessagePollResponseContent must not inherit from MessageContent, since the type is not "m.room.message".
When I answer a poll from ElementWeb I got this FTR:

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we discussed, I changed it as we did for sticker events.

@Json(name = "body") override val body: String = "",
@Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null,
@Json(name = "m.new_content") override val newContent: Content? = null
@Json(name = "m.new_content") override val newContent: Content? = null,
@Json(name = "org.matrix.msc3381.poll.response") val response: PollResponse? = null
) : MessageContent
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,18 @@ object MessageType {
const val MSGTYPE_VIDEO = "m.video"
const val MSGTYPE_LOCATION = "m.location"
const val MSGTYPE_FILE = "m.file"
const val MSGTYPE_OPTIONS = "org.matrix.options"
const val MSGTYPE_RESPONSE = "org.matrix.response"
const val MSGTYPE_POLL_CLOSED = "org.matrix.poll_closed"

const val MSGTYPE_VERIFICATION_REQUEST = "m.key.verification.request"

// Add, in local, a fake message type in order to StickerMessage can inherit Message class
// Because sticker isn't a message type but a event type without msgtype field
const val MSGTYPE_STICKER_LOCAL = "org.matrix.android.sdk.sticker"

// Fake message types for poll events to be able to inherit them from MessageContent
// Because poll events are not message events and they don't hanve msgtype field
const val MSGTYPE_POLL_START = "org.matrix.android.sdk.poll.start"
const val MSGTYPE_POLL_RESPONSE = "org.matrix.android.sdk.poll.response"

const val MSGTYPE_CONFETTI = "nic.custom.confetti"
const val MSGTYPE_SNOWFALL = "io.element.effect.snowfall"
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020 The Matrix.org Foundation C.I.C.
* Copyright 2021 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -19,11 +19,7 @@ package org.matrix.android.sdk.api.session.room.model.message
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

/**
* Ref: https://github.com/matrix-org/matrix-doc/pull/2192
*/
@JsonClass(generateAdapter = true)
data class OptionItem(
@Json(name = "label") val label: String?,
@Json(name = "value") val value: String?
data class PollResponse(
@Json(name = "answers") val answers: List<String>? = null
)
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,17 @@ interface SendService {
/**
* Method to send a poll response.
* @param pollEventId the poll currently replied to
* @param optionIndex The reply index
* @param optionValue The option value (for compatibility)
* @param answerId The id of the answer
* @return a [Cancelable]
*/
fun sendOptionsReply(pollEventId: String, optionIndex: Int, optionValue: String): Cancelable
fun voteToPoll(pollEventId: String, answerId: String): Cancelable

/**
* End a poll in the room.
* @param pollEventId event id of the poll
* @return a [Cancelable]
*/
fun endPoll(pollEventId: String): Cancelable

/**
* Redact (delete) the given event.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ object RoomSummaryConstants {
EventType.CALL_ANSWER,
EventType.ENCRYPTED,
EventType.STICKER,
EventType.REACTION
EventType.REACTION,
EventType.POLL_START
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.model.EventAnnotationsSummary
import org.matrix.android.sdk.api.session.room.model.ReadReceipt
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
import org.matrix.android.sdk.api.session.room.model.message.MessageStickerContent
import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
Expand Down Expand Up @@ -126,10 +127,10 @@ fun TimelineEvent.getEditedEventId(): String? {
* Get last MessageContent, after a possible edition
*/
fun TimelineEvent.getLastMessageContent(): MessageContent? {
return if (root.getClearType() == EventType.STICKER) {
root.getClearContent().toModel<MessageStickerContent>()
} else {
(annotations?.editSummary?.latestContent ?: root.getClearContent()).toModel()
return when (root.getClearType()) {
EventType.STICKER -> root.getClearContent().toModel<MessageStickerContent>()
EventType.POLL_START -> root.getClearContent().toModel<MessagePollContent>()
else -> (annotations?.editSummary?.latestContent ?: root.getClearContent()).toModel()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageFileContent
import org.matrix.android.sdk.api.session.room.model.message.MessageImageContent
import org.matrix.android.sdk.api.session.room.model.message.MessageLocationContent
import org.matrix.android.sdk.api.session.room.model.message.MessageNoticeContent
import org.matrix.android.sdk.api.session.room.model.message.MessageOptionsContent
import org.matrix.android.sdk.api.session.room.model.message.MessagePollResponseContent
import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent
import org.matrix.android.sdk.api.session.room.model.message.MessageType
Expand Down Expand Up @@ -57,8 +56,7 @@ object MoshiProvider {
.registerSubtype(MessageLocationContent::class.java, MessageType.MSGTYPE_LOCATION)
.registerSubtype(MessageFileContent::class.java, MessageType.MSGTYPE_FILE)
.registerSubtype(MessageVerificationRequestContent::class.java, MessageType.MSGTYPE_VERIFICATION_REQUEST)
.registerSubtype(MessageOptionsContent::class.java, MessageType.MSGTYPE_OPTIONS)
.registerSubtype(MessagePollResponseContent::class.java, MessageType.MSGTYPE_RESPONSE)
.registerSubtype(MessagePollResponseContent::class.java, MessageType.MSGTYPE_POLL_RESPONSE)
)
.add(SerializeNulls.JSON_ADAPTER_FACTORY)
.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ internal class DefaultProcessEventForPushTask @Inject constructor(

val allEvents = (newJoinEvents + inviteEvents).filter { event ->
when (event.type) {
EventType.POLL_START,
EventType.MESSAGE,
EventType.REDACTION,
EventType.ENCRYPTED,
Expand Down
Loading