mirror of
https://github.com/element-hq/element-android
synced 2024-11-23 09:55:40 +03:00
Merge pull request #7611 from vector-im/feature/fre/voice_broadcast_deletion
Be less restritive when pruning redacted events
This commit is contained in:
commit
49199bd5e2
39 changed files with 175 additions and 138 deletions
|
@ -66,7 +66,7 @@ class PollAggregationTest : InstrumentedTest {
|
|||
|
||||
val aliceEventsListener = object : Timeline.Listener {
|
||||
override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
|
||||
snapshot.firstOrNull { it.root.getClearType() in EventType.POLL_START }?.let { pollEvent ->
|
||||
snapshot.firstOrNull { it.root.getClearType() in EventType.POLL_START.values }?.let { pollEvent ->
|
||||
val pollEventId = pollEvent.eventId
|
||||
val pollContent = pollEvent.root.content?.toModel<MessagePollContent>()
|
||||
val pollSummary = pollEvent.annotations?.pollResponseSummary
|
||||
|
|
|
@ -26,10 +26,8 @@ import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult
|
|||
import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent
|
||||
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.MessageType
|
||||
import org.matrix.android.sdk.api.session.room.model.message.asMessageAudioEvent
|
||||
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
|
||||
|
@ -390,24 +388,18 @@ fun Event.isLocationMessage(): Boolean {
|
|||
}
|
||||
}
|
||||
|
||||
fun Event.isPoll(): Boolean = getClearType() in EventType.POLL_START || getClearType() in EventType.POLL_END
|
||||
fun Event.isPoll(): Boolean = getClearType() in EventType.POLL_START.values || getClearType() in EventType.POLL_END.values
|
||||
|
||||
fun Event.isSticker(): Boolean = getClearType() == EventType.STICKER
|
||||
|
||||
fun Event.isLiveLocation(): Boolean = getClearType() in EventType.STATE_ROOM_BEACON_INFO
|
||||
fun Event.isLiveLocation(): Boolean = getClearType() in EventType.STATE_ROOM_BEACON_INFO.values
|
||||
|
||||
fun Event.getRelationContent(): RelationDefaultContent? {
|
||||
return if (isEncrypted()) {
|
||||
content.toModel<EncryptedEventContent>()?.relatesTo
|
||||
} else {
|
||||
content.toModel<MessageContent>()?.relatesTo ?: run {
|
||||
// Special cases when there is only a local msgtype for some event types
|
||||
when (getClearType()) {
|
||||
EventType.STICKER -> getClearContent().toModel<MessageStickerContent>()?.relatesTo
|
||||
in EventType.BEACON_LOCATION_DATA -> getClearContent().toModel<MessageBeaconLocationDataContent>()?.relatesTo
|
||||
else -> getClearContent()?.get("m.relates_to")?.toContent().toModel()
|
||||
}
|
||||
}
|
||||
content.toModel<MessageContent>()?.relatesTo
|
||||
?: getClearContent()?.get("m.relates_to")?.toContent().toModel() // Special cases when there is only a local msgtype for some event types
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -451,7 +443,7 @@ fun Event.getPollContent(): MessagePollContent? {
|
|||
}
|
||||
|
||||
fun Event.supportsNotification() =
|
||||
this.getClearType() in EventType.MESSAGE + EventType.POLL_START + EventType.STATE_ROOM_BEACON_INFO
|
||||
this.getClearType() in EventType.MESSAGE + EventType.POLL_START.values + EventType.STATE_ROOM_BEACON_INFO.values
|
||||
|
||||
fun Event.isContentReportable() =
|
||||
this.getClearType() in EventType.MESSAGE + EventType.STATE_ROOM_BEACON_INFO
|
||||
this.getClearType() in EventType.MESSAGE + EventType.STATE_ROOM_BEACON_INFO.values
|
||||
|
|
|
@ -49,11 +49,10 @@ object EventType {
|
|||
const val STATE_ROOM_JOIN_RULES = "m.room.join_rules"
|
||||
const val STATE_ROOM_GUEST_ACCESS = "m.room.guest_access"
|
||||
const val STATE_ROOM_POWER_LEVELS = "m.room.power_levels"
|
||||
val STATE_ROOM_BEACON_INFO = listOf("org.matrix.msc3672.beacon_info", "m.beacon_info")
|
||||
val BEACON_LOCATION_DATA = listOf("org.matrix.msc3672.beacon", "m.beacon")
|
||||
val STATE_ROOM_BEACON_INFO = StableUnstableId(stable = "m.beacon_info", unstable = "org.matrix.msc3672.beacon_info")
|
||||
val BEACON_LOCATION_DATA = StableUnstableId(stable = "m.beacon", unstable = "org.matrix.msc3672.beacon")
|
||||
|
||||
const val STATE_SPACE_CHILD = "m.space.child"
|
||||
|
||||
const val STATE_SPACE_PARENT = "m.space.parent"
|
||||
|
||||
/**
|
||||
|
@ -81,8 +80,7 @@ object EventType {
|
|||
const val CALL_NEGOTIATE = "m.call.negotiate"
|
||||
const val CALL_REJECT = "m.call.reject"
|
||||
const val CALL_HANGUP = "m.call.hangup"
|
||||
const val CALL_ASSERTED_IDENTITY = "m.call.asserted_identity"
|
||||
const val CALL_ASSERTED_IDENTITY_PREFIX = "org.matrix.call.asserted_identity"
|
||||
val CALL_ASSERTED_IDENTITY = StableUnstableId(stable = "m.call.asserted_identity", unstable = "org.matrix.call.asserted_identity")
|
||||
|
||||
// This type is not processed by the client, just sent to the server
|
||||
const val CALL_REPLACES = "m.call.replaces"
|
||||
|
@ -90,10 +88,7 @@ object EventType {
|
|||
// Key share events
|
||||
const val ROOM_KEY_REQUEST = "m.room_key_request"
|
||||
const val FORWARDED_ROOM_KEY = "m.forwarded_room_key"
|
||||
val ROOM_KEY_WITHHELD = StableUnstableId(
|
||||
stable = "m.room_key.withheld",
|
||||
unstable = "org.matrix.room_key.withheld"
|
||||
)
|
||||
val ROOM_KEY_WITHHELD = StableUnstableId(stable = "m.room_key.withheld", unstable = "org.matrix.room_key.withheld")
|
||||
|
||||
const val REQUEST_SECRET = "m.secret.request"
|
||||
const val SEND_SECRET = "m.secret.send"
|
||||
|
@ -111,9 +106,9 @@ object EventType {
|
|||
const val REACTION = "m.reaction"
|
||||
|
||||
// Poll
|
||||
val POLL_START = listOf("org.matrix.msc3381.poll.start", "m.poll.start")
|
||||
val POLL_RESPONSE = listOf("org.matrix.msc3381.poll.response", "m.poll.response")
|
||||
val POLL_END = listOf("org.matrix.msc3381.poll.end", "m.poll.end")
|
||||
val POLL_START = StableUnstableId(stable = "m.poll.start", unstable = "org.matrix.msc3381.poll.start")
|
||||
val POLL_RESPONSE = StableUnstableId(stable = "m.poll.response", unstable = "org.matrix.msc3381.poll.response")
|
||||
val POLL_END = StableUnstableId(stable = "m.poll.end", unstable = "org.matrix.msc3381.poll.end")
|
||||
|
||||
// Unwedging
|
||||
internal const val DUMMY = "m.dummy"
|
||||
|
|
|
@ -34,7 +34,7 @@ data class MessageStickerContent(
|
|||
* Required. A textual representation of the image. This could be the alt text of the image, the filename of the image,
|
||||
* or some kind of content description for accessibility e.g. 'image attachment'.
|
||||
*/
|
||||
@Json(name = "body") override val body: String,
|
||||
@Json(name = "body") override val body: String = "",
|
||||
|
||||
/**
|
||||
* Metadata about the image referred to in url.
|
||||
|
|
|
@ -33,5 +33,7 @@ object RoomSummaryConstants {
|
|||
EventType.ENCRYPTED,
|
||||
EventType.STICKER,
|
||||
EventType.REACTION
|
||||
) + EventType.POLL_START + EventType.STATE_ROOM_BEACON_INFO
|
||||
) +
|
||||
EventType.POLL_START.values +
|
||||
EventType.STATE_ROOM_BEACON_INFO.values
|
||||
}
|
||||
|
|
|
@ -147,9 +147,9 @@ fun TimelineEvent.getLastMessageContent(): MessageContent? {
|
|||
// Polls/Beacon are not message contents like others as there is no msgtype subtype to discriminate moshi parsing
|
||||
// so toModel<MessageContent> won't parse them correctly
|
||||
// It's discriminated on event type instead. Maybe it shouldn't be MessageContent at all to avoid confusion?
|
||||
in EventType.POLL_START -> (getLastEditNewContent() ?: root.getClearContent()).toModel<MessagePollContent>()
|
||||
in EventType.STATE_ROOM_BEACON_INFO -> (getLastEditNewContent() ?: root.getClearContent()).toModel<MessageBeaconInfoContent>()
|
||||
in EventType.BEACON_LOCATION_DATA -> (getLastEditNewContent() ?: root.getClearContent()).toModel<MessageBeaconLocationDataContent>()
|
||||
in EventType.POLL_START.values -> (getLastEditNewContent() ?: root.getClearContent()).toModel<MessagePollContent>()
|
||||
in EventType.STATE_ROOM_BEACON_INFO.values -> (getLastEditNewContent() ?: root.getClearContent()).toModel<MessageBeaconInfoContent>()
|
||||
in EventType.BEACON_LOCATION_DATA.values -> (getLastEditNewContent() ?: root.getClearContent()).toModel<MessageBeaconLocationDataContent>()
|
||||
else -> (getLastEditNewContent() ?: root.getClearContent()).toModel()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,9 +41,8 @@ internal class CallEventProcessor @Inject constructor(private val callSignalingH
|
|||
EventType.CALL_INVITE,
|
||||
EventType.CALL_HANGUP,
|
||||
EventType.ENCRYPTED,
|
||||
EventType.CALL_ASSERTED_IDENTITY,
|
||||
EventType.CALL_ASSERTED_IDENTITY_PREFIX
|
||||
)
|
||||
) +
|
||||
EventType.CALL_ASSERTED_IDENTITY.values
|
||||
|
||||
private val eventsToPostProcess = mutableListOf<Event>()
|
||||
|
||||
|
|
|
@ -84,8 +84,7 @@ internal class CallSignalingHandler @Inject constructor(
|
|||
EventType.CALL_NEGOTIATE -> {
|
||||
handleCallNegotiateEvent(event)
|
||||
}
|
||||
EventType.CALL_ASSERTED_IDENTITY,
|
||||
EventType.CALL_ASSERTED_IDENTITY_PREFIX -> {
|
||||
in EventType.CALL_ASSERTED_IDENTITY.values -> {
|
||||
handleCallAssertedIdentityEvent(event)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,8 +56,8 @@ internal class DefaultProcessEventForPushTask @Inject constructor(
|
|||
|
||||
val allEvents = (newJoinEvents + inviteEvents).filter { event ->
|
||||
when (event.type) {
|
||||
in EventType.POLL_START,
|
||||
in EventType.STATE_ROOM_BEACON_INFO,
|
||||
in EventType.POLL_START.values,
|
||||
in EventType.STATE_ROOM_BEACON_INFO.values,
|
||||
EventType.MESSAGE,
|
||||
EventType.REDACTION,
|
||||
EventType.ENCRYPTED,
|
||||
|
|
|
@ -91,7 +91,12 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
|
|||
EventType.KEY_VERIFICATION_READY,
|
||||
EventType.KEY_VERIFICATION_KEY,
|
||||
EventType.ENCRYPTED
|
||||
) + EventType.POLL_START + EventType.POLL_RESPONSE + EventType.POLL_END + EventType.STATE_ROOM_BEACON_INFO + EventType.BEACON_LOCATION_DATA
|
||||
) +
|
||||
EventType.POLL_START.values +
|
||||
EventType.POLL_RESPONSE.values +
|
||||
EventType.POLL_END.values +
|
||||
EventType.STATE_ROOM_BEACON_INFO.values +
|
||||
EventType.BEACON_LOCATION_DATA.values
|
||||
|
||||
override fun shouldProcess(eventId: String, eventType: String, insertType: EventInsertType): Boolean {
|
||||
return allowedTypes.contains(eventType)
|
||||
|
@ -208,7 +213,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
in EventType.POLL_START -> {
|
||||
in EventType.POLL_START.values -> {
|
||||
val content: MessagePollContent? = event.content.toModel()
|
||||
if (content?.relatesTo?.type == RelationType.REPLACE) {
|
||||
Timber.v("###REPLACE in room $roomId for event ${event.eventId}")
|
||||
|
@ -216,26 +221,26 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
|
|||
handleReplace(realm, event, roomId, isLocalEcho, content.relatesTo.eventId)
|
||||
}
|
||||
}
|
||||
in EventType.POLL_RESPONSE -> {
|
||||
in EventType.POLL_RESPONSE.values -> {
|
||||
event.content.toModel<MessagePollResponseContent>(catchError = true)?.let {
|
||||
sessionManager.getSessionComponent(sessionId)?.session()?.let { session ->
|
||||
pollAggregationProcessor.handlePollResponseEvent(session, realm, event)
|
||||
}
|
||||
}
|
||||
}
|
||||
in EventType.POLL_END -> {
|
||||
in EventType.POLL_END.values -> {
|
||||
sessionManager.getSessionComponent(sessionId)?.session()?.let { session ->
|
||||
getPowerLevelsHelper(event.roomId)?.let {
|
||||
pollAggregationProcessor.handlePollEndEvent(session, it, realm, event)
|
||||
}
|
||||
}
|
||||
}
|
||||
in EventType.STATE_ROOM_BEACON_INFO -> {
|
||||
in EventType.STATE_ROOM_BEACON_INFO.values -> {
|
||||
event.content.toModel<MessageBeaconInfoContent>(catchError = true)?.let {
|
||||
liveLocationAggregationProcessor.handleBeaconInfo(realm, event, it, roomId, isLocalEcho)
|
||||
}
|
||||
}
|
||||
in EventType.BEACON_LOCATION_DATA -> {
|
||||
in EventType.BEACON_LOCATION_DATA.values -> {
|
||||
handleBeaconLocationData(event, realm, roomId, isLocalEcho)
|
||||
}
|
||||
else -> Timber.v("UnHandled event ${event.eventId}")
|
||||
|
@ -324,7 +329,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
if (event.getClearType() in EventType.POLL_START) {
|
||||
if (event.getClearType() in EventType.POLL_START.values) {
|
||||
pollAggregationProcessor.handlePollStartEvent(realm, event)
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ internal class DefaultGetActiveBeaconInfoForUserTask @Inject constructor(
|
|||
) : GetActiveBeaconInfoForUserTask {
|
||||
|
||||
override suspend fun execute(params: GetActiveBeaconInfoForUserTask.Params): Event? {
|
||||
return EventType.STATE_ROOM_BEACON_INFO
|
||||
return EventType.STATE_ROOM_BEACON_INFO.values
|
||||
.mapNotNull {
|
||||
stateEventDataSource.getStateEvent(
|
||||
roomId = params.roomId,
|
||||
|
|
|
@ -48,7 +48,7 @@ internal class LiveLocationShareRedactionEventProcessor @Inject constructor() :
|
|||
val redactedEvent = EventEntity.where(realm, eventId = event.redacts).findFirst()
|
||||
?: return
|
||||
|
||||
if (redactedEvent.type in EventType.STATE_ROOM_BEACON_INFO) {
|
||||
if (redactedEvent.type in EventType.STATE_ROOM_BEACON_INFO.values) {
|
||||
val liveSummary = LiveLocationShareAggregatedSummaryEntity.get(realm, eventId = redactedEvent.eventId)
|
||||
|
||||
if (liveSummary != null) {
|
||||
|
|
|
@ -46,7 +46,7 @@ internal class DefaultStartLiveLocationShareTask @Inject constructor(
|
|||
isLive = true,
|
||||
unstableTimestampMillis = clock.epochMillis()
|
||||
).toContent()
|
||||
val eventType = EventType.STATE_ROOM_BEACON_INFO.first()
|
||||
val eventType = EventType.STATE_ROOM_BEACON_INFO.stable
|
||||
val sendStateTaskParams = SendStateTask.Params(
|
||||
roomId = params.roomId,
|
||||
stateKey = userId,
|
||||
|
|
|
@ -45,7 +45,7 @@ internal class DefaultStopLiveLocationShareTask @Inject constructor(
|
|||
val sendStateTaskParams = SendStateTask.Params(
|
||||
roomId = params.roomId,
|
||||
stateKey = stateKey,
|
||||
eventType = EventType.STATE_ROOM_BEACON_INFO.first(),
|
||||
eventType = EventType.STATE_ROOM_BEACON_INFO.stable,
|
||||
body = updatedContent
|
||||
)
|
||||
return try {
|
||||
|
|
|
@ -61,45 +61,36 @@ internal class RedactionEventProcessor @Inject constructor() : EventInsertLivePr
|
|||
val isLocalEcho = LocalEcho.isLocalEchoId(redactionEvent.eventId ?: "")
|
||||
Timber.v("Redact event for ${redactionEvent.redacts} localEcho=$isLocalEcho")
|
||||
|
||||
val eventToPrune = EventEntity.where(realm, eventId = redactionEvent.redacts).findFirst()
|
||||
?: return
|
||||
val eventToPrune = EventEntity.where(realm, eventId = redactionEvent.redacts).findFirst() ?: return
|
||||
|
||||
val typeToPrune = eventToPrune.type
|
||||
val stateKey = eventToPrune.stateKey
|
||||
val allowedKeys = computeAllowedKeys(typeToPrune)
|
||||
if (allowedKeys.isNotEmpty()) {
|
||||
val prunedContent = ContentMapper.map(eventToPrune.content)?.filterKeys { key -> allowedKeys.contains(key) }
|
||||
eventToPrune.content = ContentMapper.map(prunedContent)
|
||||
} else {
|
||||
when (typeToPrune) {
|
||||
EventType.ENCRYPTED,
|
||||
EventType.MESSAGE,
|
||||
in EventType.STATE_ROOM_BEACON_INFO,
|
||||
in EventType.BEACON_LOCATION_DATA,
|
||||
in EventType.POLL_START -> {
|
||||
Timber.d("REDACTION for message ${eventToPrune.eventId}")
|
||||
val unsignedData = EventMapper.map(eventToPrune).unsignedData
|
||||
?: UnsignedData(null, null)
|
||||
when {
|
||||
allowedKeys.isNotEmpty() -> {
|
||||
val prunedContent = ContentMapper.map(eventToPrune.content)?.filterKeys { key -> allowedKeys.contains(key) }
|
||||
eventToPrune.content = ContentMapper.map(prunedContent)
|
||||
}
|
||||
canPruneEventType(typeToPrune) -> {
|
||||
Timber.d("REDACTION for message ${eventToPrune.eventId}")
|
||||
val unsignedData = EventMapper.map(eventToPrune).unsignedData ?: UnsignedData(null, null)
|
||||
|
||||
// was this event a m.replace
|
||||
// was this event a m.replace
|
||||
// val contentModel = ContentMapper.map(eventToPrune.content)?.toModel<MessageContent>()
|
||||
// if (RelationType.REPLACE == contentModel?.relatesTo?.type && contentModel.relatesTo?.eventId != null) {
|
||||
// eventRelationsAggregationUpdater.handleRedactionOfReplace(eventToPrune, contentModel.relatesTo!!.eventId!!, realm)
|
||||
// }
|
||||
|
||||
val modified = unsignedData.copy(redactedEvent = redactionEvent)
|
||||
// Deleting the content of a thread message will result to delete the thread relation, however threads are now dynamic
|
||||
// so there is not much of a problem
|
||||
eventToPrune.content = ContentMapper.map(emptyMap())
|
||||
eventToPrune.unsignedData = MoshiProvider.providesMoshi().adapter(UnsignedData::class.java).toJson(modified)
|
||||
eventToPrune.decryptionResultJson = null
|
||||
eventToPrune.decryptionErrorCode = null
|
||||
val modified = unsignedData.copy(redactedEvent = redactionEvent)
|
||||
eventToPrune.content = ContentMapper.map(emptyMap())
|
||||
eventToPrune.unsignedData = MoshiProvider.providesMoshi().adapter(UnsignedData::class.java).toJson(modified)
|
||||
eventToPrune.decryptionResultJson = null
|
||||
eventToPrune.decryptionErrorCode = null
|
||||
|
||||
handleTimelineThreadSummaryIfNeeded(realm, eventToPrune, isLocalEcho)
|
||||
}
|
||||
// EventType.REACTION -> {
|
||||
// eventRelationsAggregationUpdater.handleReactionRedact(eventToPrune, realm, userId)
|
||||
// }
|
||||
handleTimelineThreadSummaryIfNeeded(realm, eventToPrune, isLocalEcho)
|
||||
}
|
||||
else -> {
|
||||
Timber.w("Not pruning event (type $typeToPrune)")
|
||||
}
|
||||
}
|
||||
if (typeToPrune == EventType.STATE_ROOM_MEMBER && stateKey != null) {
|
||||
|
@ -167,4 +158,28 @@ internal class RedactionEventProcessor @Inject constructor() : EventInsertLivePr
|
|||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun canPruneEventType(eventType: String): Boolean {
|
||||
return when {
|
||||
EventType.isCallEvent(eventType) -> false
|
||||
EventType.isVerificationEvent(eventType) -> false
|
||||
eventType == EventType.STATE_ROOM_WIDGET_LEGACY ||
|
||||
eventType == EventType.STATE_ROOM_WIDGET ||
|
||||
eventType == EventType.STATE_ROOM_NAME ||
|
||||
eventType == EventType.STATE_ROOM_TOPIC ||
|
||||
eventType == EventType.STATE_ROOM_AVATAR ||
|
||||
eventType == EventType.STATE_ROOM_THIRD_PARTY_INVITE ||
|
||||
eventType == EventType.STATE_ROOM_GUEST_ACCESS ||
|
||||
eventType == EventType.STATE_SPACE_CHILD ||
|
||||
eventType == EventType.STATE_SPACE_PARENT ||
|
||||
eventType == EventType.STATE_ROOM_TOMBSTONE ||
|
||||
eventType == EventType.STATE_ROOM_HISTORY_VISIBILITY ||
|
||||
eventType == EventType.STATE_ROOM_RELATED_GROUPS ||
|
||||
eventType == EventType.STATE_ROOM_PINNED_EVENT ||
|
||||
eventType == EventType.STATE_ROOM_ENCRYPTION ||
|
||||
eventType == EventType.STATE_ROOM_SERVER_ACL ||
|
||||
eventType == EventType.REACTION -> false
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -181,7 +181,7 @@ internal class LocalEchoEventFactory @Inject constructor(
|
|||
originServerTs = dummyOriginServerTs(),
|
||||
senderId = userId,
|
||||
eventId = localId,
|
||||
type = EventType.POLL_START.first(),
|
||||
type = EventType.POLL_START.stable,
|
||||
content = newContent.toContent().plus(additionalContent.orEmpty())
|
||||
)
|
||||
}
|
||||
|
@ -206,7 +206,7 @@ internal class LocalEchoEventFactory @Inject constructor(
|
|||
originServerTs = dummyOriginServerTs(),
|
||||
senderId = userId,
|
||||
eventId = localId,
|
||||
type = EventType.POLL_RESPONSE.first(),
|
||||
type = EventType.POLL_RESPONSE.stable,
|
||||
content = content.toContent().plus(additionalContent.orEmpty()),
|
||||
unsignedData = UnsignedData(age = null, transactionId = localId)
|
||||
)
|
||||
|
@ -226,7 +226,7 @@ internal class LocalEchoEventFactory @Inject constructor(
|
|||
originServerTs = dummyOriginServerTs(),
|
||||
senderId = userId,
|
||||
eventId = localId,
|
||||
type = EventType.POLL_START.first(),
|
||||
type = EventType.POLL_START.stable,
|
||||
content = content.toContent().plus(additionalContent.orEmpty()),
|
||||
unsignedData = UnsignedData(age = null, transactionId = localId)
|
||||
)
|
||||
|
@ -249,7 +249,7 @@ internal class LocalEchoEventFactory @Inject constructor(
|
|||
originServerTs = dummyOriginServerTs(),
|
||||
senderId = userId,
|
||||
eventId = localId,
|
||||
type = EventType.POLL_END.first(),
|
||||
type = EventType.POLL_END.stable,
|
||||
content = content.toContent().plus(additionalContent.orEmpty()),
|
||||
unsignedData = UnsignedData(age = null, transactionId = localId)
|
||||
)
|
||||
|
@ -300,7 +300,7 @@ internal class LocalEchoEventFactory @Inject constructor(
|
|||
originServerTs = dummyOriginServerTs(),
|
||||
senderId = userId,
|
||||
eventId = localId,
|
||||
type = EventType.BEACON_LOCATION_DATA.first(),
|
||||
type = EventType.BEACON_LOCATION_DATA.stable,
|
||||
content = content.toContent().plus(additionalContent.orEmpty()),
|
||||
unsignedData = UnsignedData(age = null, transactionId = localId)
|
||||
)
|
||||
|
|
|
@ -87,7 +87,7 @@ object PollEventsTestData {
|
|||
)
|
||||
|
||||
internal val A_POLL_START_EVENT = Event(
|
||||
type = EventType.POLL_START.first(),
|
||||
type = EventType.POLL_START.stable,
|
||||
eventId = AN_EVENT_ID,
|
||||
originServerTs = 1652435922563,
|
||||
senderId = A_USER_ID_1,
|
||||
|
@ -96,7 +96,7 @@ object PollEventsTestData {
|
|||
)
|
||||
|
||||
internal val A_POLL_RESPONSE_EVENT = Event(
|
||||
type = EventType.POLL_RESPONSE.first(),
|
||||
type = EventType.POLL_RESPONSE.stable,
|
||||
eventId = AN_EVENT_ID,
|
||||
originServerTs = 1652435922563,
|
||||
senderId = A_USER_ID_1,
|
||||
|
@ -105,7 +105,7 @@ object PollEventsTestData {
|
|||
)
|
||||
|
||||
internal val A_POLL_END_EVENT = Event(
|
||||
type = EventType.POLL_END.first(),
|
||||
type = EventType.POLL_END.stable,
|
||||
eventId = AN_EVENT_ID,
|
||||
originServerTs = 1652435922563,
|
||||
senderId = A_USER_ID_1,
|
||||
|
|
|
@ -69,7 +69,7 @@ class DefaultGetActiveBeaconInfoForUserTaskTest {
|
|||
result shouldBeEqualTo currentStateEvent
|
||||
fakeStateEventDataSource.verifyGetStateEvent(
|
||||
roomId = params.roomId,
|
||||
eventType = EventType.STATE_ROOM_BEACON_INFO.first(),
|
||||
eventType = EventType.STATE_ROOM_BEACON_INFO.stable,
|
||||
stateKey = QueryStringValue.Equals(A_USER_ID)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ internal class DefaultStartLiveLocationShareTaskTest {
|
|||
val expectedParams = SendStateTask.Params(
|
||||
roomId = params.roomId,
|
||||
stateKey = A_USER_ID,
|
||||
eventType = EventType.STATE_ROOM_BEACON_INFO.first(),
|
||||
eventType = EventType.STATE_ROOM_BEACON_INFO.stable,
|
||||
body = expectedBeaconContent
|
||||
)
|
||||
fakeSendStateTask.verifyExecuteRetry(
|
||||
|
|
|
@ -79,7 +79,7 @@ class DefaultStopLiveLocationShareTaskTest {
|
|||
val expectedSendParams = SendStateTask.Params(
|
||||
roomId = params.roomId,
|
||||
stateKey = A_USER_ID,
|
||||
eventType = EventType.STATE_ROOM_BEACON_INFO.first(),
|
||||
eventType = EventType.STATE_ROOM_BEACON_INFO.stable,
|
||||
body = expectedBeaconContent
|
||||
)
|
||||
fakeSendStateTask.verifyExecuteRetry(
|
||||
|
|
|
@ -79,7 +79,7 @@ class LiveLocationShareRedactionEventProcessorTest {
|
|||
@Test
|
||||
fun `given a redacted live location share event when processing it then related summaries are deleted from database`() = runTest {
|
||||
val event = Event(eventId = AN_EVENT_ID, redacts = A_REDACTED_EVENT_ID)
|
||||
val redactedEventEntity = EventEntity(eventId = A_REDACTED_EVENT_ID, type = EventType.STATE_ROOM_BEACON_INFO.first())
|
||||
val redactedEventEntity = EventEntity(eventId = A_REDACTED_EVENT_ID, type = EventType.STATE_ROOM_BEACON_INFO.stable)
|
||||
fakeRealm.givenWhere<EventEntity>()
|
||||
.givenEqualTo(EventEntityFields.EVENT_ID, A_REDACTED_EVENT_ID)
|
||||
.givenFindFirst(redactedEventEntity)
|
||||
|
|
|
@ -19,7 +19,6 @@ package im.vector.app.core.extensions
|
|||
import im.vector.app.features.voicebroadcast.VoiceBroadcastConstants
|
||||
import im.vector.app.features.voicebroadcast.model.MessageVoiceBroadcastInfoContent
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
|
||||
import org.matrix.android.sdk.api.session.room.send.SendState
|
||||
|
@ -28,7 +27,7 @@ import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
|
|||
|
||||
fun TimelineEvent.canReact(): Boolean {
|
||||
// Only event of type EventType.MESSAGE, EventType.STICKER and EventType.POLL_START are supported for the moment
|
||||
return root.getClearType() in listOf(EventType.MESSAGE, EventType.STICKER) + EventType.POLL_START &&
|
||||
return root.getClearType() in listOf(EventType.MESSAGE, EventType.STICKER) + EventType.POLL_START.values &&
|
||||
root.sendState == SendState.SYNCED &&
|
||||
!root.isRedacted()
|
||||
}
|
||||
|
@ -41,7 +40,7 @@ fun TimelineEvent.getVectorLastMessageContent(): MessageContent? {
|
|||
// Iterate on event types which are not part of the matrix sdk, otherwise fallback to the sdk method
|
||||
return when (root.getClearType()) {
|
||||
VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO -> {
|
||||
(annotations?.editSummary?.latestEdit?.getClearContent()?.toModel<MessageContent>().toContent().toModel<MessageVoiceBroadcastInfoContent>()
|
||||
(annotations?.editSummary?.latestEdit?.getClearContent()?.toModel<MessageVoiceBroadcastInfoContent>()
|
||||
?: root.getClearContent().toModel<MessageVoiceBroadcastInfoContent>())
|
||||
}
|
||||
else -> getLastMessageContent()
|
||||
|
|
|
@ -1774,7 +1774,7 @@ class TimelineFragment :
|
|||
timelineViewModel.handle(RoomDetailAction.UpdateQuickReactAction(action.eventId, action.clickedOn, action.add))
|
||||
}
|
||||
is EventSharedAction.Edit -> {
|
||||
if (action.eventType in EventType.POLL_START) {
|
||||
if (action.eventType in EventType.POLL_START.values) {
|
||||
navigator.openCreatePoll(requireContext(), timelineArgs.roomId, action.eventId, PollMode.EDIT)
|
||||
} else if (withState(messageComposerViewModel) { it.isVoiceMessageIdle }) {
|
||||
messageComposerViewModel.handle(MessageComposerAction.EnterEditMode(action.eventId))
|
||||
|
|
|
@ -33,8 +33,8 @@ class CheckIfCanRedactEventUseCase @Inject constructor(
|
|||
EventType.STICKER,
|
||||
VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO,
|
||||
) +
|
||||
EventType.POLL_START +
|
||||
EventType.STATE_ROOM_BEACON_INFO
|
||||
EventType.POLL_START.values +
|
||||
EventType.STATE_ROOM_BEACON_INFO.values
|
||||
|
||||
return event.root.getClearType() in canRedactEventTypes &&
|
||||
// Message sent by the current user can always be redacted, else check permission for messages sent by other users
|
||||
|
|
|
@ -26,7 +26,7 @@ class CheckIfCanReplyEventUseCase @Inject constructor() {
|
|||
|
||||
fun execute(event: TimelineEvent, messageContent: MessageContent?, actionPermissions: ActionPermissions): Boolean {
|
||||
// Only EventType.MESSAGE, EventType.POLL_START and EventType.STATE_ROOM_BEACON_INFO event types are supported for the moment
|
||||
if (event.root.getClearType() !in EventType.STATE_ROOM_BEACON_INFO + EventType.POLL_START + EventType.MESSAGE) return false
|
||||
if (event.root.getClearType() !in EventType.STATE_ROOM_BEACON_INFO.values + EventType.POLL_START.values + EventType.MESSAGE) return false
|
||||
if (!actionPermissions.canSendMessage) return false
|
||||
return when (messageContent?.msgType) {
|
||||
MessageType.MSGTYPE_TEXT,
|
||||
|
|
|
@ -215,7 +215,7 @@ class MessageActionsViewModel @AssistedInject constructor(
|
|||
EventType.CALL_ANSWER -> {
|
||||
noticeEventFormatter.format(timelineEvent, room?.roomSummary()?.isDirect.orFalse())
|
||||
}
|
||||
in EventType.POLL_START -> {
|
||||
in EventType.POLL_START.values -> {
|
||||
timelineEvent.root.getClearContent().toModel<MessagePollContent>(catchError = true)
|
||||
?.getBestPollCreationInfo()?.question?.getBestQuestion() ?: ""
|
||||
}
|
||||
|
@ -383,7 +383,7 @@ class MessageActionsViewModel @AssistedInject constructor(
|
|||
}
|
||||
|
||||
if (canRedact(timelineEvent, actionPermissions)) {
|
||||
if (timelineEvent.root.getClearType() in EventType.POLL_START) {
|
||||
if (timelineEvent.root.getClearType() in EventType.POLL_START.values) {
|
||||
add(
|
||||
EventSharedAction.Redact(
|
||||
eventId,
|
||||
|
@ -530,13 +530,13 @@ class MessageActionsViewModel @AssistedInject constructor(
|
|||
|
||||
private fun canViewReactions(event: TimelineEvent): Boolean {
|
||||
// Only event of type EventType.MESSAGE, EventType.STICKER and EventType.POLL_START are supported for the moment
|
||||
if (event.root.getClearType() !in listOf(EventType.MESSAGE, EventType.STICKER) + EventType.POLL_START) return false
|
||||
if (event.root.getClearType() !in listOf(EventType.MESSAGE, EventType.STICKER) + EventType.POLL_START.values) return false
|
||||
return event.annotations?.reactionsSummary?.isNotEmpty() ?: false
|
||||
}
|
||||
|
||||
private fun canEdit(event: TimelineEvent, myUserId: String, actionPermissions: ActionPermissions): Boolean {
|
||||
// Only event of type EventType.MESSAGE and EventType.POLL_START are supported for the moment
|
||||
if (event.root.getClearType() !in listOf(EventType.MESSAGE) + EventType.POLL_START) return false
|
||||
if (event.root.getClearType() !in listOf(EventType.MESSAGE) + EventType.POLL_START.values) return false
|
||||
if (!actionPermissions.canSendMessage) return false
|
||||
// TODO if user is admin or moderator
|
||||
val messageContent = event.root.getClearContent().toModel<MessageContent>()
|
||||
|
@ -582,14 +582,14 @@ class MessageActionsViewModel @AssistedInject constructor(
|
|||
}
|
||||
|
||||
private fun canEndPoll(event: TimelineEvent, actionPermissions: ActionPermissions): Boolean {
|
||||
return event.root.getClearType() in EventType.POLL_START &&
|
||||
return event.root.getClearType() in EventType.POLL_START.values &&
|
||||
canRedact(event, actionPermissions) &&
|
||||
event.annotations?.pollResponseSummary?.closedTime == null
|
||||
}
|
||||
|
||||
private fun canEditPoll(event: TimelineEvent): Boolean {
|
||||
return event.root.getClearType() in EventType.POLL_START &&
|
||||
return event.root.getClearType() in EventType.POLL_START.values &&
|
||||
event.annotations?.pollResponseSummary?.closedTime == null &&
|
||||
event.annotations?.pollResponseSummary?.aggregatedContent?.totalVotes ?: 0 == 0
|
||||
(event.annotations?.pollResponseSummary?.aggregatedContent?.totalVotes ?: 0) == 0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ import im.vector.app.features.home.room.detail.timeline.helper.MessageInformatio
|
|||
import im.vector.app.features.home.room.detail.timeline.helper.MessageItemAttributesFactory
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
|
||||
import im.vector.app.features.home.room.detail.timeline.item.AbsMessageItem
|
||||
import im.vector.app.features.home.room.detail.timeline.item.BaseEventItem
|
||||
import im.vector.app.features.home.room.detail.timeline.item.MessageAudioItem
|
||||
import im.vector.app.features.home.room.detail.timeline.item.MessageAudioItem_
|
||||
import im.vector.app.features.home.room.detail.timeline.item.MessageFileItem
|
||||
|
@ -324,9 +325,11 @@ class MessageItemFactory @Inject constructor(
|
|||
informationData: MessageInformationData,
|
||||
highlight: Boolean,
|
||||
attributes: AbsMessageItem.Attributes
|
||||
): MessageVoiceItem? {
|
||||
): BaseEventItem<*>? {
|
||||
// Do not display voice broadcast messages
|
||||
if (params.event.root.asMessageAudioEvent().isVoiceBroadcast()) return null
|
||||
if (params.event.root.asMessageAudioEvent().isVoiceBroadcast()) {
|
||||
return noticeItemFactory.create(params)
|
||||
}
|
||||
|
||||
val fileUrl = getAudioFileUrl(messageContent, informationData)
|
||||
val playbackControlButtonClickListener = createOnPlaybackButtonClickListener(messageContent, informationData, params)
|
||||
|
|
|
@ -88,7 +88,7 @@ class TimelineItemFactory @Inject constructor(
|
|||
EventType.STATE_ROOM_ENCRYPTION -> encryptionItemFactory.create(params)
|
||||
// State room create
|
||||
EventType.STATE_ROOM_CREATE -> roomCreateItemFactory.create(params)
|
||||
in EventType.STATE_ROOM_BEACON_INFO -> messageItemFactory.create(params)
|
||||
in EventType.STATE_ROOM_BEACON_INFO.values -> messageItemFactory.create(params)
|
||||
VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO -> messageItemFactory.create(params)
|
||||
// Unhandled state event types
|
||||
else -> {
|
||||
|
@ -101,7 +101,7 @@ class TimelineItemFactory @Inject constructor(
|
|||
when (event.root.getClearType()) {
|
||||
// Message itemsX
|
||||
EventType.STICKER,
|
||||
in EventType.POLL_START,
|
||||
in EventType.POLL_START.values,
|
||||
EventType.MESSAGE -> messageItemFactory.create(params)
|
||||
EventType.REDACTION,
|
||||
EventType.KEY_VERIFICATION_ACCEPT,
|
||||
|
@ -114,9 +114,9 @@ class TimelineItemFactory @Inject constructor(
|
|||
EventType.CALL_SELECT_ANSWER,
|
||||
EventType.CALL_NEGOTIATE,
|
||||
EventType.REACTION,
|
||||
in EventType.POLL_RESPONSE,
|
||||
in EventType.POLL_END -> noticeItemFactory.create(params)
|
||||
in EventType.BEACON_LOCATION_DATA -> {
|
||||
in EventType.POLL_RESPONSE.values,
|
||||
in EventType.POLL_END.values -> noticeItemFactory.create(params)
|
||||
in EventType.BEACON_LOCATION_DATA.values -> {
|
||||
if (event.root.isRedacted()) {
|
||||
messageItemFactory.create(params)
|
||||
} else {
|
||||
|
|
|
@ -23,6 +23,7 @@ import im.vector.app.features.home.room.detail.timeline.helper.AvatarSizeProvide
|
|||
import im.vector.app.features.home.room.detail.timeline.helper.VoiceBroadcastEventsGroup
|
||||
import im.vector.app.features.home.room.detail.timeline.item.AbsMessageItem
|
||||
import im.vector.app.features.home.room.detail.timeline.item.AbsMessageVoiceBroadcastItem
|
||||
import im.vector.app.features.home.room.detail.timeline.item.BaseEventItem
|
||||
import im.vector.app.features.home.room.detail.timeline.item.MessageVoiceBroadcastListeningItem
|
||||
import im.vector.app.features.home.room.detail.timeline.item.MessageVoiceBroadcastListeningItem_
|
||||
import im.vector.app.features.home.room.detail.timeline.item.MessageVoiceBroadcastRecordingItem
|
||||
|
@ -47,6 +48,7 @@ class VoiceBroadcastItemFactory @Inject constructor(
|
|||
private val voiceBroadcastRecorder: VoiceBroadcastRecorder?,
|
||||
private val voiceBroadcastPlayer: VoiceBroadcastPlayer,
|
||||
private val playbackTracker: AudioMessagePlaybackTracker,
|
||||
private val noticeItemFactory: NoticeItemFactory,
|
||||
) {
|
||||
|
||||
fun create(
|
||||
|
@ -54,9 +56,11 @@ class VoiceBroadcastItemFactory @Inject constructor(
|
|||
messageContent: MessageVoiceBroadcastInfoContent,
|
||||
highlight: Boolean,
|
||||
attributes: AbsMessageItem.Attributes,
|
||||
): AbsMessageVoiceBroadcastItem<*>? {
|
||||
): BaseEventItem<*>? {
|
||||
// Only display item of the initial event with updated data
|
||||
if (messageContent.voiceBroadcastState != VoiceBroadcastState.STARTED) return null
|
||||
if (messageContent.voiceBroadcastState != VoiceBroadcastState.STARTED) {
|
||||
return noticeItemFactory.create(params)
|
||||
}
|
||||
|
||||
val voiceBroadcastEventsGroup = params.eventsGroup?.let { VoiceBroadcastEventsGroup(it) } ?: return null
|
||||
val voiceBroadcastEvent = voiceBroadcastEventsGroup.getLastDisplayableEvent().root.asVoiceBroadcastEvent() ?: return null
|
||||
|
|
|
@ -122,17 +122,17 @@ class DisplayableEventFormatter @Inject constructor(
|
|||
EventType.CALL_CANDIDATES -> {
|
||||
span { }
|
||||
}
|
||||
in EventType.POLL_START -> {
|
||||
in EventType.POLL_START.values -> {
|
||||
timelineEvent.root.getClearContent().toModel<MessagePollContent>(catchError = true)?.getBestPollCreationInfo()?.question?.getBestQuestion()
|
||||
?: stringProvider.getString(R.string.sent_a_poll)
|
||||
}
|
||||
in EventType.POLL_RESPONSE -> {
|
||||
in EventType.POLL_RESPONSE.values -> {
|
||||
stringProvider.getString(R.string.poll_response_room_list_preview)
|
||||
}
|
||||
in EventType.POLL_END -> {
|
||||
in EventType.POLL_END.values -> {
|
||||
stringProvider.getString(R.string.poll_end_room_list_preview)
|
||||
}
|
||||
in EventType.STATE_ROOM_BEACON_INFO -> {
|
||||
in EventType.STATE_ROOM_BEACON_INFO.values -> {
|
||||
simpleFormat(senderName, stringProvider.getString(R.string.sent_live_location), appendAuthor)
|
||||
}
|
||||
else -> {
|
||||
|
@ -220,17 +220,17 @@ class DisplayableEventFormatter @Inject constructor(
|
|||
emojiSpanify.spanify(stringProvider.getString(R.string.sent_a_reaction, it.key))
|
||||
} ?: span { }
|
||||
}
|
||||
in EventType.POLL_START -> {
|
||||
in EventType.POLL_START.values -> {
|
||||
event.getClearContent().toModel<MessagePollContent>(catchError = true)?.pollCreationInfo?.question?.question
|
||||
?: stringProvider.getString(R.string.sent_a_poll)
|
||||
}
|
||||
in EventType.POLL_RESPONSE -> {
|
||||
in EventType.POLL_RESPONSE.values -> {
|
||||
stringProvider.getString(R.string.poll_response_room_list_preview)
|
||||
}
|
||||
in EventType.POLL_END -> {
|
||||
in EventType.POLL_END.values -> {
|
||||
stringProvider.getString(R.string.poll_end_room_list_preview)
|
||||
}
|
||||
in EventType.STATE_ROOM_BEACON_INFO -> {
|
||||
in EventType.STATE_ROOM_BEACON_INFO.values -> {
|
||||
stringProvider.getString(R.string.sent_live_location)
|
||||
}
|
||||
else -> {
|
||||
|
|
|
@ -21,6 +21,7 @@ import im.vector.app.R
|
|||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.features.roomprofile.permissions.RoleFormatter
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import im.vector.app.features.voicebroadcast.VoiceBroadcastConstants
|
||||
import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM
|
||||
import org.matrix.android.sdk.api.extensions.appendNl
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
|
@ -106,9 +107,10 @@ class NoticeEventFormatter @Inject constructor(
|
|||
EventType.STATE_SPACE_PARENT,
|
||||
EventType.REDACTION,
|
||||
EventType.STICKER,
|
||||
in EventType.POLL_RESPONSE,
|
||||
in EventType.POLL_END,
|
||||
in EventType.BEACON_LOCATION_DATA -> formatDebug(timelineEvent.root)
|
||||
in EventType.POLL_RESPONSE.values,
|
||||
in EventType.POLL_END.values,
|
||||
in EventType.BEACON_LOCATION_DATA.values,
|
||||
VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO -> formatDebug(timelineEvent.root)
|
||||
else -> {
|
||||
Timber.v("Type $type not handled by this formatter")
|
||||
null
|
||||
|
|
|
@ -54,9 +54,9 @@ object TimelineDisplayableEvents {
|
|||
EventType.KEY_VERIFICATION_CANCEL,
|
||||
VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO,
|
||||
) +
|
||||
EventType.POLL_START +
|
||||
EventType.STATE_ROOM_BEACON_INFO +
|
||||
EventType.BEACON_LOCATION_DATA
|
||||
EventType.POLL_START.values +
|
||||
EventType.STATE_ROOM_BEACON_INFO.values +
|
||||
EventType.BEACON_LOCATION_DATA.values
|
||||
}
|
||||
|
||||
fun TimelineEvent.isRoomConfiguration(roomCreatorUserId: String?): Boolean {
|
||||
|
|
|
@ -18,6 +18,11 @@ package im.vector.app.features.home.room.detail.timeline.helper
|
|||
|
||||
import im.vector.app.core.extensions.localDateTime
|
||||
import im.vector.app.core.resources.UserPreferencesProvider
|
||||
import im.vector.app.features.voicebroadcast.VoiceBroadcastConstants
|
||||
import im.vector.app.features.voicebroadcast.isVoiceBroadcast
|
||||
import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState
|
||||
import im.vector.app.features.voicebroadcast.model.asVoiceBroadcastEvent
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.RelationType
|
||||
|
@ -28,6 +33,7 @@ import org.matrix.android.sdk.api.session.events.model.toModel
|
|||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
||||
import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho
|
||||
import org.matrix.android.sdk.api.session.room.model.message.asMessageAudioEvent
|
||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -242,10 +248,19 @@ class TimelineEventVisibilityHelper @Inject constructor(
|
|||
} else root.eventId != rootThreadEventId
|
||||
}
|
||||
|
||||
if (root.getClearType() in EventType.BEACON_LOCATION_DATA) {
|
||||
if (root.getClearType() in EventType.BEACON_LOCATION_DATA.values) {
|
||||
return !root.isRedacted()
|
||||
}
|
||||
|
||||
if (root.getClearType() == VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO &&
|
||||
root.asVoiceBroadcastEvent()?.content?.voiceBroadcastState != VoiceBroadcastState.STARTED) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (root.asMessageAudioEvent()?.isVoiceBroadcast().orFalse()) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
@ -47,8 +47,10 @@ class TimelineMessageLayoutFactory @Inject constructor(
|
|||
private val EVENT_TYPES_WITH_BUBBLE_LAYOUT = setOf(
|
||||
EventType.MESSAGE,
|
||||
EventType.ENCRYPTED,
|
||||
EventType.STICKER
|
||||
) + EventType.POLL_START + EventType.STATE_ROOM_BEACON_INFO
|
||||
EventType.STICKER,
|
||||
) +
|
||||
EventType.POLL_START.values +
|
||||
EventType.STATE_ROOM_BEACON_INFO.values
|
||||
|
||||
// Can't be rendered in bubbles, so get back to default layout
|
||||
private val MSG_TYPES_WITHOUT_BUBBLE_LAYOUT = setOf(
|
||||
|
|
|
@ -83,7 +83,7 @@ class LocationSharingViewModel @AssistedInject constructor(
|
|||
.distinctUntilChanged()
|
||||
.setOnEach {
|
||||
val powerLevelsHelper = PowerLevelsHelper(it)
|
||||
val canShareLiveLocation = EventType.STATE_ROOM_BEACON_INFO
|
||||
val canShareLiveLocation = EventType.STATE_ROOM_BEACON_INFO.values
|
||||
.all { beaconInfoType ->
|
||||
powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, beaconInfoType)
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ class NotifiableEventResolver @Inject constructor(
|
|||
) {
|
||||
|
||||
private val nonEncryptedNotifiableEventTypes: List<String> =
|
||||
listOf(EventType.MESSAGE) + EventType.POLL_START + EventType.STATE_ROOM_BEACON_INFO
|
||||
listOf(EventType.MESSAGE) + EventType.POLL_START.values + EventType.STATE_ROOM_BEACON_INFO.values
|
||||
|
||||
suspend fun resolveEvent(event: Event, session: Session, isNoisy: Boolean): NotifiableEvent? {
|
||||
val roomID = event.roomId ?: return null
|
||||
|
|
|
@ -35,8 +35,13 @@ class CheckIfCanRedactEventUseCaseTest {
|
|||
|
||||
@Test
|
||||
fun `given an event which can be redacted and owned by user when use case executes then the result is true`() {
|
||||
val canRedactEventTypes = listOf(EventType.MESSAGE, EventType.STICKER, VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO) +
|
||||
EventType.POLL_START + EventType.STATE_ROOM_BEACON_INFO
|
||||
val canRedactEventTypes = listOf(
|
||||
EventType.MESSAGE,
|
||||
EventType.STICKER,
|
||||
VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO
|
||||
) +
|
||||
EventType.POLL_START.values +
|
||||
EventType.STATE_ROOM_BEACON_INFO.values
|
||||
|
||||
canRedactEventTypes.forEach { eventType ->
|
||||
val event = givenAnEvent(
|
||||
|
|
|
@ -43,7 +43,7 @@ class CheckIfCanReplyEventUseCaseTest {
|
|||
|
||||
@Test
|
||||
fun `given reply is allowed for the event type when use case is executed then result is true`() {
|
||||
val eventTypes = EventType.STATE_ROOM_BEACON_INFO + EventType.POLL_START + EventType.MESSAGE
|
||||
val eventTypes = EventType.STATE_ROOM_BEACON_INFO.values + EventType.POLL_START.values + EventType.MESSAGE
|
||||
|
||||
eventTypes.forEach { eventType ->
|
||||
val event = givenAnEvent(eventType)
|
||||
|
|
|
@ -63,7 +63,7 @@ object FakeCreatePollViewStates {
|
|||
)
|
||||
|
||||
private val A_POLL_START_EVENT = Event(
|
||||
type = EventType.POLL_START.first(),
|
||||
type = EventType.POLL_START.stable,
|
||||
eventId = A_FAKE_EVENT_ID,
|
||||
originServerTs = 1652435922563,
|
||||
senderId = A_FAKE_USER_ID,
|
||||
|
@ -80,8 +80,8 @@ object FakeCreatePollViewStates {
|
|||
)
|
||||
|
||||
val initialCreatePollViewState = CreatePollViewState(createPollArgs).copy(
|
||||
canCreatePoll = false,
|
||||
canAddMoreOptions = true
|
||||
canCreatePoll = false,
|
||||
canAddMoreOptions = true
|
||||
)
|
||||
|
||||
val pollViewStateWithOnlyQuestion = initialCreatePollViewState.copy(
|
||||
|
|
Loading…
Reference in a new issue