Merge pull request #7988 from vector-im/yostyle/msc3912
Implement MSC3912 to delete server side all the data of a deleted voice broadcast
This commit is contained in:
commit
c802e2d0f7
|
@ -0,0 +1 @@
|
|||
[Voice Broadcast] Use MSC3912 to delete server side all the related events
|
|
@ -0,0 +1 @@
|
|||
Implement [MSC3912](https://github.com/matrix-org/matrix-spec-proposals/pull/3912): Relation-based redactions
|
|
@ -75,6 +75,11 @@ data class HomeServerCapabilities(
|
|||
* True if the home server supports remote toggle of Pusher for a given device.
|
||||
*/
|
||||
val canRemotelyTogglePushNotificationsOfDevices: Boolean = false,
|
||||
|
||||
/**
|
||||
* True if the home server supports event redaction with relations.
|
||||
*/
|
||||
var canRedactEventWithRelations: Boolean = false,
|
||||
) {
|
||||
|
||||
enum class RoomCapabilitySupport {
|
||||
|
|
|
@ -156,11 +156,12 @@ interface SendService {
|
|||
|
||||
/**
|
||||
* Redact (delete) the given event.
|
||||
* @param event The event to redact
|
||||
* @param reason Optional reason string
|
||||
* @param event the event to redact
|
||||
* @param reason optional reason string
|
||||
* @param withRelations the list of relation types to redact with this event
|
||||
* @param additionalContent additional content to put in the event content
|
||||
*/
|
||||
fun redactEvent(event: Event, reason: String?, additionalContent: Content? = null): Cancelable
|
||||
fun redactEvent(event: Event, reason: String?, withRelations: List<String>? = null, additionalContent: Content? = null): Cancelable
|
||||
|
||||
/**
|
||||
* Schedule this message to be resent.
|
||||
|
|
|
@ -58,6 +58,8 @@ private const val FEATURE_QR_CODE_LOGIN = "org.matrix.msc3882"
|
|||
private const val FEATURE_THREADS_MSC3771 = "org.matrix.msc3771"
|
||||
private const val FEATURE_THREADS_MSC3773 = "org.matrix.msc3773"
|
||||
private const val FEATURE_REMOTE_TOGGLE_PUSH_NOTIFICATIONS_MSC3881 = "org.matrix.msc3881"
|
||||
private const val FEATURE_EVENT_REDACTION_WITH_RELATIONS = "org.matrix.msc3912"
|
||||
private const val FEATURE_EVENT_REDACTION_WITH_RELATIONS_STABLE = "org.matrix.msc3912.stable"
|
||||
|
||||
/**
|
||||
* Return true if the SDK supports this homeserver version.
|
||||
|
@ -153,3 +155,13 @@ private fun Versions.getMaxVersion(): HomeServerVersion {
|
|||
internal fun Versions.doesServerSupportRemoteToggleOfPushNotifications(): Boolean {
|
||||
return unstableFeatures?.get(FEATURE_REMOTE_TOGGLE_PUSH_NOTIFICATIONS_MSC3881).orFalse()
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate if the server supports MSC3912: https://github.com/matrix-org/matrix-spec-proposals/pull/3912.
|
||||
*
|
||||
* @return true if event redaction with relations is supported
|
||||
*/
|
||||
internal fun Versions.doesServerSupportRedactEventWithRelations(): Boolean {
|
||||
return unstableFeatures?.get(FEATURE_EVENT_REDACTION_WITH_RELATIONS).orFalse() ||
|
||||
unstableFeatures?.get(FEATURE_EVENT_REDACTION_WITH_RELATIONS_STABLE).orFalse()
|
||||
}
|
||||
|
|
|
@ -15,9 +15,12 @@
|
|||
*/
|
||||
package org.matrix.android.sdk.internal.crypto.tasks
|
||||
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
|
||||
import org.matrix.android.sdk.internal.network.executeRequest
|
||||
import org.matrix.android.sdk.internal.session.homeserver.HomeServerCapabilitiesDataSource
|
||||
import org.matrix.android.sdk.internal.session.room.RoomAPI
|
||||
import org.matrix.android.sdk.internal.session.room.send.model.EventRedactBody
|
||||
import org.matrix.android.sdk.internal.task.Task
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -26,22 +29,34 @@ internal interface RedactEventTask : Task<RedactEventTask.Params, String> {
|
|||
val txID: String,
|
||||
val roomId: String,
|
||||
val eventId: String,
|
||||
val reason: String?
|
||||
val reason: String?,
|
||||
val withRelations: List<String>?,
|
||||
)
|
||||
}
|
||||
|
||||
internal class DefaultRedactEventTask @Inject constructor(
|
||||
private val roomAPI: RoomAPI,
|
||||
private val globalErrorReceiver: GlobalErrorReceiver
|
||||
private val globalErrorReceiver: GlobalErrorReceiver,
|
||||
private val homeServerCapabilitiesDataSource: HomeServerCapabilitiesDataSource,
|
||||
) : RedactEventTask {
|
||||
|
||||
override suspend fun execute(params: RedactEventTask.Params): String {
|
||||
val withRelations = if (homeServerCapabilitiesDataSource.getHomeServerCapabilities()?.canRedactEventWithRelations.orFalse() &&
|
||||
!params.withRelations.isNullOrEmpty()) {
|
||||
params.withRelations
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
val response = executeRequest(globalErrorReceiver) {
|
||||
roomAPI.redactEvent(
|
||||
txId = params.txID,
|
||||
roomId = params.roomId,
|
||||
eventId = params.eventId,
|
||||
reason = if (params.reason == null) emptyMap() else mapOf("reason" to params.reason)
|
||||
body = EventRedactBody(
|
||||
reason = params.reason,
|
||||
withRelations = withRelations,
|
||||
)
|
||||
)
|
||||
}
|
||||
return response.eventId
|
||||
|
|
|
@ -65,6 +65,7 @@ import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo045
|
|||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo046
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo047
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo048
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo049
|
||||
import org.matrix.android.sdk.internal.util.Normalizer
|
||||
import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration
|
||||
import javax.inject.Inject
|
||||
|
@ -73,7 +74,7 @@ internal class RealmSessionStoreMigration @Inject constructor(
|
|||
private val normalizer: Normalizer
|
||||
) : MatrixRealmMigration(
|
||||
dbName = "Session",
|
||||
schemaVersion = 48L,
|
||||
schemaVersion = 49L,
|
||||
) {
|
||||
/**
|
||||
* Forces all RealmSessionStoreMigration instances to be equal.
|
||||
|
@ -131,5 +132,6 @@ internal class RealmSessionStoreMigration @Inject constructor(
|
|||
if (oldVersion < 46) MigrateSessionTo046(realm).perform()
|
||||
if (oldVersion < 47) MigrateSessionTo047(realm).perform()
|
||||
if (oldVersion < 48) MigrateSessionTo048(realm).perform()
|
||||
if (oldVersion < 49) MigrateSessionTo049(realm).perform()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ internal object HomeServerCapabilitiesMapper {
|
|||
canLoginWithQrCode = entity.canLoginWithQrCode,
|
||||
canUseThreadReadReceiptsAndNotifications = entity.canUseThreadReadReceiptsAndNotifications,
|
||||
canRemotelyTogglePushNotificationsOfDevices = entity.canRemotelyTogglePushNotificationsOfDevices,
|
||||
canRedactEventWithRelations = entity.canRedactEventWithRelations,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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.internal.database.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields
|
||||
import org.matrix.android.sdk.internal.extensions.forceRefreshOfHomeServerCapabilities
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
internal class MigrateSessionTo049(realm: DynamicRealm) : RealmMigrator(realm, 49) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.get("HomeServerCapabilitiesEntity")
|
||||
?.addField(HomeServerCapabilitiesEntityFields.CAN_REDACT_EVENT_WITH_RELATIONS, Boolean::class.java)
|
||||
?.transform { obj ->
|
||||
obj.set(HomeServerCapabilitiesEntityFields.CAN_REDACT_EVENT_WITH_RELATIONS, false)
|
||||
}
|
||||
?.forceRefreshOfHomeServerCapabilities()
|
||||
}
|
||||
}
|
|
@ -34,6 +34,7 @@ internal open class HomeServerCapabilitiesEntity(
|
|||
var canLoginWithQrCode: Boolean = false,
|
||||
var canUseThreadReadReceiptsAndNotifications: Boolean = false,
|
||||
var canRemotelyTogglePushNotificationsOfDevices: Boolean = false,
|
||||
var canRedactEventWithRelations: Boolean = false,
|
||||
) : RealmObject() {
|
||||
|
||||
companion object
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
|
|||
import org.matrix.android.sdk.internal.auth.version.Versions
|
||||
import org.matrix.android.sdk.internal.auth.version.doesServerSupportLogoutDevices
|
||||
import org.matrix.android.sdk.internal.auth.version.doesServerSupportQrCodeLogin
|
||||
import org.matrix.android.sdk.internal.auth.version.doesServerSupportRedactEventWithRelations
|
||||
import org.matrix.android.sdk.internal.auth.version.doesServerSupportRemoteToggleOfPushNotifications
|
||||
import org.matrix.android.sdk.internal.auth.version.doesServerSupportThreadUnreadNotifications
|
||||
import org.matrix.android.sdk.internal.auth.version.doesServerSupportThreads
|
||||
|
@ -154,6 +155,8 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor(
|
|||
getVersionResult.doesServerSupportQrCodeLogin()
|
||||
homeServerCapabilitiesEntity.canRemotelyTogglePushNotificationsOfDevices =
|
||||
getVersionResult.doesServerSupportRemoteToggleOfPushNotifications()
|
||||
homeServerCapabilitiesEntity.canRedactEventWithRelations =
|
||||
getVersionResult.doesServerSupportRedactEventWithRelations()
|
||||
}
|
||||
|
||||
if (getWellknownResult != null && getWellknownResult is WellknownResult.Prompt) {
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.matrix.android.sdk.internal.session.room.relation.RelationsResponse
|
|||
import org.matrix.android.sdk.internal.session.room.relation.threads.ThreadSummariesResponse
|
||||
import org.matrix.android.sdk.internal.session.room.reporting.ReportContentBody
|
||||
import org.matrix.android.sdk.internal.session.room.send.SendResponse
|
||||
import org.matrix.android.sdk.internal.session.room.send.model.EventRedactBody
|
||||
import org.matrix.android.sdk.internal.session.room.tags.TagBody
|
||||
import org.matrix.android.sdk.internal.session.room.timeline.EventContextResponse
|
||||
import org.matrix.android.sdk.internal.session.room.timeline.PaginationResponse
|
||||
|
@ -61,7 +62,7 @@ internal interface RoomAPI {
|
|||
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "publicRooms")
|
||||
suspend fun publicRooms(
|
||||
@Query("server") server: String?,
|
||||
@Body publicRoomsParams: PublicRoomsParams
|
||||
@Body publicRoomsParams: PublicRoomsParams,
|
||||
): PublicRoomsResponse
|
||||
|
||||
/**
|
||||
|
@ -91,7 +92,7 @@ internal interface RoomAPI {
|
|||
@Query("from") from: String,
|
||||
@Query("dir") dir: String,
|
||||
@Query("limit") limit: Int?,
|
||||
@Query("filter") filter: String?
|
||||
@Query("filter") filter: String?,
|
||||
): PaginationResponse
|
||||
|
||||
/**
|
||||
|
@ -107,7 +108,7 @@ internal interface RoomAPI {
|
|||
@Path("roomId") roomId: String,
|
||||
@Query("at") syncToken: String?,
|
||||
@Query("membership") membership: Membership?,
|
||||
@Query("not_membership") notMembership: Membership?
|
||||
@Query("not_membership") notMembership: Membership?,
|
||||
): RoomMembersResponse
|
||||
|
||||
/**
|
||||
|
@ -123,7 +124,7 @@ internal interface RoomAPI {
|
|||
@Path("txId") txId: String,
|
||||
@Path("roomId") roomId: String,
|
||||
@Path("eventType") eventType: String,
|
||||
@Body content: Content?
|
||||
@Body content: Content?,
|
||||
): SendResponse
|
||||
|
||||
/**
|
||||
|
@ -139,7 +140,7 @@ internal interface RoomAPI {
|
|||
@Path("roomId") roomId: String,
|
||||
@Path("eventId") eventId: String,
|
||||
@Query("limit") limit: Int,
|
||||
@Query("filter") filter: String? = null
|
||||
@Query("filter") filter: String? = null,
|
||||
): EventContextResponse
|
||||
|
||||
/**
|
||||
|
@ -151,7 +152,7 @@ internal interface RoomAPI {
|
|||
@GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/event/{eventId}")
|
||||
suspend fun getEvent(
|
||||
@Path("roomId") roomId: String,
|
||||
@Path("eventId") eventId: String
|
||||
@Path("eventId") eventId: String,
|
||||
): Event
|
||||
|
||||
/**
|
||||
|
@ -163,7 +164,7 @@ internal interface RoomAPI {
|
|||
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/read_markers")
|
||||
suspend fun sendReadMarker(
|
||||
@Path("roomId") roomId: String,
|
||||
@Body markers: Map<String, String>
|
||||
@Body markers: Map<String, String>,
|
||||
)
|
||||
|
||||
/**
|
||||
|
@ -174,7 +175,7 @@ internal interface RoomAPI {
|
|||
@Path("roomId") roomId: String,
|
||||
@Path("receiptType") receiptType: String,
|
||||
@Path("eventId") eventId: String,
|
||||
@Body body: ReadBody
|
||||
@Body body: ReadBody,
|
||||
)
|
||||
|
||||
/**
|
||||
|
@ -187,7 +188,7 @@ internal interface RoomAPI {
|
|||
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/invite")
|
||||
suspend fun invite(
|
||||
@Path("roomId") roomId: String,
|
||||
@Body body: InviteBody
|
||||
@Body body: InviteBody,
|
||||
)
|
||||
|
||||
/**
|
||||
|
@ -199,7 +200,7 @@ internal interface RoomAPI {
|
|||
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/invite")
|
||||
suspend fun invite3pid(
|
||||
@Path("roomId") roomId: String,
|
||||
@Body body: ThreePidInviteBody
|
||||
@Body body: ThreePidInviteBody,
|
||||
)
|
||||
|
||||
/**
|
||||
|
@ -213,7 +214,7 @@ internal interface RoomAPI {
|
|||
suspend fun sendStateEvent(
|
||||
@Path("roomId") roomId: String,
|
||||
@Path("state_event_type") stateEventType: String,
|
||||
@Body params: JsonDict
|
||||
@Body params: JsonDict,
|
||||
): SendResponse
|
||||
|
||||
/**
|
||||
|
@ -229,7 +230,7 @@ internal interface RoomAPI {
|
|||
@Path("roomId") roomId: String,
|
||||
@Path("state_event_type") stateEventType: String,
|
||||
@Path("state_key") stateKey: String,
|
||||
@Body params: JsonDict
|
||||
@Body params: JsonDict,
|
||||
): SendResponse
|
||||
|
||||
/**
|
||||
|
@ -257,7 +258,7 @@ internal interface RoomAPI {
|
|||
@Path("eventType") eventType: String,
|
||||
@Query("from") from: String? = null,
|
||||
@Query("to") to: String? = null,
|
||||
@Query("limit") limit: Int? = null
|
||||
@Query("limit") limit: Int? = null,
|
||||
): RelationsResponse
|
||||
|
||||
/**
|
||||
|
@ -277,7 +278,7 @@ internal interface RoomAPI {
|
|||
@Path("relationType") relationType: String,
|
||||
@Query("from") from: String? = null,
|
||||
@Query("to") to: String? = null,
|
||||
@Query("limit") limit: Int? = null
|
||||
@Query("limit") limit: Int? = null,
|
||||
): RelationsResponse
|
||||
|
||||
/**
|
||||
|
@ -291,7 +292,7 @@ internal interface RoomAPI {
|
|||
suspend fun join(
|
||||
@Path("roomIdOrAlias") roomIdOrAlias: String,
|
||||
@Query("server_name") viaServers: List<String>,
|
||||
@Body params: JsonDict
|
||||
@Body params: JsonDict,
|
||||
): JoinRoomResponse
|
||||
|
||||
/**
|
||||
|
@ -303,7 +304,7 @@ internal interface RoomAPI {
|
|||
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/leave")
|
||||
suspend fun leave(
|
||||
@Path("roomId") roomId: String,
|
||||
@Body params: Map<String, String?>
|
||||
@Body params: Map<String, String?>,
|
||||
)
|
||||
|
||||
/**
|
||||
|
@ -315,7 +316,7 @@ internal interface RoomAPI {
|
|||
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/ban")
|
||||
suspend fun ban(
|
||||
@Path("roomId") roomId: String,
|
||||
@Body userIdAndReason: UserIdAndReason
|
||||
@Body userIdAndReason: UserIdAndReason,
|
||||
)
|
||||
|
||||
/**
|
||||
|
@ -327,7 +328,7 @@ internal interface RoomAPI {
|
|||
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/unban")
|
||||
suspend fun unban(
|
||||
@Path("roomId") roomId: String,
|
||||
@Body userIdAndReason: UserIdAndReason
|
||||
@Body userIdAndReason: UserIdAndReason,
|
||||
)
|
||||
|
||||
/**
|
||||
|
@ -339,7 +340,7 @@ internal interface RoomAPI {
|
|||
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/kick")
|
||||
suspend fun kick(
|
||||
@Path("roomId") roomId: String,
|
||||
@Body userIdAndReason: UserIdAndReason
|
||||
@Body userIdAndReason: UserIdAndReason,
|
||||
)
|
||||
|
||||
/**
|
||||
|
@ -350,14 +351,14 @@ internal interface RoomAPI {
|
|||
* @param txId the transaction Id
|
||||
* @param roomId the room id
|
||||
* @param eventId the event to delete
|
||||
* @param reason json containing reason key {"reason": "Indecent material"}
|
||||
* @param body body containing reason key {"reason": "Indecent material"} and with_relations
|
||||
*/
|
||||
@PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/redact/{eventId}/{txnId}")
|
||||
suspend fun redactEvent(
|
||||
@Path("txnId") txId: String,
|
||||
@Path("roomId") roomId: String,
|
||||
@Path("eventId") eventId: String,
|
||||
@Body reason: Map<String, String>
|
||||
@Body body: EventRedactBody,
|
||||
): SendResponse
|
||||
|
||||
/**
|
||||
|
@ -371,7 +372,7 @@ internal interface RoomAPI {
|
|||
suspend fun reportContent(
|
||||
@Path("roomId") roomId: String,
|
||||
@Path("eventId") eventId: String,
|
||||
@Body body: ReportContentBody
|
||||
@Body body: ReportContentBody,
|
||||
)
|
||||
|
||||
/**
|
||||
|
@ -388,7 +389,7 @@ internal interface RoomAPI {
|
|||
suspend fun sendTypingState(
|
||||
@Path("roomId") roomId: String,
|
||||
@Path("userId") userId: String,
|
||||
@Body body: TypingBody
|
||||
@Body body: TypingBody,
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -403,7 +404,7 @@ internal interface RoomAPI {
|
|||
@Path("userId") userId: String,
|
||||
@Path("roomId") roomId: String,
|
||||
@Path("tag") tag: String,
|
||||
@Body body: TagBody
|
||||
@Body body: TagBody,
|
||||
)
|
||||
|
||||
/**
|
||||
|
@ -413,7 +414,7 @@ internal interface RoomAPI {
|
|||
suspend fun deleteTag(
|
||||
@Path("userId") userId: String,
|
||||
@Path("roomId") roomId: String,
|
||||
@Path("tag") tag: String
|
||||
@Path("tag") tag: String,
|
||||
)
|
||||
|
||||
/**
|
||||
|
@ -424,7 +425,7 @@ internal interface RoomAPI {
|
|||
@Path("userId") userId: String,
|
||||
@Path("roomId") roomId: String,
|
||||
@Path("type") type: String,
|
||||
@Body content: JsonDict
|
||||
@Body content: JsonDict,
|
||||
)
|
||||
|
||||
/**
|
||||
|
@ -437,7 +438,7 @@ internal interface RoomAPI {
|
|||
suspend fun deleteRoomAccountData(
|
||||
@Path("userId") userId: String,
|
||||
@Path("roomId") roomId: String,
|
||||
@Path("type") type: String
|
||||
@Path("type") type: String,
|
||||
)
|
||||
|
||||
/**
|
||||
|
@ -450,7 +451,7 @@ internal interface RoomAPI {
|
|||
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/upgrade")
|
||||
suspend fun upgradeRoom(
|
||||
@Path("roomId") roomId: String,
|
||||
@Body body: RoomUpgradeBody
|
||||
@Body body: RoomUpgradeBody,
|
||||
): RoomUpgradeResponse
|
||||
|
||||
/**
|
||||
|
@ -462,7 +463,7 @@ internal interface RoomAPI {
|
|||
@GET(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "im.nheko.summary/rooms/{roomIdOrAlias}/summary")
|
||||
suspend fun getRoomSummary(
|
||||
@Path("roomIdOrAlias") roomidOrAlias: String,
|
||||
@Query("via") viaServers: List<String>?
|
||||
@Query("via") viaServers: List<String>?,
|
||||
): RoomStrippedState
|
||||
|
||||
@GET(NetworkConstants.URI_API_PREFIX_PATH_V1 + "rooms/{roomId}/threads")
|
||||
|
@ -470,6 +471,6 @@ internal interface RoomAPI {
|
|||
@Path("roomId") roomId: String,
|
||||
@Query("include") include: String? = "all",
|
||||
@Query("from") from: String? = null,
|
||||
@Query("limit") limit: Int? = null
|
||||
@Query("limit") limit: Int? = null,
|
||||
): ThreadSummariesResponse
|
||||
}
|
||||
|
|
|
@ -140,11 +140,11 @@ internal class DefaultSendService @AssistedInject constructor(
|
|||
.let { sendEvent(it) }
|
||||
}
|
||||
|
||||
override fun redactEvent(event: Event, reason: String?, additionalContent: Content?): Cancelable {
|
||||
override fun redactEvent(event: Event, reason: String?, withRelations: List<String>?, additionalContent: Content?): Cancelable {
|
||||
// TODO manage media/attachements?
|
||||
val redactionEcho = localEchoEventFactory.createRedactEvent(roomId, event.eventId!!, reason, additionalContent)
|
||||
val redactionEcho = localEchoEventFactory.createRedactEvent(roomId, event.eventId!!, reason, withRelations, additionalContent)
|
||||
.also { createLocalEcho(it) }
|
||||
return eventSenderProcessor.postRedaction(redactionEcho, reason)
|
||||
return eventSenderProcessor.postRedaction(redactionEcho, reason, withRelations)
|
||||
}
|
||||
|
||||
override fun resendTextMessage(localEcho: TimelineEvent): Cancelable {
|
||||
|
|
|
@ -70,6 +70,7 @@ import org.matrix.android.sdk.api.util.TextContent
|
|||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.session.content.ThumbnailExtractor
|
||||
import org.matrix.android.sdk.internal.session.permalinks.PermalinkFactory
|
||||
import org.matrix.android.sdk.internal.session.room.send.model.EventRedactBody
|
||||
import org.matrix.android.sdk.internal.session.room.send.pills.TextPillsUtils
|
||||
import org.matrix.android.sdk.internal.util.time.Clock
|
||||
import java.util.UUID
|
||||
|
@ -795,8 +796,16 @@ internal class LocalEchoEventFactory @Inject constructor(
|
|||
}
|
||||
}
|
||||
*/
|
||||
fun createRedactEvent(roomId: String, eventId: String, reason: String?, additionalContent: Content? = null): Event {
|
||||
fun createRedactEvent(roomId: String, eventId: String, reason: String?, withRelations: List<String>? = null, additionalContent: Content? = null): Event {
|
||||
val localId = LocalEcho.createLocalEchoId()
|
||||
val content = if (reason != null || withRelations != null) {
|
||||
EventRedactBody(
|
||||
reason = reason,
|
||||
withRelations = withRelations,
|
||||
).toContent().plus(additionalContent.orEmpty())
|
||||
} else {
|
||||
additionalContent
|
||||
}
|
||||
return Event(
|
||||
roomId = roomId,
|
||||
originServerTs = dummyOriginServerTs(),
|
||||
|
@ -804,7 +813,7 @@ internal class LocalEchoEventFactory @Inject constructor(
|
|||
eventId = localId,
|
||||
type = EventType.REDACTION,
|
||||
redacts = eventId,
|
||||
content = reason?.let { mapOf("reason" to it).toContent().plus(additionalContent.orEmpty()) } ?: additionalContent,
|
||||
content = content,
|
||||
unsignedData = UnsignedData(age = null, transactionId = localId)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ import androidx.work.WorkerParameters
|
|||
import com.squareup.moshi.JsonClass
|
||||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import org.matrix.android.sdk.internal.SessionManager
|
||||
import org.matrix.android.sdk.internal.crypto.tasks.RedactEventTask
|
||||
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
|
||||
import org.matrix.android.sdk.internal.network.executeRequest
|
||||
import org.matrix.android.sdk.internal.session.SessionComponent
|
||||
import org.matrix.android.sdk.internal.session.room.RoomAPI
|
||||
import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker
|
||||
|
@ -43,27 +43,29 @@ internal class RedactEventWorker(context: Context, params: WorkerParameters, ses
|
|||
val roomId: String,
|
||||
val eventId: String,
|
||||
val reason: String?,
|
||||
val withRelations: List<String>? = null,
|
||||
override val lastFailureMessage: String? = null
|
||||
) : SessionWorkerParams
|
||||
|
||||
@Inject lateinit var roomAPI: RoomAPI
|
||||
@Inject lateinit var globalErrorReceiver: GlobalErrorReceiver
|
||||
@Inject lateinit var redactEventTask: RedactEventTask
|
||||
|
||||
override fun injectWith(injector: SessionComponent) {
|
||||
injector.inject(this)
|
||||
}
|
||||
|
||||
override suspend fun doSafeWork(params: Params): Result {
|
||||
val eventId = params.eventId
|
||||
return runCatching {
|
||||
executeRequest(globalErrorReceiver) {
|
||||
roomAPI.redactEvent(
|
||||
params.txID,
|
||||
params.roomId,
|
||||
eventId,
|
||||
if (params.reason == null) emptyMap() else mapOf("reason" to params.reason)
|
||||
redactEventTask.execute(
|
||||
RedactEventTask.Params(
|
||||
txID = params.txID,
|
||||
roomId = params.roomId,
|
||||
eventId = params.eventId,
|
||||
reason = params.reason,
|
||||
withRelations = params.withRelations,
|
||||
)
|
||||
)
|
||||
}
|
||||
}.fold(
|
||||
{
|
||||
Result.success()
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2023 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.internal.session.room.send.model
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class EventRedactBody(
|
||||
@Json(name = "reason")
|
||||
val reason: String? = null,
|
||||
|
||||
@Json(name = "org.matrix.msc3912.with_relations")
|
||||
val withRelations: List<String>? = null,
|
||||
)
|
|
@ -26,9 +26,9 @@ internal interface EventSenderProcessor : SessionLifecycleObserver {
|
|||
|
||||
fun postEvent(event: Event, encrypt: Boolean): Cancelable
|
||||
|
||||
fun postRedaction(redactionLocalEcho: Event, reason: String?): Cancelable
|
||||
fun postRedaction(redactionLocalEcho: Event, reason: String?, withRelations: List<String>? = null): Cancelable
|
||||
|
||||
fun postRedaction(redactionLocalEchoId: String, eventToRedactId: String, roomId: String, reason: String?): Cancelable
|
||||
fun postRedaction(redactionLocalEchoId: String, eventToRedactId: String, roomId: String, reason: String?, withRelations: List<String>? = null): Cancelable
|
||||
|
||||
fun postTask(task: QueuedTask): Cancelable
|
||||
|
||||
|
|
|
@ -101,12 +101,18 @@ internal class EventSenderProcessorCoroutine @Inject constructor(
|
|||
return postTask(task)
|
||||
}
|
||||
|
||||
override fun postRedaction(redactionLocalEcho: Event, reason: String?): Cancelable {
|
||||
return postRedaction(redactionLocalEcho.eventId!!, redactionLocalEcho.redacts!!, redactionLocalEcho.roomId!!, reason)
|
||||
override fun postRedaction(redactionLocalEcho: Event, reason: String?, withRelations: List<String>?): Cancelable {
|
||||
return postRedaction(redactionLocalEcho.eventId!!, redactionLocalEcho.redacts!!, redactionLocalEcho.roomId!!, reason, withRelations)
|
||||
}
|
||||
|
||||
override fun postRedaction(redactionLocalEchoId: String, eventToRedactId: String, roomId: String, reason: String?): Cancelable {
|
||||
val task = queuedTaskFactory.createRedactTask(redactionLocalEchoId, eventToRedactId, roomId, reason)
|
||||
override fun postRedaction(
|
||||
redactionLocalEchoId: String,
|
||||
eventToRedactId: String,
|
||||
roomId: String,
|
||||
reason: String?,
|
||||
withRelations: List<String>?
|
||||
): Cancelable {
|
||||
val task = queuedTaskFactory.createRedactTask(redactionLocalEchoId, eventToRedactId, roomId, reason, withRelations)
|
||||
return postTask(task)
|
||||
}
|
||||
|
||||
|
|
|
@ -19,9 +19,11 @@ package org.matrix.android.sdk.internal.session.room.send.queue
|
|||
import android.content.Context
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.crypto.CryptoService
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.room.send.SendState
|
||||
import org.matrix.android.sdk.internal.di.SessionId
|
||||
import org.matrix.android.sdk.internal.session.room.send.LocalEchoRepository
|
||||
import org.matrix.android.sdk.internal.session.room.send.model.EventRedactBody
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -107,10 +109,18 @@ internal class QueueMemento @Inject constructor(
|
|||
info.redactionLocalEcho?.let { localEchoRepository.getUpToDateEcho(it) }?.let {
|
||||
localEchoRepository.updateSendState(it.eventId!!, it.roomId, SendState.UNSENT)
|
||||
// try to get reason
|
||||
val reason = it.content?.get("reason") as? String
|
||||
val body = it.content.toModel<EventRedactBody>()
|
||||
if (it.redacts != null && it.roomId != null) {
|
||||
Timber.d("## Send -Reschedule redact $info")
|
||||
eventProcessor.postTask(queuedTaskFactory.createRedactTask(it.eventId, it.redacts, it.roomId, reason))
|
||||
eventProcessor.postTask(
|
||||
queuedTaskFactory.createRedactTask(
|
||||
redactionLocalEcho = it.eventId,
|
||||
eventId = it.redacts,
|
||||
roomId = it.roomId,
|
||||
reason = body?.reason,
|
||||
withRelations = body?.withRelations,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
// postTask(queuedTaskFactory.createRedactTask(info.eventToRedactId, info.)
|
||||
|
|
|
@ -43,12 +43,13 @@ internal class QueuedTaskFactory @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
fun createRedactTask(redactionLocalEcho: String, eventId: String, roomId: String, reason: String?): QueuedTask {
|
||||
fun createRedactTask(redactionLocalEcho: String, eventId: String, roomId: String, reason: String?, withRelations: List<String>? = null): QueuedTask {
|
||||
return RedactQueuedTask(
|
||||
redactionLocalEchoId = redactionLocalEcho,
|
||||
toRedactEventId = eventId,
|
||||
roomId = roomId,
|
||||
reason = reason,
|
||||
withRelations = withRelations,
|
||||
redactEventTask = redactEventTask,
|
||||
localEchoRepository = localEchoRepository,
|
||||
cancelSendTracker = cancelSendTracker
|
||||
|
|
|
@ -26,13 +26,14 @@ internal class RedactQueuedTask(
|
|||
val redactionLocalEchoId: String,
|
||||
private val roomId: String,
|
||||
private val reason: String?,
|
||||
private val withRelations: List<String>?,
|
||||
private val redactEventTask: RedactEventTask,
|
||||
private val localEchoRepository: LocalEchoRepository,
|
||||
private val cancelSendTracker: CancelSendTracker
|
||||
) : QueuedTask(queueIdentifier = roomId, taskIdentifier = redactionLocalEchoId) {
|
||||
|
||||
override suspend fun doExecute() {
|
||||
redactEventTask.execute(RedactEventTask.Params(redactionLocalEchoId, roomId, toRedactEventId, reason))
|
||||
redactEventTask.execute(RedactEventTask.Params(redactionLocalEchoId, roomId, toRedactEventId, reason, withRelations))
|
||||
}
|
||||
|
||||
override fun onTaskFailed() {
|
||||
|
|
|
@ -20,6 +20,7 @@ import im.vector.app.features.voicebroadcast.VoiceBroadcastConstants
|
|||
import im.vector.app.features.voicebroadcast.model.MessageVoiceBroadcastInfoContent
|
||||
import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState
|
||||
import im.vector.app.features.voicebroadcast.model.asVoiceBroadcastEvent
|
||||
import im.vector.app.features.voicebroadcast.model.isVoiceBroadcast
|
||||
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.MessageContent
|
||||
|
@ -49,3 +50,7 @@ fun TimelineEvent.getVectorLastMessageContent(): MessageContent? {
|
|||
else -> getLastMessageContent()
|
||||
}
|
||||
}
|
||||
|
||||
fun TimelineEvent.isVoiceBroadcast(): Boolean {
|
||||
return root.isVoiceBroadcast()
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import im.vector.app.R
|
|||
import im.vector.app.SpaceStateHandler
|
||||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||
import im.vector.app.core.extensions.isVoiceBroadcast
|
||||
import im.vector.app.core.mvrx.runCatchingToAsync
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.core.resources.BuildMeta
|
||||
|
@ -859,14 +860,20 @@ class TimelineViewModel @AssistedInject constructor(
|
|||
|
||||
private fun handleRedactEvent(action: RoomDetailAction.RedactAction) {
|
||||
val event = room?.getTimelineEvent(action.targetEventId) ?: return
|
||||
if (event.isLiveLocation()) {
|
||||
when {
|
||||
event.isLiveLocation() -> {
|
||||
viewModelScope.launch {
|
||||
redactLiveLocationShareEventUseCase.execute(event.root, room, action.reason)
|
||||
}
|
||||
} else {
|
||||
}
|
||||
event.isVoiceBroadcast() -> {
|
||||
room.sendService().redactEvent(event.root, action.reason, listOf(RelationType.REFERENCE))
|
||||
}
|
||||
else -> {
|
||||
room.sendService().redactEvent(event.root, action.reason)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleUndoReact(action: RoomDetailAction.UndoReaction) {
|
||||
if (room == null) return
|
||||
|
|
|
@ -49,7 +49,9 @@ value class VoiceBroadcastEvent(val root: Event) {
|
|||
get() = root.content.toModel()
|
||||
}
|
||||
|
||||
fun Event.isVoiceBroadcast() = type == VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO
|
||||
|
||||
/**
|
||||
* Map a [VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO] state event to a [VoiceBroadcastEvent].
|
||||
*/
|
||||
fun Event.asVoiceBroadcastEvent() = if (type == VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO) VoiceBroadcastEvent(this) else null
|
||||
fun Event.asVoiceBroadcastEvent() = if (isVoiceBroadcast()) VoiceBroadcastEvent(this) else null
|
||||
|
|
Loading…
Reference in New Issue