Merge branch 'develop' into feature/aris/threads_live_timeline

# Conflicts:
#	matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo025.kt
This commit is contained in:
ariskotsomitopoulos 2022-02-14 16:13:51 +02:00
commit f98b595d85
11 changed files with 149 additions and 30 deletions

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

@ -0,0 +1 @@
Adds support for MSC3283, additional homeserver capabilities

View file

@ -104,3 +104,76 @@ fun initAccount() {
existingSession = createAccountAndSync(matrix, userName, password, true)
}
```
### Contributing to the UiAllScreensSanityTest
The `UiAllScreensSanityTest` makes use of the Robot pattern in order to model pages, components and interactions.
Each Robot aims to return the UI back to its original state after the interaction, allowing for a reusable and consistent DSL.
```kotlin
// launches and closes settings after executing the block
elementRobot.settings {
// whilst in the settings, launches and closes the advanced settings sub screen
advancedSettings {
// crawls all the pages within the advanced settings
crawl()
}
}
// enables developer mode by navigating to the settings, enabling the toggle and then returning to the starting point to execute the block
// on block completion the Robot disables developer mode by navigating back to the settings and finally returning to the original starting point
elementRobot.withDeveloperMode {
// the same starting point as the example above
settings {
advancedSettings { crawlDeveloperOptions() }
}
}
```
The Robots used in the example above...
```kotlin
class ElementRobot {
fun settings(block: SettingsRobot.() -> Unit) {
// double check we're where we think we are
waitUntilViewVisible(withId(R.id.bottomNavigationView))
// navigate to the settings
openDrawer()
clickOn(R.id.homeDrawerHeaderSettingsView)
// execute the robot with the context of the settings screen
block(SettingsRobot())
// close the settings and ensure we're back at the starting point
pressBack()
waitUntilViewVisible(withId(R.id.bottomNavigationView))
}
fun withDeveloperMode(block: ElementRobot.() -> Unit) {
settings { toggleDeveloperMode() }
block()
settings { toggleDeveloperMode() }
}
}
class SettingsRobot {
fun toggleDeveloperMode() {
advancedSettings {
toggleDeveloperMode()
}
}
fun advancedSettings(block: SettingsAdvancedRobot.() -> Unit) {
clickOn(R.string.settings_advanced_settings)
block(SettingsAdvancedRobot())
pressBack()
}
}
class SettingsAdvancedRobot {
fun toggleDeveloperMode() {
clickOn(R.string.settings_developer_mode_summary)
}
}
```

View file

@ -21,6 +21,18 @@ data class HomeServerCapabilities(
* True if it is possible to change the password of the account.
*/
val canChangePassword: Boolean = true,
/**
* True if it is possible to change the display name of the account.
*/
val canChangeDisplayName: Boolean = true,
/**
* True if it is possible to change the avatar of the account.
*/
val canChangeAvatar: Boolean = true,
/**
* True if it is possible to change the 3pid associations of the account.
*/
val canChange3pid: Boolean = true,
/**
* Max size of file which can be uploaded to the homeserver in bytes. [MAX_UPLOAD_FILE_SIZE_UNKNOWN] if unknown or not retrieved yet
*/
@ -76,6 +88,7 @@ data class HomeServerCapabilities(
}
}
}
fun isFeatureSupported(feature: String, byRoomVersion: String): Boolean {
if (roomVersions?.capabilities == null) return false
val info = roomVersions.capabilities[feature] ?: return false

View file

@ -35,6 +35,9 @@ internal object HomeServerCapabilitiesMapper {
fun map(entity: HomeServerCapabilitiesEntity): HomeServerCapabilities {
return HomeServerCapabilities(
canChangePassword = entity.canChangePassword,
canChangeDisplayName = entity.canChangeDisplayName,
canChangeAvatar = entity.canChangeAvatar,
canChange3pid = entity.canChange3pid,
maxUploadFileSize = entity.maxUploadFileSize,
lastVersionIdentityServerSupported = entity.lastVersionIdentityServerSupported,
defaultIdentityServerUrl = entity.defaultIdentityServerUrl,

View file

@ -17,7 +17,7 @@
package org.matrix.android.sdk.internal.database.migration
import io.realm.DynamicRealm
import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields
import org.matrix.android.sdk.internal.extensions.forceRefreshOfHomeServerCapabilities
import org.matrix.android.sdk.internal.util.database.RealmMigrator
class MigrateSessionTo003(realm: DynamicRealm) : RealmMigrator(realm, 3) {
@ -25,9 +25,6 @@ class MigrateSessionTo003(realm: DynamicRealm) : RealmMigrator(realm, 3) {
override fun doMigrate(realm: DynamicRealm) {
realm.schema.get("HomeServerCapabilitiesEntity")
?.addField("preferredJitsiDomain", String::class.java)
?.transform { obj ->
// Schedule a refresh of the capabilities
obj.setLong(HomeServerCapabilitiesEntityFields.LAST_UPDATED_TIMESTAMP, 0)
}
?.forceRefreshOfHomeServerCapabilities()
}
}

View file

@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.database.migration
import io.realm.DynamicRealm
import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields
import org.matrix.android.sdk.internal.extensions.forceRefreshOfHomeServerCapabilities
import org.matrix.android.sdk.internal.util.database.RealmMigrator
class MigrateSessionTo016(realm: DynamicRealm) : RealmMigrator(realm, 16) {
@ -25,9 +26,6 @@ class MigrateSessionTo016(realm: DynamicRealm) : RealmMigrator(realm, 16) {
override fun doMigrate(realm: DynamicRealm) {
realm.schema.get("HomeServerCapabilitiesEntity")
?.addField(HomeServerCapabilitiesEntityFields.ROOM_VERSIONS_JSON, String::class.java)
?.transform { obj ->
// Schedule a refresh of the capabilities
obj.setLong(HomeServerCapabilitiesEntityFields.LAST_UPDATED_TIMESTAMP, 0)
}
?.forceRefreshOfHomeServerCapabilities()
}
}

View file

@ -17,19 +17,17 @@
package org.matrix.android.sdk.internal.database.migration
import io.realm.DynamicRealm
import io.realm.FieldAttribute
import org.matrix.android.sdk.internal.database.model.ChunkEntityFields
import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields
import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields
import org.matrix.android.sdk.internal.extensions.forceRefreshOfHomeServerCapabilities
import org.matrix.android.sdk.internal.util.database.RealmMigrator
class MigrateSessionTo025(realm: DynamicRealm) : RealmMigrator(realm, 24) {
class MigrateSessionTo025(realm: DynamicRealm) : RealmMigrator(realm, 25) {
override fun doMigrate(realm: DynamicRealm) {
realm.schema.get("ChunkEntity")
?.addField(ChunkEntityFields.ROOT_THREAD_EVENT_ID, String::class.java, FieldAttribute.INDEXED)
?.addField(ChunkEntityFields.IS_LAST_FORWARD_THREAD, Boolean::class.java, FieldAttribute.INDEXED)
realm.schema.get("TimelineEventEntity")
?.addField(TimelineEventEntityFields.OWNED_BY_THREAD_CHUNK, Boolean::class.java)
realm.schema.get("HomeServerCapabilitiesEntity")
?.addField(HomeServerCapabilitiesEntityFields.CAN_CHANGE_DISPLAY_NAME, Boolean::class.java)
?.addField(HomeServerCapabilitiesEntityFields.CAN_CHANGE_AVATAR, Boolean::class.java)
?.addField(HomeServerCapabilitiesEntityFields.CAN_CHANGE3PID, Boolean::class.java)
?.forceRefreshOfHomeServerCapabilities()
}
}

View file

@ -21,6 +21,9 @@ import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
internal open class HomeServerCapabilitiesEntity(
var canChangePassword: Boolean = true,
var canChangeDisplayName: Boolean = true,
var canChangeAvatar: Boolean = true,
var canChange3pid: Boolean = true,
var roomVersionsJson: String? = null,
var maxUploadFileSize: Long = HomeServerCapabilities.MAX_UPLOAD_FILE_SIZE_UNKNOWN,
var lastVersionIdentityServerSupported: Boolean = false,

View file

@ -18,6 +18,8 @@ package org.matrix.android.sdk.internal.extensions
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.RealmObjectSchema
import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields
internal fun RealmObject.assertIsManaged() {
check(isManaged) { "${javaClass.simpleName} entity should be managed to use this function" }
@ -31,3 +33,12 @@ internal fun <T> RealmList<T>.clearWith(delete: (T) -> Unit) {
first()?.let { delete.invoke(it) }
}
}
/**
* Schedule a refresh of the HomeServers capabilities
*/
internal fun RealmObjectSchema?.forceRefreshOfHomeServerCapabilities(): RealmObjectSchema? {
return this?.transform { obj ->
obj.setLong(HomeServerCapabilitiesEntityFields.LAST_UPDATED_TIMESTAMP, 0)
}
}

View file

@ -18,7 +18,6 @@ package org.matrix.android.sdk.internal.session.homeserver
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.extensions.orTrue
import org.matrix.android.sdk.api.util.JsonDict
/**
@ -37,10 +36,30 @@ internal data class GetCapabilitiesResult(
internal data class Capabilities(
/**
* Capability to indicate if the user can change their password.
* True if the user can change their password, false otherwise.
*/
@Json(name = "m.change_password")
val changePassword: ChangePassword? = null,
val changePassword: BooleanCapability? = null,
/**
* Capability to indicate if the user can change their display name.
* True if the user can change their display name, false otherwise.
*/
@Json(name = "m.set_displayname")
val changeDisplayName: BooleanCapability? = null,
/**
* Capability to indicate if the user can change their avatar.
* True if the user can change their avatar, false otherwise.
*/
@Json(name = "m.set_avatar_url")
val changeAvatar: BooleanCapability? = null,
/**
* Capability to indicate if the user can change add, remove or change 3PID associations.
* True if the user can change their 3PID associations, false otherwise.
*/
@Json(name = "m.3pid_changes")
val change3pid: BooleanCapability? = null,
/**
* This capability describes the default and available room versions a server supports, and at what level of stability.
* Clients should make use of this capability to determine if users need to be encouraged to upgrade their rooms.
@ -50,9 +69,9 @@ internal data class Capabilities(
)
@JsonClass(generateAdapter = true)
internal data class ChangePassword(
internal data class BooleanCapability(
/**
* Required. True if the user can change their password, false otherwise.
* Required.
*/
@Json(name = "enabled")
val enabled: Boolean?
@ -87,8 +106,3 @@ internal data class RoomVersions(
@Json(name = "org.matrix.msc3244.room_capabilities")
val roomCapabilities: JsonDict? = null
)
// The spec says: If not present, the client should assume that password changes are possible via the API
internal fun GetCapabilitiesResult.canChangePassword(): Boolean {
return capabilities?.changePassword?.enabled.orTrue()
}

View file

@ -20,6 +20,7 @@ import com.zhuinden.monarchy.Monarchy
import org.matrix.android.sdk.api.MatrixPatterns.getDomain
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
import org.matrix.android.sdk.api.auth.wellknown.WellknownResult
import org.matrix.android.sdk.api.extensions.orTrue
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
import org.matrix.android.sdk.internal.auth.version.Versions
import org.matrix.android.sdk.internal.auth.version.isLoginAndRegistrationSupportedBySdk
@ -108,9 +109,16 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor(
val homeServerCapabilitiesEntity = HomeServerCapabilitiesEntity.getOrCreate(realm)
if (getCapabilitiesResult != null) {
homeServerCapabilitiesEntity.canChangePassword = getCapabilitiesResult.canChangePassword()
val capabilities = getCapabilitiesResult.capabilities
homeServerCapabilitiesEntity.roomVersionsJson = getCapabilitiesResult.capabilities?.roomVersions?.let {
// The spec says: If not present, the client should assume that
// password, display name, avatar changes and 3pid changes are possible via the API
homeServerCapabilitiesEntity.canChangePassword = capabilities?.changePassword?.enabled.orTrue()
homeServerCapabilitiesEntity.canChangeDisplayName = capabilities?.changeDisplayName?.enabled.orTrue()
homeServerCapabilitiesEntity.canChangeAvatar = capabilities?.changeAvatar?.enabled.orTrue()
homeServerCapabilitiesEntity.canChange3pid = capabilities?.change3pid?.enabled.orTrue()
homeServerCapabilitiesEntity.roomVersionsJson = capabilities?.roomVersions?.let {
MoshiProvider.providesMoshi().adapter(RoomVersions::class.java).toJson(it)
}
}