Merge pull request #5762 from vector-im/feature/bma/dokka_2

Make some data class immutable
This commit is contained in:
Benoit Marty 2022-04-14 17:17:55 +02:00 committed by GitHub
commit a171a29bf1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 120 additions and 105 deletions

1
changelog.d/5762.sdk Normal file
View file

@ -0,0 +1 @@
Some data classes are now immutable, using `val` instead of `var`

View file

@ -50,6 +50,7 @@ ext.groups = [
'com.beust',
'com.davemorrissey.labs',
'com.dropbox.core',
'com.soywiz.korlibs.korte',
'com.facebook.fbjni',
'com.facebook.fresco',
'com.facebook.infer.annotation',

View file

@ -24,8 +24,8 @@ import kotlinx.parcelize.Parcelize
*/
@Parcelize
data class LocalizedFlowDataLoginTerms(
var policyName: String? = null,
var version: String? = null,
var localizedUrl: String? = null,
var localizedName: String? = null
val policyName: String?,
val version: String?,
val localizedUrl: String?,
val localizedName: String?
) : Parcelable

View file

@ -18,17 +18,16 @@ package org.matrix.android.sdk.api.session.crypto.keysbackup
/**
* Data model for response to [KeysBackup.getKeysBackupTrust()].
* TODO Members should be only val
*/
data class KeysBackupVersionTrust(
/**
* Flag to indicate if the backup is trusted.
* true if there is a signature that is valid & from a trusted device.
*/
var usable: Boolean = false,
val usable: Boolean,
/**
* Signatures found in the backup version.
*/
var signatures: MutableList<KeysBackupVersionTrustSignature> = ArrayList()
val signatures: List<KeysBackupVersionTrustSignature> = emptyList()
)

View file

@ -20,23 +20,21 @@ import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
/**
* A signature in a `KeysBackupVersionTrust` object.
* TODO Make it a data class with only val
*/
class KeysBackupVersionTrustSignature {
data class KeysBackupVersionTrustSignature(
/**
* The id of the device that signed the backup version.
*/
val deviceId: String?,
/**
* The id of the device that signed the backup version.
*/
var deviceId: String? = null
/**
* The device that signed the backup version.
* Can be null if the device is not known.
*/
val device: CryptoDeviceInfo?,
/**
* The device that signed the backup version.
* Can be null if the device is not known.
*/
var device: CryptoDeviceInfo? = null
/**
* Flag to indicate the signature from this device is valid.
*/
var valid = false
}
/**
* Flag to indicate the signature from this device is valid.
*/
val valid: Boolean,
)

View file

@ -22,12 +22,12 @@ import org.matrix.android.sdk.internal.crypto.model.CryptoInfo
data class CryptoDeviceInfo(
val deviceId: String,
override val userId: String,
var algorithms: List<String>? = null,
val algorithms: List<String>? = null,
override val keys: Map<String, String>? = null,
override val signatures: Map<String, Map<String, String>>? = null,
val unsigned: UnsignedDeviceInfo? = null,
var trustLevel: DeviceTrustLevel? = null,
var isBlocked: Boolean = false,
val isBlocked: Boolean = false,
val firstTimeSeenLocalTs: Long? = null
) : CryptoInfo {

View file

@ -25,14 +25,14 @@ import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequest
@JsonClass(generateAdapter = true)
data class OutgoingRoomKeyRequest(
// RequestBody
var requestBody: RoomKeyRequestBody?,
val requestBody: RoomKeyRequestBody?,
// list of recipients for the request
override var recipients: Map<String, List<String>>,
override val recipients: Map<String, List<String>>,
// Unique id for this request. Used for both
// an id within the request for later pairing with a cancellation, and for
// the transaction id when sending the to_device messages to our local
override var requestId: String, // current state of this request
override var state: OutgoingGossipingRequestState
override val requestId: String, // current state of this request
override val state: OutgoingGossipingRequestState
// transaction id for the cancellation, if any
// override var cancellationTxnId: String? = null
) : OutgoingGossipingRequest {
@ -43,9 +43,7 @@ data class OutgoingRoomKeyRequest(
* @return the room id.
*/
val roomId: String?
get() = if (null != requestBody) {
requestBody!!.roomId
} else null
get() = requestBody?.roomId
/**
* Used only for log.
@ -53,7 +51,5 @@ data class OutgoingRoomKeyRequest(
* @return the session id
*/
val sessionId: String?
get() = if (null != requestBody) {
requestBody!!.sessionId
} else null
get() = requestBody?.sessionId
}

View file

@ -16,9 +16,9 @@
package org.matrix.android.sdk.api.session.room.model
data class EventAnnotationsSummary(
var eventId: String,
var reactionsSummary: List<ReactionAggregatedSummary> = emptyList(),
var editSummary: EditAggregatedSummary? = null,
var pollResponseSummary: PollResponseAggregatedSummary? = null,
var referencesAggregatedSummary: ReferencesAggregatedSummary? = null
val eventId: String,
val reactionsSummary: List<ReactionAggregatedSummary> = emptyList(),
val editSummary: EditAggregatedSummary? = null,
val pollResponseSummary: PollResponseAggregatedSummary? = null,
val referencesAggregatedSummary: ReferencesAggregatedSummary? = null
)

View file

@ -16,13 +16,11 @@
package org.matrix.android.sdk.api.session.room.model
data class PollResponseAggregatedSummary(
var aggregatedContent: PollSummaryContent? = null,
val aggregatedContent: PollSummaryContent? = null,
// If set the poll is closed (Clients SHOULD NOT consider responses after the close event)
var closedTime: Long? = null,
val closedTime: Long? = null,
// Clients SHOULD validate that the option in the relationship is a valid option, and ignore the response if invalid
var nbOptions: Int = 0,
val nbOptions: Int = 0,
// The list of the eventIDs used to build the summary (might be out of sync if chunked received from message chunk)
val sourceEvents: List<String>,
val localEchos: List<String>

View file

@ -24,13 +24,13 @@ import com.squareup.moshi.JsonClass
*/
@JsonClass(generateAdapter = true)
data class PollSummaryContent(
var myVote: String? = null,
// Array of VoteInfo, list is constructed so that there is only one vote by user
val myVote: String? = null,
// List of VoteInfo, list is constructed so that there is only one vote by user
// And that optionIndex is valid
var votes: List<VoteInfo>? = null,
var votesSummary: Map<String, VoteSummary>? = null,
var totalVotes: Int = 0,
var winnerVoteCount: Int = 0
val votes: List<VoteInfo>? = null,
val votesSummary: Map<String, VoteSummary>? = null,
val totalVotes: Int = 0,
val winnerVoteCount: Int = 0
)
@JsonClass(generateAdapter = true)

View file

@ -56,7 +56,7 @@ data class TimelineEvent(
* It's not unique on the timeline as it's reset on each chunk.
*/
val displayIndex: Int,
var ownedByThreadChunk: Boolean = false,
val ownedByThreadChunk: Boolean = false,
val senderInfo: SenderInfo,
val annotations: EventAnnotationsSummary? = null,
val readReceipts: List<ReadReceipt> = emptyList()

View file

@ -18,7 +18,7 @@ package org.matrix.android.sdk.api.session.securestorage
data class SsssKeyCreationInfo(
val keyId: String = "",
var content: SecretStorageKeyContent?,
val content: SecretStorageKeyContent?,
val recoveryKey: String = "",
val keySpec: SsssKeySpec
)

View file

@ -29,7 +29,7 @@ data class ThreadDetails(
val threadSummarySenderInfo: SenderInfo? = null,
val threadSummaryLatestEvent: Event? = null,
val lastMessageTimestamp: Long? = null,
var threadNotificationState: ThreadNotificationState = ThreadNotificationState.NO_NEW_MESSAGE,
val threadNotificationState: ThreadNotificationState = ThreadNotificationState.NO_NEW_MESSAGE,
val isThread: Boolean = false,
val lastRootThreadEdition: String? = null
)

View file

@ -19,9 +19,9 @@ package org.matrix.android.sdk.internal.crypto
import org.matrix.android.sdk.api.session.crypto.model.OutgoingGossipingRequestState
internal interface OutgoingGossipingRequest {
var recipients: Map<String, List<String>>
var requestId: String
var state: OutgoingGossipingRequestState
val recipients: Map<String, List<String>>
val requestId: String
val state: OutgoingGossipingRequestState
// transaction id for the cancellation, if any
// var cancellationTxnId: String?
}

View file

@ -20,9 +20,8 @@ import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo
/**
* Define the result of an encryption file
* TODO var should be val
*/
internal data class EncryptionResult(
var encryptedFileInfo: EncryptedFileInfo,
var encryptedByteArray: ByteArray
val encryptedFileInfo: EncryptedFileInfo,
val encryptedByteArray: ByteArray
)

View file

@ -409,20 +409,22 @@ internal class DefaultKeysBackupService @Inject constructor(
*/
@WorkerThread
private fun getKeysBackupTrustBg(keysBackupVersion: KeysVersionResult): KeysBackupVersionTrust {
val keysBackupVersionTrust = KeysBackupVersionTrust()
val authData = keysBackupVersion.getAuthDataAsMegolmBackupAuthData()
if (authData == null || authData.publicKey.isEmpty() || authData.signatures.isNullOrEmpty()) {
Timber.v("getKeysBackupTrust: Key backup is absent or missing required data")
return keysBackupVersionTrust
return KeysBackupVersionTrust(usable = false)
}
val mySigs = authData.signatures[userId]
if (mySigs.isNullOrEmpty()) {
Timber.v("getKeysBackupTrust: Ignoring key backup because it lacks any signatures from this user")
return keysBackupVersionTrust
return KeysBackupVersionTrust(usable = false)
}
var keysBackupVersionTrustIsUsable = false
val keysBackupVersionTrustSignatures = mutableListOf<KeysBackupVersionTrustSignature>()
for ((keyId, mySignature) in mySigs) {
// XXX: is this how we're supposed to get the device id?
var deviceId: String? = null
@ -449,19 +451,23 @@ internal class DefaultKeysBackupService @Inject constructor(
}
if (isSignatureValid && device.isVerified) {
keysBackupVersionTrust.usable = true
keysBackupVersionTrustIsUsable = true
}
}
val signature = KeysBackupVersionTrustSignature()
signature.device = device
signature.valid = isSignatureValid
signature.deviceId = deviceId
keysBackupVersionTrust.signatures.add(signature)
val signature = KeysBackupVersionTrustSignature(
deviceId = deviceId,
device = device,
valid = isSignatureValid,
)
keysBackupVersionTrustSignatures.add(signature)
}
}
return keysBackupVersionTrust
return KeysBackupVersionTrust(
usable = keysBackupVersionTrustIsUsable,
signatures = keysBackupVersionTrustSignatures
)
}
override fun trustKeysBackupVersion(keysBackupVersion: KeysVersionResult,
@ -1103,7 +1109,7 @@ internal class DefaultKeysBackupService @Inject constructor(
privateKeySalt: String,
privateKeyIterations: Int,
progressListener: ProgressListener): ByteArray {
return deriveKey(passphrase, privateKeySalt, privateKeyIterations, progressListener)
return deriveKey(passphrase, privateKeySalt, privateKeyIterations, progressListener)
}
/**

View file

@ -30,17 +30,17 @@ internal data class BindThreePidBody(
* Required. The identity server to use. (without "https://")
*/
@Json(name = "id_server")
var identityServerUrlWithoutProtocol: String,
val identityServerUrlWithoutProtocol: String,
/**
* Required. An access token previously registered with the identity server.
*/
@Json(name = "id_access_token")
var identityServerAccessToken: String,
val identityServerAccessToken: String,
/**
* Required. The session identifier given by the identity server.
*/
@Json(name = "sid")
var sid: String
val sid: String
)

View file

@ -316,14 +316,16 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
ContentMapper
.map(eventAnnotationsSummaryEntity.pollResponseSummary?.aggregatedContent)
?.toModel<PollSummaryContent>()
?.apply {
totalVotes = 0
winnerVoteCount = 0
votes = emptyList()
votesSummary = emptyMap()
}
?.apply {
eventAnnotationsSummaryEntity.pollResponseSummary?.aggregatedContent = ContentMapper.map(toContent())
?.let { existingPollSummaryContent ->
eventAnnotationsSummaryEntity.pollResponseSummary?.aggregatedContent = ContentMapper.map(
PollSummaryContent(
myVote = existingPollSummaryContent.myVote,
votes = emptyList(),
votesSummary = emptyMap(),
totalVotes = 0,
winnerVoteCount = 0,
)
.toContent())
}
val txId = event.unsignedData?.transactionId
@ -410,15 +412,15 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
existing.pollResponseSummary = it
}
val closedTime = existingPollSummary?.closedTime
val closedTime = existingPollSummary.closedTime
if (closedTime != null && eventTimestamp > closedTime) {
Timber.v("## POLL is closed ignore event poll:$targetEventId, event :${event.eventId}")
return
}
val sumModel = ContentMapper.map(existingPollSummary?.aggregatedContent).toModel<PollSummaryContent>() ?: PollSummaryContent()
val currentModel = ContentMapper.map(existingPollSummary.aggregatedContent).toModel<PollSummaryContent>()
if (existingPollSummary!!.sourceEvents.contains(eventId)) {
if (existingPollSummary.sourceEvents.contains(eventId)) {
// ignore this event, we already know it (??)
Timber.v("## POLL ignoring event for summary, it's known eventId:$eventId")
return
@ -443,7 +445,9 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
return
}
val votes = sumModel.votes?.toMutableList() ?: ArrayList()
val votes = currentModel?.votes.orEmpty().toMutableList()
var myVote: String? = null
val existingVoteIndex = votes.indexOfFirst { it.userId == senderId }
if (existingVoteIndex != -1) {
// Is the vote newer?
@ -452,7 +456,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
// Take the new one
votes[existingVoteIndex] = VoteInfo(senderId, option, eventTimestamp)
if (userId == senderId) {
sumModel.myVote = option
myVote = option
}
Timber.v("## POLL adding vote $option for user $senderId in poll :$targetEventId ")
} else {
@ -461,16 +465,14 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
} else {
votes.add(VoteInfo(senderId, option, eventTimestamp))
if (userId == senderId) {
sumModel.myVote = option
myVote = option
}
Timber.v("## POLL adding vote $option for user $senderId in poll :$targetEventId ")
}
sumModel.votes = votes
// Precompute the percentage of votes for all options
val totalVotes = votes.size
sumModel.totalVotes = totalVotes
sumModel.votesSummary = votes
val newVotesSummary = votes
.groupBy({ it.option }, { it.userId })
.mapValues {
VoteSummary(
@ -478,7 +480,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
percentage = if (totalVotes == 0 && it.value.isEmpty()) 0.0 else it.value.size.toDouble() / totalVotes
)
}
sumModel.winnerVoteCount = sumModel.votesSummary?.maxOf { it.value.total } ?: 0
val newWinnerVoteCount = newVotesSummary.maxOf { it.value.total }
if (isLocalEcho) {
existingPollSummary.sourceLocalEchoEvents.add(eventId)
@ -486,7 +488,15 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
existingPollSummary.sourceEvents.add(eventId)
}
existingPollSummary.aggregatedContent = ContentMapper.map(sumModel.toContent())
val newSumModel = PollSummaryContent(
myVote = myVote,
votes = votes,
votesSummary = newVotesSummary,
totalVotes = totalVotes,
winnerVoteCount = newWinnerVoteCount
)
existingPollSummary.aggregatedContent = ContentMapper.map(newSumModel.toContent())
}
private fun handleEndPoll(realm: Realm,

View file

@ -20,7 +20,7 @@ import io.realm.Realm
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.room.model.message.MessageLiveLocationContent
interface LiveLocationAggregationProcessor {
internal interface LiveLocationAggregationProcessor {
fun handleLiveLocation(realm: Realm,
event: Event,
content: MessageLiveLocationContent,

View file

@ -48,15 +48,17 @@ fun TermPolicies.toLocalizedLoginTerms(userLanguage: String,
val policies = get("policies")
if (policies is Map<*, *>) {
policies.keys.forEach { policyName ->
val localizedFlowDataLoginTerms = LocalizedFlowDataLoginTerms()
localizedFlowDataLoginTerms.policyName = policyName as String
val localizedFlowDataLoginTermsPolicyName = policyName as String
var localizedFlowDataLoginTermsVersion: String? = null
var localizedFlowDataLoginTermsLocalizedUrl: String? = null
var localizedFlowDataLoginTermsLocalizedName: String? = null
val policy = policies[policyName]
// Enter this policy
if (policy is Map<*, *>) {
// Version
localizedFlowDataLoginTerms.version = policy["version"] as String?
localizedFlowDataLoginTermsVersion = policy["version"] as String?
var userLanguageUrlAndName: UrlAndName? = null
var defaultLanguageUrlAndName: UrlAndName? = null
@ -86,21 +88,26 @@ fun TermPolicies.toLocalizedLoginTerms(userLanguage: String,
// Copy found language data by priority
when {
userLanguageUrlAndName != null -> {
localizedFlowDataLoginTerms.localizedUrl = userLanguageUrlAndName!!.url
localizedFlowDataLoginTerms.localizedName = userLanguageUrlAndName!!.name
localizedFlowDataLoginTermsLocalizedUrl = userLanguageUrlAndName!!.url
localizedFlowDataLoginTermsLocalizedName = userLanguageUrlAndName!!.name
}
defaultLanguageUrlAndName != null -> {
localizedFlowDataLoginTerms.localizedUrl = defaultLanguageUrlAndName!!.url
localizedFlowDataLoginTerms.localizedName = defaultLanguageUrlAndName!!.name
localizedFlowDataLoginTermsLocalizedUrl = defaultLanguageUrlAndName!!.url
localizedFlowDataLoginTermsLocalizedName = defaultLanguageUrlAndName!!.name
}
firstUrlAndName != null -> {
localizedFlowDataLoginTerms.localizedUrl = firstUrlAndName!!.url
localizedFlowDataLoginTerms.localizedName = firstUrlAndName!!.name
localizedFlowDataLoginTermsLocalizedUrl = firstUrlAndName!!.url
localizedFlowDataLoginTermsLocalizedName = firstUrlAndName!!.name
}
}
}
result.add(localizedFlowDataLoginTerms)
result.add(LocalizedFlowDataLoginTerms(
policyName = localizedFlowDataLoginTermsPolicyName,
version = localizedFlowDataLoginTermsVersion,
localizedUrl = localizedFlowDataLoginTermsLocalizedUrl,
localizedName = localizedFlowDataLoginTermsLocalizedName
))
}
}