mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-22 09:25:49 +03:00
Refactor Account Data
Auto stash before rebase of "develop"
This commit is contained in:
parent
a250a895fe
commit
bf06b57bad
27 changed files with 690 additions and 20 deletions
|
@ -31,6 +31,7 @@ import im.vector.matrix.android.api.util.JsonDict
|
||||||
import im.vector.matrix.android.api.util.Optional
|
import im.vector.matrix.android.api.util.Optional
|
||||||
import im.vector.matrix.android.api.util.toOptional
|
import im.vector.matrix.android.api.util.toOptional
|
||||||
import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
|
import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
|
||||||
|
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountData
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
@ -121,6 +122,13 @@ class RxSession(private val session: Session) {
|
||||||
session.getCrossSigningService().getUserCrossSigningKeys(userId).toOptional()
|
session.getCrossSigningService().getUserCrossSigningKeys(userId).toOptional()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun liveAccountData(filter: List<String>): Observable<List<UserAccountData>> {
|
||||||
|
return session.getLiveAccountData(filter).asObservable()
|
||||||
|
.startWithCallable {
|
||||||
|
session.getAccountData(filter)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Session.rx(): RxSession {
|
fun Session.rx(): RxSession {
|
||||||
|
|
|
@ -21,6 +21,7 @@ import androidx.lifecycle.LiveData
|
||||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
import im.vector.matrix.android.api.auth.data.SessionParams
|
||||||
import im.vector.matrix.android.api.failure.GlobalError
|
import im.vector.matrix.android.api.failure.GlobalError
|
||||||
import im.vector.matrix.android.api.pushrules.PushRuleService
|
import im.vector.matrix.android.api.pushrules.PushRuleService
|
||||||
|
import im.vector.matrix.android.api.session.accountdata.AccountDataService
|
||||||
import im.vector.matrix.android.api.session.cache.CacheService
|
import im.vector.matrix.android.api.session.cache.CacheService
|
||||||
import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
|
import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
|
||||||
import im.vector.matrix.android.api.session.content.ContentUrlResolver
|
import im.vector.matrix.android.api.session.content.ContentUrlResolver
|
||||||
|
@ -57,7 +58,8 @@ interface Session :
|
||||||
PushersService,
|
PushersService,
|
||||||
InitialSyncProgressService,
|
InitialSyncProgressService,
|
||||||
HomeServerCapabilitiesService,
|
HomeServerCapabilitiesService,
|
||||||
SecureStorageService {
|
SecureStorageService,
|
||||||
|
AccountDataService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The params associated to the session
|
* The params associated to the session
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 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 im.vector.matrix.android.api.session.accountdata
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
|
import im.vector.matrix.android.api.util.Optional
|
||||||
|
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountData
|
||||||
|
|
||||||
|
interface AccountDataService {
|
||||||
|
|
||||||
|
fun getAccountData(type: String): UserAccountData?
|
||||||
|
|
||||||
|
fun getLiveAccountData(type: String): LiveData<Optional<UserAccountData>>
|
||||||
|
|
||||||
|
fun getAccountData(filterType: List<String>): List<UserAccountData>
|
||||||
|
|
||||||
|
fun getLiveAccountData(filterType: List<String>): LiveData<List<UserAccountData>>
|
||||||
|
|
||||||
|
fun updateAccountData(type: String, data: Any, callback: MatrixCallback<Unit>? = null)
|
||||||
|
}
|
|
@ -66,6 +66,9 @@ object EventType {
|
||||||
const val ROOM_KEY_REQUEST = "m.room_key_request"
|
const val ROOM_KEY_REQUEST = "m.room_key_request"
|
||||||
const val FORWARDED_ROOM_KEY = "m.forwarded_room_key"
|
const val FORWARDED_ROOM_KEY = "m.forwarded_room_key"
|
||||||
|
|
||||||
|
const val REQUEST_SECRET = "m.secret.request"
|
||||||
|
const val SEND_SECRET = "m.secret.send"
|
||||||
|
|
||||||
// Interactive key verification
|
// Interactive key verification
|
||||||
const val KEY_VERIFICATION_START = "m.key.verification.start"
|
const val KEY_VERIFICATION_START = "m.key.verification.start"
|
||||||
const val KEY_VERIFICATION_ACCEPT = "m.key.verification.accept"
|
const val KEY_VERIFICATION_ACCEPT = "m.key.verification.accept"
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 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 im.vector.matrix.android.api.session.securestorage
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some features may require clients to store encrypted data on the server so that it can be shared securely between clients.
|
||||||
|
* Clients may also wish to securely send such data directly to each other.
|
||||||
|
* For example, key backups (MSC1219) can store the decryption key for the backups on the server, or cross-signing (MSC1756) can store the signing keys.
|
||||||
|
*
|
||||||
|
* https://github.com/matrix-org/matrix-doc/pull/1946
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface SharedSecretStorageService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a key for encrypting secrets.
|
||||||
|
*
|
||||||
|
* @param algorithm the algorithm used by the key.
|
||||||
|
* @param opts the options for the algorithm. The properties used
|
||||||
|
* depend on the algorithm given.
|
||||||
|
* @param keyId the ID of the key
|
||||||
|
*
|
||||||
|
* @return {string} the ID of the key
|
||||||
|
*/
|
||||||
|
fun addKey(algorithm: String, opts: Map<String, Any>, keyId: String, callback: MatrixCallback<String>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether we have a key with a given ID.
|
||||||
|
*
|
||||||
|
* @param keyId The ID of the key to check
|
||||||
|
* @return Whether we have the key.
|
||||||
|
*/
|
||||||
|
fun hasKey(keyId: String): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store an encrypted secret on the server
|
||||||
|
*
|
||||||
|
* @param name The name of the secret
|
||||||
|
* @param secret The secret contents.
|
||||||
|
* @param keys The IDs of the keys to use to encrypt the secret or null to use the default key.
|
||||||
|
*/
|
||||||
|
fun storeSecret(name: String, secretBase64: String, keys: List<String>?, callback: MatrixCallback<Unit>)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an encrypted secret from the shared storage
|
||||||
|
*
|
||||||
|
* @param name The name of the secret
|
||||||
|
* @param keyId The id of the key that should be used to decrypt
|
||||||
|
* @param privateKey the passphrase/secret
|
||||||
|
*
|
||||||
|
* @return The decrypted value
|
||||||
|
*/
|
||||||
|
fun getSecret(name: String, keyId: String, privateKey: String) : String
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 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 im.vector.matrix.android.internal.crypto.secrets
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
|
import im.vector.matrix.android.api.session.securestorage.SharedSecretStorageService
|
||||||
|
|
||||||
|
internal class DefaultSharedSecureStorage : SharedSecretStorageService {
|
||||||
|
|
||||||
|
override fun addKey(algorithm: String, opts: Map<String, Any>, keyId: String, callback: MatrixCallback<String>) {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hasKey(keyId: String): Boolean {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun storeSecret(name: String, secretBase64: String, keys: List<String>?, callback: MatrixCallback<Unit>) {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSecret(name: String, keyId: String, privateKey: String): String {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
}
|
|
@ -53,6 +53,7 @@ import io.realm.annotations.RealmModule
|
||||||
DraftEntity::class,
|
DraftEntity::class,
|
||||||
HomeServerCapabilitiesEntity::class,
|
HomeServerCapabilitiesEntity::class,
|
||||||
RoomMemberSummaryEntity::class,
|
RoomMemberSummaryEntity::class,
|
||||||
CurrentStateEventEntity::class
|
CurrentStateEventEntity::class,
|
||||||
|
UserAccountDataEntity::class
|
||||||
])
|
])
|
||||||
internal class SessionRealmModule
|
internal class SessionRealmModule
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 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 im.vector.matrix.android.internal.database.model
|
||||||
|
|
||||||
|
import io.realm.RealmObject
|
||||||
|
import io.realm.annotations.Index
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clients can store custom config data for their account on their homeserver.
|
||||||
|
* This account data will be synced between different devices and can persist across installations on a particular device.
|
||||||
|
* Users may only view the account data for their own accountThe account_data may be either global or scoped to a particular rooms.
|
||||||
|
*/
|
||||||
|
internal open class UserAccountDataEntity(
|
||||||
|
@Index var type: String? = null,
|
||||||
|
var contentStr: String? = null
|
||||||
|
) : RealmObject() {
|
||||||
|
|
||||||
|
companion object
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 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 im.vector.matrix.android.internal.network.parsing
|
||||||
|
|
||||||
|
import com.squareup.moshi.JsonAdapter
|
||||||
|
import com.squareup.moshi.Moshi
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
|
||||||
|
class AccountDataJsonAdapterFactory<UserAccountData> : JsonAdapter.Factory {
|
||||||
|
|
||||||
|
|
||||||
|
override fun create(type: Type, annotations: MutableSet<out Annotation>, moshi: Moshi): JsonAdapter<*>? {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ import im.vector.matrix.android.api.failure.GlobalError
|
||||||
import im.vector.matrix.android.api.pushrules.PushRuleService
|
import im.vector.matrix.android.api.pushrules.PushRuleService
|
||||||
import im.vector.matrix.android.api.session.InitialSyncProgressService
|
import im.vector.matrix.android.api.session.InitialSyncProgressService
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
|
import im.vector.matrix.android.api.session.accountdata.AccountDataService
|
||||||
import im.vector.matrix.android.api.session.cache.CacheService
|
import im.vector.matrix.android.api.session.cache.CacheService
|
||||||
import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
|
import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
|
||||||
import im.vector.matrix.android.api.session.content.ContentUrlResolver
|
import im.vector.matrix.android.api.session.content.ContentUrlResolver
|
||||||
|
@ -91,6 +92,7 @@ internal class DefaultSession @Inject constructor(
|
||||||
private val contentUploadProgressTracker: ContentUploadStateTracker,
|
private val contentUploadProgressTracker: ContentUploadStateTracker,
|
||||||
private val initialSyncProgressService: Lazy<InitialSyncProgressService>,
|
private val initialSyncProgressService: Lazy<InitialSyncProgressService>,
|
||||||
private val homeServerCapabilitiesService: Lazy<HomeServerCapabilitiesService>,
|
private val homeServerCapabilitiesService: Lazy<HomeServerCapabilitiesService>,
|
||||||
|
private val accountDataService: Lazy<AccountDataService>,
|
||||||
private val shieldTrustUpdater: ShieldTrustUpdater)
|
private val shieldTrustUpdater: ShieldTrustUpdater)
|
||||||
: Session,
|
: Session,
|
||||||
RoomService by roomService.get(),
|
RoomService by roomService.get(),
|
||||||
|
@ -106,7 +108,8 @@ internal class DefaultSession @Inject constructor(
|
||||||
InitialSyncProgressService by initialSyncProgressService.get(),
|
InitialSyncProgressService by initialSyncProgressService.get(),
|
||||||
SecureStorageService by secureStorageService.get(),
|
SecureStorageService by secureStorageService.get(),
|
||||||
HomeServerCapabilitiesService by homeServerCapabilitiesService.get(),
|
HomeServerCapabilitiesService by homeServerCapabilitiesService.get(),
|
||||||
ProfileService by profileService.get() {
|
ProfileService by profileService.get(),
|
||||||
|
AccountDataService by accountDataService.get() {
|
||||||
|
|
||||||
private var isOpen = false
|
private var isOpen = false
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ import im.vector.matrix.android.api.auth.data.sessionId
|
||||||
import im.vector.matrix.android.api.crypto.MXCryptoConfig
|
import im.vector.matrix.android.api.crypto.MXCryptoConfig
|
||||||
import im.vector.matrix.android.api.session.InitialSyncProgressService
|
import im.vector.matrix.android.api.session.InitialSyncProgressService
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
|
import im.vector.matrix.android.api.session.accountdata.AccountDataService
|
||||||
import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilitiesService
|
import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilitiesService
|
||||||
import im.vector.matrix.android.api.session.securestorage.SecureStorageService
|
import im.vector.matrix.android.api.session.securestorage.SecureStorageService
|
||||||
import im.vector.matrix.android.internal.crypto.verification.VerificationMessageLiveObserver
|
import im.vector.matrix.android.internal.crypto.verification.VerificationMessageLiveObserver
|
||||||
|
@ -61,6 +62,7 @@ import im.vector.matrix.android.internal.session.room.create.RoomCreateEventLive
|
||||||
import im.vector.matrix.android.internal.session.room.prune.EventsPruner
|
import im.vector.matrix.android.internal.session.room.prune.EventsPruner
|
||||||
import im.vector.matrix.android.internal.session.room.tombstone.RoomTombstoneEventLiveObserver
|
import im.vector.matrix.android.internal.session.room.tombstone.RoomTombstoneEventLiveObserver
|
||||||
import im.vector.matrix.android.internal.session.securestorage.DefaultSecureStorageService
|
import im.vector.matrix.android.internal.session.securestorage.DefaultSecureStorageService
|
||||||
|
import im.vector.matrix.android.internal.session.user.accountdata.DefaultAccountDataService
|
||||||
import im.vector.matrix.android.internal.util.md5
|
import im.vector.matrix.android.internal.util.md5
|
||||||
import io.realm.RealmConfiguration
|
import io.realm.RealmConfiguration
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
@ -263,4 +265,7 @@ internal abstract class SessionModule {
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindHomeServerCapabilitiesService(homeServerCapabilitiesService: DefaultHomeServerCapabilitiesService): HomeServerCapabilitiesService
|
abstract fun bindHomeServerCapabilitiesService(homeServerCapabilitiesService: DefaultHomeServerCapabilitiesService): HomeServerCapabilitiesService
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindAccountDataServiceService(accountDataService: DefaultAccountDataService): AccountDataService
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,12 @@ package im.vector.matrix.android.internal.session.sync
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.api.pushrules.RuleScope
|
import im.vector.matrix.android.api.pushrules.RuleScope
|
||||||
import im.vector.matrix.android.api.pushrules.RuleSetKey
|
import im.vector.matrix.android.api.pushrules.RuleSetKey
|
||||||
|
import im.vector.matrix.android.api.session.events.model.Content
|
||||||
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomMemberContent
|
import im.vector.matrix.android.api.session.room.model.RoomMemberContent
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||||
|
import im.vector.matrix.android.internal.database.mapper.ContentMapper
|
||||||
import im.vector.matrix.android.internal.database.mapper.PushRulesMapper
|
import im.vector.matrix.android.internal.database.mapper.PushRulesMapper
|
||||||
import im.vector.matrix.android.internal.database.mapper.asDomain
|
import im.vector.matrix.android.internal.database.mapper.asDomain
|
||||||
import im.vector.matrix.android.internal.database.model.BreadcrumbsEntity
|
import im.vector.matrix.android.internal.database.model.BreadcrumbsEntity
|
||||||
|
@ -29,15 +32,18 @@ import im.vector.matrix.android.internal.database.model.IgnoredUserEntity
|
||||||
import im.vector.matrix.android.internal.database.model.PushRulesEntity
|
import im.vector.matrix.android.internal.database.model.PushRulesEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields
|
import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields
|
||||||
|
import im.vector.matrix.android.internal.database.model.UserAccountDataEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.UserAccountDataEntityFields
|
||||||
import im.vector.matrix.android.internal.database.query.getDirectRooms
|
import im.vector.matrix.android.internal.database.query.getDirectRooms
|
||||||
import im.vector.matrix.android.internal.database.query.getOrCreate
|
import im.vector.matrix.android.internal.database.query.getOrCreate
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
|
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||||
import im.vector.matrix.android.internal.di.UserId
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
|
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
|
||||||
import im.vector.matrix.android.internal.session.sync.model.InvitedRoomSync
|
import im.vector.matrix.android.internal.session.sync.model.InvitedRoomSync
|
||||||
|
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountData
|
||||||
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataBreadcrumbs
|
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataBreadcrumbs
|
||||||
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataDirectMessages
|
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataDirectMessages
|
||||||
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataFallback
|
|
||||||
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataIgnoredUsers
|
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataIgnoredUsers
|
||||||
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataPushRules
|
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataPushRules
|
||||||
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataSync
|
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataSync
|
||||||
|
@ -45,6 +51,7 @@ import im.vector.matrix.android.internal.session.user.accountdata.DirectChatsHel
|
||||||
import im.vector.matrix.android.internal.session.user.accountdata.UpdateUserAccountDataTask
|
import im.vector.matrix.android.internal.session.user.accountdata.UpdateUserAccountDataTask
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import io.realm.RealmList
|
import io.realm.RealmList
|
||||||
|
import io.realm.kotlin.where
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -56,21 +63,23 @@ internal class UserAccountDataSyncHandler @Inject constructor(
|
||||||
|
|
||||||
fun handle(realm: Realm, accountData: UserAccountDataSync?) {
|
fun handle(realm: Realm, accountData: UserAccountDataSync?) {
|
||||||
accountData?.list?.forEach {
|
accountData?.list?.forEach {
|
||||||
when (it) {
|
// Generic handling, just save in base
|
||||||
is UserAccountDataDirectMessages -> handleDirectChatRooms(realm, it)
|
handleGenericAccountData(realm, it.type, it.content)
|
||||||
is UserAccountDataPushRules -> handlePushRules(realm, it)
|
|
||||||
is UserAccountDataIgnoredUsers -> handleIgnoredUsers(realm, it)
|
|
||||||
is UserAccountDataBreadcrumbs -> handleBreadcrumbs(realm, it)
|
|
||||||
is UserAccountDataFallback -> Timber.d("Receive account data of unhandled type ${it.type}")
|
|
||||||
else -> error("Missing code here!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO Store all account data, app can be interested of it
|
// Didn't want to break too much thing, so i re-serialize to jsonString before reparsing
|
||||||
// accountData?.list?.forEach {
|
// TODO would be better to have a mapper?
|
||||||
// it.toString()
|
val toJson = MoshiProvider.providesMoshi().adapter(Event::class.java).toJson(it)
|
||||||
// MoshiProvider.providesMoshi()
|
val model = toJson?.let { json ->
|
||||||
// }
|
MoshiProvider.providesMoshi().adapter(UserAccountData::class.java).fromJson(json)
|
||||||
|
}
|
||||||
|
// Specific parsing
|
||||||
|
when (model) {
|
||||||
|
is UserAccountDataDirectMessages -> handleDirectChatRooms(realm, model)
|
||||||
|
is UserAccountDataPushRules -> handlePushRules(realm, model)
|
||||||
|
is UserAccountDataIgnoredUsers -> handleIgnoredUsers(realm, model)
|
||||||
|
is UserAccountDataBreadcrumbs -> handleBreadcrumbs(realm, model)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we get some direct chat invites, we synchronize the user account data including those.
|
// If we get some direct chat invites, we synchronize the user account data including those.
|
||||||
|
@ -200,4 +209,18 @@ internal class UserAccountDataSyncHandler @Inject constructor(
|
||||||
?.breadcrumbsIndex = index
|
?.breadcrumbsIndex = index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleGenericAccountData(realm: Realm, type: String, content: Content?) {
|
||||||
|
val existing = realm.where<UserAccountDataEntity>().equalTo(UserAccountDataEntityFields.TYPE, type)
|
||||||
|
.findFirst()
|
||||||
|
if (existing != null) {
|
||||||
|
// Update current value
|
||||||
|
existing.contentStr = ContentMapper.map(content)
|
||||||
|
} else {
|
||||||
|
realm.createObject(UserAccountDataEntity::class.java).let { accountDataEntity ->
|
||||||
|
accountDataEntity.type = type
|
||||||
|
accountDataEntity.contentStr = ContentMapper.map(content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ package im.vector.matrix.android.internal.session.sync.model.accountdata
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
|
|
||||||
internal abstract class UserAccountData {
|
abstract class UserAccountData {
|
||||||
|
|
||||||
@Json(name = "type") abstract val type: String
|
@Json(name = "type") abstract val type: String
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
internal data class UserAccountDataFallback(
|
data class UserAccountDataFallback(
|
||||||
@Json(name = "type") override val type: String,
|
@Json(name = "type") override val type: String,
|
||||||
@Json(name = "content") val content: Map<String, Any>
|
@Json(name = "content") val content: Map<String, Any>
|
||||||
) : UserAccountData()
|
) : UserAccountData()
|
||||||
|
|
|
@ -18,8 +18,9 @@ package im.vector.matrix.android.internal.session.sync.model.accountdata
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
internal data class UserAccountDataSync(
|
internal data class UserAccountDataSync(
|
||||||
@Json(name = "events") val list: List<UserAccountData> = emptyList()
|
@Json(name = "events") val list: List<Event> = emptyList()
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 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 im.vector.matrix.android.internal.session.user.accountdata
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.Transformations
|
||||||
|
import com.zhuinden.monarchy.Monarchy
|
||||||
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
|
import im.vector.matrix.android.api.session.accountdata.AccountDataService
|
||||||
|
import im.vector.matrix.android.api.util.JSON_DICT_PARAMETERIZED_TYPE
|
||||||
|
import im.vector.matrix.android.api.util.Optional
|
||||||
|
import im.vector.matrix.android.api.util.toOptional
|
||||||
|
import im.vector.matrix.android.internal.database.model.UserAccountDataEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.UserAccountDataEntityFields
|
||||||
|
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||||
|
import im.vector.matrix.android.internal.di.SessionId
|
||||||
|
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountData
|
||||||
|
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataFallback
|
||||||
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
|
import im.vector.matrix.android.internal.task.configureWith
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal class DefaultAccountDataService @Inject constructor(
|
||||||
|
private val monarchy: Monarchy,
|
||||||
|
@SessionId private val sessionId: String,
|
||||||
|
private val updateUserAccountDataTask: UpdateUserAccountDataTask,
|
||||||
|
private val taskExecutor: TaskExecutor
|
||||||
|
) : AccountDataService {
|
||||||
|
|
||||||
|
private val moshi = MoshiProvider.providesMoshi()
|
||||||
|
private val adapter = moshi.adapter<Map<String, Any>>(JSON_DICT_PARAMETERIZED_TYPE)
|
||||||
|
|
||||||
|
override fun getAccountData(type: String): UserAccountData? {
|
||||||
|
return getAccountData(listOf(type)).firstOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getLiveAccountData(type: String): LiveData<Optional<UserAccountData>> {
|
||||||
|
return Transformations.map(getLiveAccountData(listOf(type))) {
|
||||||
|
it.firstOrNull()?.toOptional()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getAccountData(filterType: List<String>): List<UserAccountData> {
|
||||||
|
return monarchy.fetchAllCopiedSync { realm ->
|
||||||
|
realm.where(UserAccountDataEntity::class.java)
|
||||||
|
.apply {
|
||||||
|
if (filterType.isNotEmpty()) {
|
||||||
|
`in`(UserAccountDataEntityFields.TYPE, filterType.toTypedArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}?.mapNotNull { entity ->
|
||||||
|
entity.type?.let { type ->
|
||||||
|
UserAccountDataFallback(
|
||||||
|
type = type,
|
||||||
|
content = entity.contentStr?.let { adapter.fromJson(it) } ?: emptyMap()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getLiveAccountData(filterType: List<String>): LiveData<List<UserAccountData>> {
|
||||||
|
return monarchy.findAllMappedWithChanges({ realm ->
|
||||||
|
realm.where(UserAccountDataEntity::class.java)
|
||||||
|
.apply {
|
||||||
|
if (filterType.isNotEmpty()) {
|
||||||
|
`in`(UserAccountDataEntityFields.TYPE, filterType.toTypedArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, { entity ->
|
||||||
|
UserAccountDataFallback(
|
||||||
|
type = entity.type ?: "",
|
||||||
|
content = entity.contentStr?.let { adapter.fromJson(it) } ?: emptyMap()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateAccountData(type: String, data: Any, callback: MatrixCallback<Unit>?) {
|
||||||
|
updateUserAccountDataTask.configureWith(UpdateUserAccountDataTask.AnyParams(
|
||||||
|
type = type,
|
||||||
|
any = data
|
||||||
|
)) {
|
||||||
|
this.retryCount = 5
|
||||||
|
callback?.let { this.callback = it }
|
||||||
|
}
|
||||||
|
.executeBy(taskExecutor)
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,6 +49,14 @@ internal interface UpdateUserAccountDataTask : Task<UpdateUserAccountDataTask.Pa
|
||||||
return breadcrumbsContent
|
return breadcrumbsContent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class AnyParams(override val type: String,
|
||||||
|
private val any: Any
|
||||||
|
) : Params {
|
||||||
|
override fun getData(): Any {
|
||||||
|
return any
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class DefaultUpdateUserAccountDataTask @Inject constructor(
|
internal class DefaultUpdateUserAccountDataTask @Inject constructor(
|
||||||
|
|
|
@ -354,6 +354,9 @@ dependencies {
|
||||||
compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.5.0'
|
compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.5.0'
|
||||||
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.5.0'
|
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.5.0'
|
||||||
|
|
||||||
|
// Json viewer
|
||||||
|
implementation "com.yuyh.json:jsonviewer:1.0.6"
|
||||||
|
|
||||||
// gplay flavor only
|
// gplay flavor only
|
||||||
// Warning: due to the exclude, Android Studio does not propose to upgrade. Uncomment next line to be proposed to upgrade
|
// Warning: due to the exclude, Android Studio does not propose to upgrade. Uncomment next line to be proposed to upgrade
|
||||||
// implementation 'com.google.firebase:firebase-messaging:20.0.0'
|
// implementation 'com.google.firebase:firebase-messaging:20.0.0'
|
||||||
|
|
|
@ -374,6 +374,11 @@ SOFTWARE.
|
||||||
<br/>
|
<br/>
|
||||||
Copyright (c) 2014 Dushyanth Maguluru
|
Copyright (c) 2014 Dushyanth Maguluru
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<b>JsonViewer</b>
|
||||||
|
<br/>
|
||||||
|
Copyright 2017 smuyyh, All right reserved.
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<pre>
|
<pre>
|
||||||
Apache License
|
Apache License
|
||||||
|
|
|
@ -72,6 +72,7 @@ import im.vector.riotx.features.settings.VectorSettingsPreferencesFragment
|
||||||
import im.vector.riotx.features.settings.VectorSettingsSecurityPrivacyFragment
|
import im.vector.riotx.features.settings.VectorSettingsSecurityPrivacyFragment
|
||||||
import im.vector.riotx.features.settings.crosssigning.CrossSigningSettingsFragment
|
import im.vector.riotx.features.settings.crosssigning.CrossSigningSettingsFragment
|
||||||
import im.vector.riotx.features.settings.devices.VectorSettingsDevicesFragment
|
import im.vector.riotx.features.settings.devices.VectorSettingsDevicesFragment
|
||||||
|
import im.vector.riotx.features.settings.devtools.AccountDataFragment
|
||||||
import im.vector.riotx.features.settings.ignored.VectorSettingsIgnoredUsersFragment
|
import im.vector.riotx.features.settings.ignored.VectorSettingsIgnoredUsersFragment
|
||||||
import im.vector.riotx.features.settings.push.PushGatewaysFragment
|
import im.vector.riotx.features.settings.push.PushGatewaysFragment
|
||||||
import im.vector.riotx.features.signout.soft.SoftLogoutFragment
|
import im.vector.riotx.features.signout.soft.SoftLogoutFragment
|
||||||
|
@ -348,4 +349,9 @@ interface FragmentModule {
|
||||||
@IntoMap
|
@IntoMap
|
||||||
@FragmentKey(CrossSigningSettingsFragment::class)
|
@FragmentKey(CrossSigningSettingsFragment::class)
|
||||||
fun bindCrossSigningSettingsFragment(fragment: CrossSigningSettingsFragment): Fragment
|
fun bindCrossSigningSettingsFragment(fragment: CrossSigningSettingsFragment): Fragment
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@FragmentKey(AccountDataFragment::class)
|
||||||
|
fun bindAccountDataFragment(fragment: AccountDataFragment): Fragment
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 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 im.vector.riotx.features.settings.devtools
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import com.airbnb.epoxy.TypedEpoxyController
|
||||||
|
import com.airbnb.mvrx.Fail
|
||||||
|
import com.airbnb.mvrx.Loading
|
||||||
|
import com.airbnb.mvrx.Success
|
||||||
|
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountData
|
||||||
|
import im.vector.riotx.R
|
||||||
|
import im.vector.riotx.core.epoxy.loadingItem
|
||||||
|
import im.vector.riotx.core.resources.StringProvider
|
||||||
|
import im.vector.riotx.core.ui.list.genericFooterItem
|
||||||
|
import im.vector.riotx.core.ui.list.genericItemWithValue
|
||||||
|
import im.vector.riotx.core.utils.DebouncedClickListener
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class AccountDataEpoxyController @Inject constructor(
|
||||||
|
private val stringProvider: StringProvider
|
||||||
|
) : TypedEpoxyController<AccountDataViewState>() {
|
||||||
|
|
||||||
|
interface InteractionListener {
|
||||||
|
fun didTap(data: UserAccountData)
|
||||||
|
}
|
||||||
|
|
||||||
|
var interactionListener: InteractionListener? = null
|
||||||
|
|
||||||
|
override fun buildModels(data: AccountDataViewState?) {
|
||||||
|
if (data == null) return
|
||||||
|
when (data.accountData) {
|
||||||
|
is Loading -> {
|
||||||
|
loadingItem {
|
||||||
|
id("loading")
|
||||||
|
loadingText(stringProvider.getString(R.string.loading))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is Fail -> {
|
||||||
|
genericFooterItem {
|
||||||
|
id("fail")
|
||||||
|
text(data.accountData.error.localizedMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is Success -> {
|
||||||
|
val dataList = data.accountData.invoke()
|
||||||
|
if (dataList.isEmpty()) {
|
||||||
|
genericFooterItem {
|
||||||
|
id("noResults")
|
||||||
|
text(stringProvider.getString(R.string.no_result_placeholder))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dataList.forEach { accountData ->
|
||||||
|
genericItemWithValue {
|
||||||
|
id(accountData.type)
|
||||||
|
title(accountData.type)
|
||||||
|
itemClickAction(DebouncedClickListener(View.OnClickListener {
|
||||||
|
interactionListener?.didTap(accountData)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 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 im.vector.riotx.features.settings.devtools
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import com.airbnb.mvrx.fragmentViewModel
|
||||||
|
import com.airbnb.mvrx.withState
|
||||||
|
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||||
|
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountData
|
||||||
|
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataFallback
|
||||||
|
import im.vector.riotx.R
|
||||||
|
import im.vector.riotx.core.extensions.configureWith
|
||||||
|
import im.vector.riotx.core.platform.VectorBaseActivity
|
||||||
|
import im.vector.riotx.core.platform.VectorBaseFragment
|
||||||
|
import kotlinx.android.synthetic.main.fragment_generic_recycler.*
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class AccountDataFragment @Inject constructor(
|
||||||
|
val viewModelFactory: AccountDataViewModel.Factory,
|
||||||
|
private val epoxyController: AccountDataEpoxyController
|
||||||
|
) : VectorBaseFragment(), AccountDataEpoxyController.InteractionListener {
|
||||||
|
|
||||||
|
override fun getLayoutResId() = R.layout.fragment_generic_recycler
|
||||||
|
|
||||||
|
private val viewModel: AccountDataViewModel by fragmentViewModel(AccountDataViewModel::class)
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
(activity as? VectorBaseActivity)?.supportActionBar?.setTitle(R.string.settings_account_data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun invalidate() = withState(viewModel) { state ->
|
||||||
|
epoxyController.setData(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
recyclerView.configureWith(epoxyController, showDivider = true)
|
||||||
|
epoxyController.interactionListener = this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun didTap(data: UserAccountData) {
|
||||||
|
val fb = data as? UserAccountDataFallback ?: return
|
||||||
|
val jsonString = MoshiProvider.providesMoshi()
|
||||||
|
.adapter(UserAccountDataFallback::class.java)
|
||||||
|
.toJson(fb)
|
||||||
|
JsonViewerBottomSheetDialog.newInstance(jsonString)
|
||||||
|
.show(childFragmentManager, "JSON_VIEWER")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 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 im.vector.riotx.features.settings.devtools
|
||||||
|
|
||||||
|
import com.airbnb.mvrx.Async
|
||||||
|
import com.airbnb.mvrx.FragmentViewModelContext
|
||||||
|
import com.airbnb.mvrx.MvRxState
|
||||||
|
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||||
|
import com.airbnb.mvrx.Uninitialized
|
||||||
|
import com.airbnb.mvrx.ViewModelContext
|
||||||
|
import com.squareup.inject.assisted.Assisted
|
||||||
|
import com.squareup.inject.assisted.AssistedInject
|
||||||
|
import im.vector.matrix.android.api.session.Session
|
||||||
|
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountData
|
||||||
|
import im.vector.matrix.rx.rx
|
||||||
|
import im.vector.riotx.core.platform.EmptyAction
|
||||||
|
import im.vector.riotx.core.platform.EmptyViewEvents
|
||||||
|
import im.vector.riotx.core.platform.VectorViewModel
|
||||||
|
|
||||||
|
data class AccountDataViewState(
|
||||||
|
val accountData: Async<List<UserAccountData>> = Uninitialized
|
||||||
|
) : MvRxState
|
||||||
|
|
||||||
|
class AccountDataViewModel @AssistedInject constructor(@Assisted initialState: AccountDataViewState,
|
||||||
|
private val session: Session)
|
||||||
|
: VectorViewModel<AccountDataViewState, EmptyAction, EmptyViewEvents>(initialState) {
|
||||||
|
|
||||||
|
|
||||||
|
init {
|
||||||
|
session.rx().liveAccountData(emptyList())
|
||||||
|
.execute {
|
||||||
|
copy(accountData = it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handle(action: EmptyAction) {}
|
||||||
|
|
||||||
|
@AssistedInject.Factory
|
||||||
|
interface Factory {
|
||||||
|
fun create(initialState: AccountDataViewState): AccountDataViewModel
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object : MvRxViewModelFactory<AccountDataViewModel, AccountDataViewState> {
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
override fun create(viewModelContext: ViewModelContext, state: AccountDataViewState): AccountDataViewModel? {
|
||||||
|
val fragment: AccountDataFragment = (viewModelContext as FragmentViewModelContext).fragment()
|
||||||
|
return fragment.viewModelFactory.create(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 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 im.vector.riotx.features.settings.devtools
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import butterknife.BindView
|
||||||
|
import com.airbnb.mvrx.MvRx
|
||||||
|
import com.yuyh.jsonviewer.library.JsonRecyclerView
|
||||||
|
import im.vector.riotx.R
|
||||||
|
import im.vector.riotx.core.platform.VectorBaseBottomSheetDialogFragment
|
||||||
|
import im.vector.riotx.features.themes.ThemeUtils
|
||||||
|
|
||||||
|
class JsonViewerBottomSheetDialog : VectorBaseBottomSheetDialogFragment() {
|
||||||
|
|
||||||
|
override fun getLayoutResId() = R.layout.fragment_jsonviewer
|
||||||
|
|
||||||
|
@BindView(R.id.rv_json)
|
||||||
|
lateinit var jsonRecyclerView: JsonRecyclerView
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
jsonRecyclerView.setKeyColor(ThemeUtils.getColor(requireContext(), R.attr.colorAccent))
|
||||||
|
jsonRecyclerView.setValueTextColor(ContextCompat.getColor(requireContext(), R.color.riotx_notice_secondary))
|
||||||
|
jsonRecyclerView.setValueNumberColor(ContextCompat.getColor(requireContext(), R.color.riotx_notice_secondary))
|
||||||
|
jsonRecyclerView.setValueUrlColor(ThemeUtils.getColor(requireContext(), android.R.attr.textColorLink))
|
||||||
|
jsonRecyclerView.setValueNullColor(ContextCompat.getColor(requireContext(), R.color.riotx_notice_secondary))
|
||||||
|
jsonRecyclerView.setBracesColor(ThemeUtils.getColor(requireContext(), R.attr.riotx_text_primary))
|
||||||
|
|
||||||
|
val jsonString = arguments?.getString(MvRx.KEY_ARG)
|
||||||
|
jsonRecyclerView.bindJson(jsonString)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun newInstance(jsonString: String): JsonViewerBottomSheetDialog {
|
||||||
|
return JsonViewerBottomSheetDialog().apply {
|
||||||
|
setArguments(Bundle().apply { putString(MvRx.KEY_ARG, jsonString) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
vector/src/main/res/layout/fragment_jsonviewer.xml
Normal file
16
vector/src/main/res/layout/fragment_jsonviewer.xml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:paddingTop="16dp"
|
||||||
|
android:paddingBottom="16dp"
|
||||||
|
android:fillViewport="true"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.yuyh.jsonviewer.library.JsonRecyclerView
|
||||||
|
android:id="@+id/rv_json"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:ignore="ScrollViewSize" />
|
||||||
|
</HorizontalScrollView>
|
|
@ -6,6 +6,8 @@
|
||||||
<!-- Sections has been created to avoid merge conflict. Let's see if it's better -->
|
<!-- Sections has been created to avoid merge conflict. Let's see if it's better -->
|
||||||
|
|
||||||
<!-- BEGIN Strings added by Valere -->
|
<!-- BEGIN Strings added by Valere -->
|
||||||
|
<string name="settings_dev_tools">Dev Tools</string>
|
||||||
|
<string name="settings_account_data">Account Data</string>
|
||||||
<plurals name="poll_info">
|
<plurals name="poll_info">
|
||||||
<item quantity="zero">%d vote</item>
|
<item quantity="zero">%d vote</item>
|
||||||
<item quantity="other">%d votes</item>
|
<item quantity="other">%d votes</item>
|
||||||
|
|
|
@ -63,6 +63,14 @@
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:title="@string/settings_push_rules"
|
android:title="@string/settings_push_rules"
|
||||||
app:fragment="im.vector.riotx.features.settings.push.PushRulesFragment" />
|
app:fragment="im.vector.riotx.features.settings.push.PushRulesFragment" />
|
||||||
|
</im.vector.riotx.core.preference.VectorPreferenceCategory>
|
||||||
|
|
||||||
|
<im.vector.riotx.core.preference.VectorPreferenceCategory android:title="@string/settings_dev_tools">
|
||||||
|
|
||||||
|
<im.vector.riotx.core.preference.VectorPreference
|
||||||
|
android:persistent="false"
|
||||||
|
android:title="@string/settings_account_data"
|
||||||
|
app:fragment="im.vector.riotx.features.settings.devtools.AccountDataFragment" />
|
||||||
|
|
||||||
</im.vector.riotx.core.preference.VectorPreferenceCategory>
|
</im.vector.riotx.core.preference.VectorPreferenceCategory>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue