1
0
mirror of https://github.com/vector-im/riotX-android synced 2025-10-06 08:12:46 +02:00

Compare commits

...

3 Commits

Author SHA1 Message Date
Onuray Sahin
d932c5598b Use extended credentials for login response. 2021-03-08 15:22:23 +03:00
ganfra
06770ca010 Create Extended wrapper class and try it in Sync 2021-02-18 19:39:15 +01:00
ganfra
4b099dfef9 Moshi codegen: first dirty version of the json keys generator 2021-02-18 17:43:42 +01:00
20 changed files with 329 additions and 29 deletions

View File

@@ -137,6 +137,7 @@ dependencies {
implementation "com.squareup.moshi:moshi-adapters:$moshi_version" implementation "com.squareup.moshi:moshi-adapters:$moshi_version"
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version" kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"
kapt project(':moshi:codegen')
implementation "ru.noties.markwon:core:$markwon_version" implementation "ru.noties.markwon:core:$markwon_version"

View File

@@ -0,0 +1,22 @@
/*
* Copyright (c) 2021 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.api.util
data class Extended<T : Any>(
val wrapped: T,
val undefined: JsonDict
)

View File

@@ -17,6 +17,7 @@
package org.matrix.android.sdk.internal.auth package org.matrix.android.sdk.internal.auth
import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.auth.data.Credentials
import org.matrix.android.sdk.api.util.Extended
import org.matrix.android.sdk.internal.auth.data.LoginFlowResponse import org.matrix.android.sdk.internal.auth.data.LoginFlowResponse
import org.matrix.android.sdk.internal.auth.data.PasswordLoginParams import org.matrix.android.sdk.internal.auth.data.PasswordLoginParams
import org.matrix.android.sdk.internal.auth.data.RiotConfig import org.matrix.android.sdk.internal.auth.data.RiotConfig
@@ -97,12 +98,12 @@ internal interface AuthAPI {
*/ */
@Headers("CONNECT_TIMEOUT:60000", "READ_TIMEOUT:60000", "WRITE_TIMEOUT:60000") @Headers("CONNECT_TIMEOUT:60000", "READ_TIMEOUT:60000", "WRITE_TIMEOUT:60000")
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "login") @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "login")
fun login(@Body loginParams: PasswordLoginParams): Call<Credentials> fun login(@Body loginParams: PasswordLoginParams): Call<Extended<Credentials>>
// Unfortunately we cannot use interface for @Body parameter, so I duplicate the method for the type TokenLoginParams // Unfortunately we cannot use interface for @Body parameter, so I duplicate the method for the type TokenLoginParams
@Headers("CONNECT_TIMEOUT:60000", "READ_TIMEOUT:60000", "WRITE_TIMEOUT:60000") @Headers("CONNECT_TIMEOUT:60000", "READ_TIMEOUT:60000", "WRITE_TIMEOUT:60000")
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "login") @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "login")
fun login(@Body loginParams: TokenLoginParams): Call<Credentials> fun login(@Body loginParams: TokenLoginParams): Call<Extended<Credentials>>
/** /**
* Ask the homeserver to reset the password associated with the provided email. * Ask the homeserver to reset the password associated with the provided email.

View File

@@ -41,6 +41,7 @@ import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import org.matrix.android.sdk.api.util.Extended
internal class DefaultLoginWizard( internal class DefaultLoginWizard(
okHttpClient: OkHttpClient, okHttpClient: OkHttpClient,
@@ -73,11 +74,11 @@ internal class DefaultLoginWizard(
val loginParams = TokenLoginParams( val loginParams = TokenLoginParams(
token = loginToken token = loginToken
) )
val credentials = executeRequest<Credentials>(null) { val credentials = executeRequest<Extended<Credentials>>(null) {
apiCall = authAPI.login(loginParams) apiCall = authAPI.login(loginParams)
} }
sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig) sessionCreator.createSession(credentials.wrapped, pendingSessionData.homeServerConnectionConfig)
} }
} }
@@ -89,11 +90,11 @@ internal class DefaultLoginWizard(
} else { } else {
PasswordLoginParams.userIdentifier(login, password, deviceName) PasswordLoginParams.userIdentifier(login, password, deviceName)
} }
val credentials = executeRequest<Credentials>(null) { val credentials = executeRequest<Extended<Credentials>>(null) {
apiCall = authAPI.login(loginParams) apiCall = authAPI.login(loginParams)
} }
sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig) sessionCreator.createSession(credentials.wrapped, pendingSessionData.homeServerConnectionConfig)
} }
override fun resetPassword(email: String, newPassword: String, callback: MatrixCallback<Unit>): Cancelable { override fun resetPassword(email: String, newPassword: String, callback: MatrixCallback<Unit>): Cancelable {

View File

@@ -31,6 +31,7 @@ import org.matrix.android.sdk.internal.network.httpclient.addSocketFactory
import org.matrix.android.sdk.internal.network.ssl.UnrecognizedCertificateException import org.matrix.android.sdk.internal.network.ssl.UnrecognizedCertificateException
import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.task.Task
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import org.matrix.android.sdk.api.util.Extended
import javax.inject.Inject import javax.inject.Inject
internal interface DirectLoginTask : Task<DirectLoginTask.Params, Session> { internal interface DirectLoginTask : Task<DirectLoginTask.Params, Session> {
@@ -59,7 +60,7 @@ internal class DefaultDirectLoginTask @Inject constructor(
val loginParams = PasswordLoginParams.userIdentifier(params.userId, params.password, params.deviceName) val loginParams = PasswordLoginParams.userIdentifier(params.userId, params.password, params.deviceName)
val credentials = try { val credentials = try {
executeRequest<Credentials>(null) { executeRequest<Extended<Credentials>>(null) {
apiCall = authAPI.login(loginParams) apiCall = authAPI.login(loginParams)
} }
} catch (throwable: Throwable) { } catch (throwable: Throwable) {
@@ -75,7 +76,7 @@ internal class DefaultDirectLoginTask @Inject constructor(
} }
} }
return sessionCreator.createSession(credentials, params.homeServerConnectionConfig) return sessionCreator.createSession(credentials.wrapped, params.homeServerConnectionConfig)
} }
private fun buildClient(homeServerConnectionConfig: HomeServerConnectionConfig): OkHttpClient { private fun buildClient(homeServerConnectionConfig: HomeServerConnectionConfig): OkHttpClient {

View File

@@ -32,6 +32,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageType
import org.matrix.android.sdk.api.session.room.model.message.MessageVerificationRequestContent import org.matrix.android.sdk.api.session.room.model.message.MessageVerificationRequestContent
import org.matrix.android.sdk.api.session.room.model.message.MessageVideoContent import org.matrix.android.sdk.api.session.room.model.message.MessageVideoContent
import org.matrix.android.sdk.internal.network.parsing.CipherSuiteMoshiAdapter import org.matrix.android.sdk.internal.network.parsing.CipherSuiteMoshiAdapter
import org.matrix.android.sdk.internal.network.parsing.ExtendedAdapterFactory
import org.matrix.android.sdk.internal.network.parsing.ForceToBooleanJsonAdapter import org.matrix.android.sdk.internal.network.parsing.ForceToBooleanJsonAdapter
import org.matrix.android.sdk.internal.network.parsing.RuntimeJsonAdapterFactory import org.matrix.android.sdk.internal.network.parsing.RuntimeJsonAdapterFactory
import org.matrix.android.sdk.internal.network.parsing.TlsVersionMoshiAdapter import org.matrix.android.sdk.internal.network.parsing.TlsVersionMoshiAdapter
@@ -44,6 +45,7 @@ object MoshiProvider {
.add(ForceToBooleanJsonAdapter()) .add(ForceToBooleanJsonAdapter())
.add(CipherSuiteMoshiAdapter()) .add(CipherSuiteMoshiAdapter())
.add(TlsVersionMoshiAdapter()) .add(TlsVersionMoshiAdapter())
.add(ExtendedAdapterFactory())
.add(RuntimeJsonAdapterFactory.of(MessageContent::class.java, "msgtype", MessageDefaultContent::class.java) .add(RuntimeJsonAdapterFactory.of(MessageContent::class.java, "msgtype", MessageDefaultContent::class.java)
.registerSubtype(MessageTextContent::class.java, MessageType.MSGTYPE_TEXT) .registerSubtype(MessageTextContent::class.java, MessageType.MSGTYPE_TEXT)
.registerSubtype(MessageNoticeContent::class.java, MessageType.MSGTYPE_NOTICE) .registerSubtype(MessageNoticeContent::class.java, MessageType.MSGTYPE_NOTICE)

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 2021 New Vector Ltd
*
* 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.network.parsing
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonReader
import com.squareup.moshi.JsonWriter
import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import org.matrix.android.sdk.api.util.Extended
import org.matrix.android.sdk.api.util.JSON_DICT_PARAMETERIZED_TYPE
import org.matrix.android.sdk.api.util.JsonDict
import org.matrix.android.sdk.internal.JsonKeys
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
internal class ExtendedAdapterFactory() : JsonAdapter.Factory {
override fun create(type: Type, annotations: MutableSet<out Annotation>, moshi: Moshi): JsonAdapter<*>? {
if (Types.getRawType(type) != Extended::class.java) {
return null
}
val wrappedType = (type as ParameterizedType).actualTypeArguments.firstOrNull() ?: return null
val rawType = Types.getRawType(wrappedType)
val adapter = moshi.adapter(rawType)
return ExtendedAdapter(rawType, adapter, moshi.adapter(JSON_DICT_PARAMETERIZED_TYPE))
}
}
internal class ExtendedAdapter(private val rawType: Class<*>,
private val wrappedAdapter: JsonAdapter<*>,
private val jsonDictAdapter: JsonAdapter<JsonDict>) : JsonAdapter<Extended<*>>() {
override fun fromJson(reader: JsonReader): Extended<*>? {
val wrapped = wrappedAdapter.fromJson(reader.peekJson()) ?: return null
val allValues = jsonDictAdapter.fromJson(reader) ?: return null
val definedKeys = JsonKeys.jsonKeysByClasses[rawType].orEmpty()
val filteredValues = allValues.filterNot {
definedKeys.contains(it.key)
}
return Extended(wrapped, filteredValues)
}
override fun toJson(writer: JsonWriter, value: Extended<*>?) {
// WILL SEE
}
}

View File

@@ -50,7 +50,7 @@ internal class DefaultProcessEventForPushTask @Inject constructor(
} }
val newJoinEvents = params.syncResponse.join val newJoinEvents = params.syncResponse.join
.mapNotNull { (key, value) -> .mapNotNull { (key, value) ->
value.timeline?.events?.map { it.copy(roomId = key) } value.wrapped.timeline?.events?.map { it.copy(roomId = key) }
} }
.flatten() .flatten()
val inviteEvents = params.syncResponse.invite val inviteEvents = params.syncResponse.invite
@@ -80,7 +80,7 @@ internal class DefaultProcessEventForPushTask @Inject constructor(
val allRedactedEvents = params.syncResponse.join val allRedactedEvents = params.syncResponse.join
.asSequence() .asSequence()
.mapNotNull { (_, value) -> value.timeline?.events } .mapNotNull { (_, value) -> value.wrapped.timeline?.events }
.flatten() .flatten()
.filter { it.type == EventType.REDACTION } .filter { it.type == EventType.REDACTION }
.mapNotNull { it.redacts } .mapNotNull { it.redacts }

View File

@@ -204,7 +204,7 @@ internal interface RoomAPI {
* Ref: https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-rooms-roomid-state * Ref: https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-rooms-roomid-state
*/ */
@GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/state") @GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/state")
fun getRoomState(@Path("roomId") roomId: String) : Call<List<Event>> fun getRoomState(@Path("roomId") roomId: String): Call<List<Event>>
/** /**
* Send a relation event to a room. * Send a relation event to a room.

View File

@@ -26,6 +26,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomCanonicalAliasContent
import org.matrix.android.sdk.api.session.room.model.RoomNameContent import org.matrix.android.sdk.api.session.room.model.RoomNameContent
import org.matrix.android.sdk.api.session.room.model.RoomTopicContent import org.matrix.android.sdk.api.session.room.model.RoomTopicContent
import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.room.send.SendState
import org.matrix.android.sdk.api.util.JsonDict
import org.matrix.android.sdk.internal.crypto.EventDecryptor import org.matrix.android.sdk.internal.crypto.EventDecryptor
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
import org.matrix.android.sdk.internal.crypto.crosssigning.DefaultCrossSigningService import org.matrix.android.sdk.internal.crypto.crosssigning.DefaultCrossSigningService
@@ -47,7 +48,6 @@ import org.matrix.android.sdk.internal.session.room.RoomAvatarResolver
import org.matrix.android.sdk.internal.session.room.membership.RoomDisplayNameResolver import org.matrix.android.sdk.internal.session.room.membership.RoomDisplayNameResolver
import org.matrix.android.sdk.internal.session.room.membership.RoomMemberHelper import org.matrix.android.sdk.internal.session.room.membership.RoomMemberHelper
import org.matrix.android.sdk.internal.session.sync.model.RoomSyncSummary import org.matrix.android.sdk.internal.session.sync.model.RoomSyncSummary
import org.matrix.android.sdk.internal.session.sync.model.RoomSyncUnreadNotifications
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@@ -62,7 +62,7 @@ internal class RoomSummaryUpdater @Inject constructor(
roomId: String, roomId: String,
membership: Membership? = null, membership: Membership? = null,
roomSummary: RoomSyncSummary? = null, roomSummary: RoomSyncSummary? = null,
unreadNotifications: RoomSyncUnreadNotifications? = null, unreadNotifications: JsonDict? = null,
updateMembers: Boolean = false, updateMembers: Boolean = false,
inviterId: String? = null) { inviterId: String? = null) {
val roomSummaryEntity = RoomSummaryEntity.getOrCreate(realm, roomId) val roomSummaryEntity = RoomSummaryEntity.getOrCreate(realm, roomId)
@@ -78,8 +78,8 @@ internal class RoomSummaryUpdater @Inject constructor(
roomSummaryEntity.joinedMembersCount = roomSummary.joinedMembersCount roomSummaryEntity.joinedMembersCount = roomSummary.joinedMembersCount
} }
} }
roomSummaryEntity.highlightCount = unreadNotifications?.highlightCount ?: 0 roomSummaryEntity.highlightCount = (unreadNotifications?.get("highlight_count") as? Double)?.toInt() ?: 0
roomSummaryEntity.notificationCount = unreadNotifications?.notificationCount ?: 0 roomSummaryEntity.notificationCount = (unreadNotifications?.get("notification_count") as? Double)?.toInt() ?: 0
if (membership != null) { if (membership != null) {
roomSummaryEntity.membership = membership roomSummaryEntity.membership = membership

View File

@@ -27,6 +27,8 @@ 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.RoomMemberContent
import org.matrix.android.sdk.api.session.room.model.tag.RoomTagContent import org.matrix.android.sdk.api.session.room.model.tag.RoomTagContent
import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.room.send.SendState
import org.matrix.android.sdk.api.util.Extended
import org.matrix.android.sdk.api.util.JsonDict
import org.matrix.android.sdk.internal.crypto.DefaultCryptoService import org.matrix.android.sdk.internal.crypto.DefaultCryptoService
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult
@@ -78,7 +80,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
private val timelineInput: TimelineInput) { private val timelineInput: TimelineInput) {
sealed class HandlingStrategy { sealed class HandlingStrategy {
data class JOINED(val data: Map<String, RoomSync>) : HandlingStrategy() data class JOINED(val data: Map<String, Extended<RoomSync>>) : HandlingStrategy()
data class INVITED(val data: Map<String, InvitedRoomSync>) : HandlingStrategy() data class INVITED(val data: Map<String, InvitedRoomSync>) : HandlingStrategy()
data class LEFT(val data: Map<String, RoomSync>) : HandlingStrategy() data class LEFT(val data: Map<String, RoomSync>) : HandlingStrategy()
} }
@@ -125,12 +127,12 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
private fun handleJoinedRoom(realm: Realm, private fun handleJoinedRoom(realm: Realm,
roomId: String, roomId: String,
roomSync: RoomSync, roomSyncExtended: Extended<RoomSync>,
isInitialSync: Boolean, isInitialSync: Boolean,
insertType: EventInsertType, insertType: EventInsertType,
syncLocalTimestampMillis: Long): RoomEntity { syncLocalTimestampMillis: Long): RoomEntity {
Timber.v("Handle join sync for room $roomId") Timber.v("Handle join sync for room $roomId")
val roomSync = roomSyncExtended.wrapped
var ephemeralResult: EphemeralResult? = null var ephemeralResult: EphemeralResult? = null
if (roomSync.ephemeral?.events?.isNotEmpty() == true) { if (roomSync.ephemeral?.events?.isNotEmpty() == true) {
ephemeralResult = handleEphemeral(realm, roomId, roomSync.ephemeral, isInitialSync) ephemeralResult = handleEphemeral(realm, roomId, roomSync.ephemeral, isInitialSync)
@@ -186,12 +188,13 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
roomTypingUsersHandler.handle(realm, roomId, ephemeralResult) roomTypingUsersHandler.handle(realm, roomId, ephemeralResult)
roomChangeMembershipStateDataSource.setMembershipFromSync(roomId, Membership.JOIN) roomChangeMembershipStateDataSource.setMembershipFromSync(roomId, Membership.JOIN)
@Suppress("UNCHECKED_CAST")
roomSummaryUpdater.update( roomSummaryUpdater.update(
realm, realm,
roomId, roomId,
Membership.JOIN, Membership.JOIN,
roomSync.summary, roomSync.summary,
roomSync.unreadNotifications, roomSyncExtended.undefined["unread_notifications"] as? JsonDict,
updateMembers = hasRoomMember updateMembers = hasRoomMember
) )
return roomEntity return roomEntity
@@ -267,7 +270,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
roomEntity.chunks.clearWith { it.deleteOnCascade(deleteStateEvents = true, canDeleteRoot = true) } roomEntity.chunks.clearWith { it.deleteOnCascade(deleteStateEvents = true, canDeleteRoot = true) }
roomTypingUsersHandler.handle(realm, roomId, null) roomTypingUsersHandler.handle(realm, roomId, null)
roomChangeMembershipStateDataSource.setMembershipFromSync(roomId, Membership.LEAVE) roomChangeMembershipStateDataSource.setMembershipFromSync(roomId, Membership.LEAVE)
roomSummaryUpdater.update(realm, roomId, membership, roomSync.summary, roomSync.unreadNotifications) roomSummaryUpdater.update(realm, roomId, membership, roomSync.summary, null)
return roomEntity return roomEntity
} }

View File

@@ -16,6 +16,7 @@
package org.matrix.android.sdk.internal.session.sync package org.matrix.android.sdk.internal.session.sync
import org.matrix.android.sdk.api.util.Extended
import org.matrix.android.sdk.internal.network.NetworkConstants import org.matrix.android.sdk.internal.network.NetworkConstants
import org.matrix.android.sdk.internal.network.TimeOutInterceptor import org.matrix.android.sdk.internal.network.TimeOutInterceptor
import org.matrix.android.sdk.internal.session.sync.model.SyncResponse import org.matrix.android.sdk.internal.session.sync.model.SyncResponse
@@ -33,5 +34,5 @@ internal interface SyncAPI {
@Header(TimeOutInterceptor.CONNECT_TIMEOUT) connectTimeOut: Long = TimeOutInterceptor.DEFAULT_LONG_TIMEOUT, @Header(TimeOutInterceptor.CONNECT_TIMEOUT) connectTimeOut: Long = TimeOutInterceptor.DEFAULT_LONG_TIMEOUT,
@Header(TimeOutInterceptor.READ_TIMEOUT) readTimeOut: Long = TimeOutInterceptor.DEFAULT_LONG_TIMEOUT, @Header(TimeOutInterceptor.READ_TIMEOUT) readTimeOut: Long = TimeOutInterceptor.DEFAULT_LONG_TIMEOUT,
@Header(TimeOutInterceptor.WRITE_TIMEOUT) writeTimeOut: Long = TimeOutInterceptor.DEFAULT_LONG_TIMEOUT @Header(TimeOutInterceptor.WRITE_TIMEOUT) writeTimeOut: Long = TimeOutInterceptor.DEFAULT_LONG_TIMEOUT
): Call<SyncResponse> ): Call<Extended<SyncResponse>>
} }

View File

@@ -17,6 +17,7 @@
package org.matrix.android.sdk.internal.session.sync package org.matrix.android.sdk.internal.session.sync
import org.matrix.android.sdk.R import org.matrix.android.sdk.R
import org.matrix.android.sdk.api.util.Extended
import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
import org.matrix.android.sdk.internal.network.TimeOutInterceptor import org.matrix.android.sdk.internal.network.TimeOutInterceptor
@@ -81,13 +82,14 @@ internal class DefaultSyncTask @Inject constructor(
val readTimeOut = (params.timeout + TIMEOUT_MARGIN).coerceAtLeast(TimeOutInterceptor.DEFAULT_LONG_TIMEOUT) val readTimeOut = (params.timeout + TIMEOUT_MARGIN).coerceAtLeast(TimeOutInterceptor.DEFAULT_LONG_TIMEOUT)
val syncResponse = executeRequest<SyncResponse>(globalErrorReceiver) { val syncResponse = executeRequest<Extended<SyncResponse>>(globalErrorReceiver) {
apiCall = syncAPI.sync( apiCall = syncAPI.sync(
params = requestParams, params = requestParams,
readTimeOut = readTimeOut readTimeOut = readTimeOut
) )
} }
syncResponseHandler.handleResponse(syncResponse, token) Timber.v("Sync Response undefined: ${syncResponse.undefined}")
syncResponseHandler.handleResponse(syncResponse.wrapped, token)
if (isInitialSync) { if (isInitialSync) {
initialSyncProgressService.endAll() initialSyncProgressService.endAll()
} }

View File

@@ -41,11 +41,6 @@ internal data class RoomSync(
*/ */
@Json(name = "account_data") val accountData: RoomSyncAccountData? = null, @Json(name = "account_data") val accountData: RoomSyncAccountData? = null,
/**
* The notification counts for the room.
*/
@Json(name = "unread_notifications") val unreadNotifications: RoomSyncUnreadNotifications? = null,
/** /**
* The room summary * The room summary
*/ */

View File

@@ -17,6 +17,7 @@ package org.matrix.android.sdk.internal.session.sync.model
import com.squareup.moshi.Json import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.util.Extended
// RoomsSyncResponse represents the rooms list in server sync v2 response. // RoomsSyncResponse represents the rooms list in server sync v2 response.
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
@@ -24,7 +25,7 @@ internal data class RoomsSyncResponse(
/** /**
* Joined rooms: keys are rooms ids. * Joined rooms: keys are rooms ids.
*/ */
@Json(name = "join") val join: Map<String, RoomSync> = emptyMap(), @Json(name = "join") val join: Map<String, Extended<RoomSync>> = emptyMap(),
/** /**
* Invitations. The rooms that the user has been invited to: keys are rooms ids. * Invitations. The rooms that the user has been invited to: keys are rooms ids.

1
moshi/codegen/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2021 New Vector Ltd
*
* 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.
*/
apply plugin: 'java-library'
apply plugin: 'kotlin'
dependencies {
def kotlin_poet_version = "1.6.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation("com.squareup.moshi:moshi:1.11.0")
implementation("com.squareup:kotlinpoet:$kotlin_poet_version")
implementation("com.squareup:kotlinpoet-metadata-specs:$kotlin_poet_version")
implementation("com.squareup:kotlinpoet-classinspector-elements:$kotlin_poet_version")
}
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
repositories {
mavenCentral()
}
compileKotlin {
kotlinOptions {
jvmTarget = "1.8"
}
}
compileTestKotlin {
kotlinOptions {
jvmTarget = "1.8"
}
}

View File

@@ -0,0 +1,153 @@
/*
* Copyright (c) 2021 New Vector Ltd
*
* 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.moshi.codegen
import com.squareup.kotlinpoet.AnnotationSpec
import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.CodeBlock
import com.squareup.kotlinpoet.FileSpec
import com.squareup.kotlinpoet.KModifier
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
import com.squareup.kotlinpoet.PropertySpec
import com.squareup.kotlinpoet.TypeSpec
import com.squareup.kotlinpoet.TypeVariableName
import com.squareup.kotlinpoet.asClassName
import com.squareup.kotlinpoet.asTypeName
import com.squareup.kotlinpoet.classinspector.elements.ElementsClassInspector
import com.squareup.kotlinpoet.joinToCode
import com.squareup.kotlinpoet.metadata.KotlinPoetMetadataPreview
import com.squareup.kotlinpoet.metadata.isData
import com.squareup.kotlinpoet.metadata.isInner
import com.squareup.kotlinpoet.metadata.specs.ClassInspector
import com.squareup.kotlinpoet.metadata.specs.toTypeSpec
import com.squareup.kotlinpoet.metadata.toImmutableKmClass
import com.squareup.kotlinpoet.tag
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import java.io.IOException
import javax.annotation.processing.AbstractProcessor
import javax.annotation.processing.Filer
import javax.annotation.processing.Messager
import javax.annotation.processing.ProcessingEnvironment
import javax.annotation.processing.RoundEnvironment
import javax.lang.model.SourceVersion
import javax.lang.model.element.AnnotationMirror
import javax.lang.model.element.TypeElement
import javax.lang.model.util.Elements
import javax.lang.model.util.Types
import javax.tools.Diagnostic
@KotlinPoetMetadataPreview class JsonClassProcessor : AbstractProcessor() {
private val annotation = JsonClass::class.java
private lateinit var filer: Filer
private lateinit var messager: Messager
private lateinit var elements: Elements
private lateinit var types: Types
private lateinit var options: Map<String, String>
private lateinit var classInspector: ClassInspector
override fun init(processingEnv: ProcessingEnvironment) {
super.init(processingEnv)
filer = processingEnv.filer
messager = processingEnv.messager
elements = processingEnv.elementUtils
types = processingEnv.typeUtils
options = processingEnv.options
classInspector = ElementsClassInspector.create(elements, types)
}
override fun getSupportedAnnotationTypes(): Set<String> = setOf(annotation.canonicalName)
override fun getSupportedSourceVersion(): SourceVersion = SourceVersion.latest()
@KotlinPoetMetadataPreview
override fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean {
if (roundEnv.errorRaised()) {
return false
}
val jsonKeysByClass = HashMap<ClassName, Set<String>>()
roundEnv.getElementsAnnotatedWith(annotation)
.asSequence()
.map { it as TypeElement }
.forEach { type ->
val jsonClass = type.getAnnotation(JsonClass::class.java)
if (!jsonClass.generateAdapter) return@forEach
val kmClass = type.toImmutableKmClass()
if (!kmClass.isData) {
return@forEach
}
if (kmClass.isInner) {
return@forEach
}
val dataClassSpec = kmClass.toTypeSpec(classInspector)
val jsonKeys = dataClassSpec.primaryConstructor?.parameters?.map {
it.annotations.jsonName() ?: it.name
}.orEmpty().toSet()
val typeName: String = type.qualifiedName.toString()
val className = ClassName("", typeName)
jsonKeysByClass[className] = jsonKeys
}
val packageName = "org.matrix.android.sdk.internal"
val generatedClassName = ClassName(packageName, "JsonKeys")
val objectBuilder = TypeSpec.objectBuilder(generatedClassName).addModifiers(KModifier.INTERNAL)
val setTypeName = Set::class.asClassName().parameterizedBy(String::class.asTypeName())
val anyClassName = Class::class.asClassName().parameterizedBy(TypeVariableName("*"))
val mapTypeName = Map::class.asClassName().parameterizedBy(anyClassName, setTypeName)
val jsonKeysPropertySpec = PropertySpec.builder("jsonKeysByClasses", mapTypeName)
.addModifiers(KModifier.PUBLIC)
.initializer(
"mapOf(\n%L\n)",
jsonKeysByClass
.map {
val setOfBlock = it.value.map { jsonKey ->
CodeBlock.of("%S", jsonKey)
}.joinToCode(", ")
CodeBlock.of("%L::class.java to setOf(%L)", it.key, setOfBlock)
}.joinToCode(", \n")
)
.build()
objectBuilder.addProperty(jsonKeysPropertySpec)
try {
val fileSpec = FileSpec.builder(packageName, "JsonKeys")
.addType(objectBuilder.build())
.build()
fileSpec.writeTo(filer)
} catch (e: IOException) {
messager.printMessage(Diagnostic.Kind.NOTE, e.toString())
}
return true
}
private fun List<AnnotationSpec>?.jsonName(): String? {
if (this == null) return null
return find { it.typeName == Json::class.asClassName() }?.let { annotation ->
val mirror = requireNotNull(annotation.tag<AnnotationMirror>()) {
"Could not get the annotation mirror from the annotation spec"
}
mirror.elementValues.entries.single {
it.key.simpleName.contentEquals("name")
}.value.value as String
}
}
}

View File

@@ -0,0 +1 @@
org.matrix.moshi.codegen.JsonClassProcessor

View File

@@ -1,3 +1,4 @@
include ':moshi:codegen'
include ':vector' include ':vector'
include ':matrix-sdk-android' include ':matrix-sdk-android'
include ':matrix-sdk-android-rx' include ':matrix-sdk-android-rx'