Merge branch 'develop' into feature/bca/rust_flavor

This commit is contained in:
valere 2023-01-03 09:55:08 +01:00
commit 6952d17d16
50 changed files with 128 additions and 335 deletions

View File

@ -1,3 +1,46 @@
Changes in Element v1.5.18 (2023-01-02)
=======================================
This release fixes a bunch of recent regressions. Most of them were not pushed to production hopefully. Current production version is 1.5.11.
Threads are now enabled by default, and this may let the application perform an initial sync.
Testers on the PlayStore may have experimented some issues like empty room list, or incomplete room state (room name missing, etc.), or even crashing due to initial sync not using lazy loading of room members. All those issues have been fixed, but to fix your current state, please clear cache once you get the release 1.5.18.
Bugfixes 🐛
----------
- Start DM will create a deadlock if user profile was never loaded ([#7870](https://github.com/vector-im/element-android/issues/7870))
Changes in Element v1.5.16 (2022-12-29)
======================================
Features ✨
----------
- [Rich text editor] Add support for links ([#7746](https://github.com/vector-im/element-android/issues/7746))
- [Poll] When a poll is ended, use /relations API to ensure poll results are correct ([#7767](https://github.com/vector-im/element-android/issues/7767))
- [Session manager] Security recommendations cards: whole view should be tappable ([#7795](https://github.com/vector-im/element-android/issues/7795))
- [Session manager] Other sessions list: header should not be sticky ([#7797](https://github.com/vector-im/element-android/issues/7797))
Bugfixes 🐛
----------
- Do not show typing notification of ignored users. ([#2965](https://github.com/vector-im/element-android/issues/2965))
- [Push Notifications, Threads] - quick reply to threaded notification now sent to thread except main timeline ([#7475](https://github.com/vector-im/element-android/issues/7475))
- [Session manager] Other sessions list: filter option is displayed when selection mode is enabled ([#7784](https://github.com/vector-im/element-android/issues/7784))
- [Session manager] Other sessions: Filter bottom sheet cut in landscape mode ([#7786](https://github.com/vector-im/element-android/issues/7786))
- Automatically show keyboard after learn more bottom sheet is dismissed ([#7790](https://github.com/vector-im/element-android/issues/7790))
- [Session Manager] Other sessions list: cannot select/deselect session by a long press when in select mode ([#7792](https://github.com/vector-im/element-android/issues/7792))
- Fix current session ip address visibility ([#7794](https://github.com/vector-im/element-android/issues/7794))
- Device Manager UI review fixes ([#7798](https://github.com/vector-im/element-android/issues/7798))
SDK API changes ⚠️
------------------
- [Sync] Sync Filter params are moved to MatrixConfiguration and will not be stored in session realm to avoid bug when session cache is cleared ([#7843](https://github.com/vector-im/element-android/issues/7843))
Other changes
-------------
- [Voice Broadcast] Replace the player timeline ([#7821](https://github.com/vector-im/element-android/issues/7821))
- Increase session manager test coverage ([#7836](https://github.com/vector-im/element-android/issues/7836))
Changes in Element v1.5.14 (2022-12-20)
=======================================

View File

@ -1 +0,0 @@
Do not show typing notification of ignored users.

View File

@ -1 +0,0 @@
[Push Notifications, Threads] - quick reply to threaded notification now sent to thread except main timeline

View File

@ -1 +0,0 @@
[Rich text editor] Add support for links

View File

@ -1 +0,0 @@
[Poll] When a poll is ended, use /relations API to ensure poll results are correct

View File

@ -1 +0,0 @@
[Session manager] Other sessions list: filter option is displayed when selection mode is enabled

View File

@ -1 +0,0 @@
[Session manager] Other sessions: Filter bottom sheet cut in landscape mode

View File

@ -1 +0,0 @@
Automatically show keyboard after learn more bottom sheet is dismissed

View File

@ -1 +0,0 @@
[Session Manager] Other sessions list: cannot select/deselect session by a long press when in select mode

View File

@ -1 +0,0 @@
Fix current session ip address visibility

View File

@ -1 +0,0 @@
[Session manager] Security recommendations cards: whole view should be tappable

View File

@ -1 +0,0 @@
[Session manager] Other sessions list: header should not be sticky

View File

@ -1 +0,0 @@
Device Manager UI review fixes

View File

@ -1 +0,0 @@
[Voice Broadcast] Replace the player timeline

View File

@ -1 +0,0 @@
Increase session manager test coverage

View File

@ -0,0 +1,2 @@
Main changes in this version: Thread are now enabled by default.
Full changelog: https://github.com/vector-im/element-android/releases

View File

@ -0,0 +1,2 @@
Main changes in this version: Thread are now enabled by default.
Full changelog: https://github.com/vector-im/element-android/releases

View File

@ -63,7 +63,7 @@ android {
// that the app's state is completely cleared between tests.
testInstrumentationRunnerArguments clearPackageData: 'true'
buildConfigField "String", "SDK_VERSION", "\"1.5.16\""
buildConfigField "String", "SDK_VERSION", "\"1.5.20\""
buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\""
buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\""

View File

@ -50,7 +50,6 @@ import org.matrix.android.sdk.api.session.room.send.SendState
import org.matrix.android.sdk.api.session.room.timeline.Timeline
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
import org.matrix.android.sdk.api.session.sync.filter.SyncFilterBuilder
import timber.log.Timber
import java.util.UUID
import java.util.concurrent.CountDownLatch
@ -349,10 +348,6 @@ class CommonTestHelper internal constructor(context: Context, val cryptoConfig:
assertTrue(registrationResult is RegistrationResult.Success)
val session = (registrationResult as RegistrationResult.Success).session
session.open()
session.filterService().setSyncFilter(
SyncFilterBuilder()
.lazyLoadMembersForStateEvents(true)
)
if (sessionTestParams.withInitialSync) {
syncSession(session, 120_000)
}

View File

@ -16,9 +16,13 @@
package org.matrix.android.sdk.api
import org.matrix.android.sdk.api.session.sync.filter.SyncFilterParams
data class SyncConfig(
/**
* Time to keep sync connection alive for before making another request in milliseconds.
*/
val longPollTimeout: Long = 30_000L,
val syncFilterParams: SyncFilterParams = SyncFilterParams()
)

View File

@ -50,7 +50,6 @@ import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageServi
import org.matrix.android.sdk.api.session.signout.SignOutService
import org.matrix.android.sdk.api.session.space.SpaceService
import org.matrix.android.sdk.api.session.statistics.StatisticsListener
import org.matrix.android.sdk.api.session.sync.FilterService
import org.matrix.android.sdk.api.session.sync.SyncService
import org.matrix.android.sdk.api.session.terms.TermsService
import org.matrix.android.sdk.api.session.thirdparty.ThirdPartyService
@ -163,11 +162,6 @@ interface Session {
*/
fun signOutService(): SignOutService
/**
* Returns the FilterService associated with the session.
*/
fun filterService(): FilterService
/**
* Returns the PushRuleService associated with the session.
*/

View File

@ -14,9 +14,9 @@
* limitations under the License.
*/
package org.matrix.android.sdk.internal.sync.filter
package org.matrix.android.sdk.api.session.sync.filter
internal data class SyncFilterParams(
data class SyncFilterParams(
val lazyLoadMembersForStateEvents: Boolean? = null,
val lazyLoadMembersForMessageEvents: Boolean? = null,
val useThreadNotifications: Boolean? = null,

View File

@ -63,6 +63,7 @@ import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo043
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo044
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo045
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo046
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo047
import org.matrix.android.sdk.internal.util.Normalizer
import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration
import javax.inject.Inject
@ -71,7 +72,7 @@ internal class RealmSessionStoreMigration @Inject constructor(
private val normalizer: Normalizer
) : MatrixRealmMigration(
dbName = "Session",
schemaVersion = 46L,
schemaVersion = 47L,
) {
/**
* Forces all RealmSessionStoreMigration instances to be equal.
@ -127,5 +128,6 @@ internal class RealmSessionStoreMigration @Inject constructor(
if (oldVersion < 44) MigrateSessionTo044(realm).perform()
if (oldVersion < 45) MigrateSessionTo045(realm).perform()
if (oldVersion < 46) MigrateSessionTo046(realm).perform()
if (oldVersion < 47) MigrateSessionTo047(realm).perform()
}
}

View File

@ -1,61 +0,0 @@
/*
* Copyright 2022 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.internal.database.mapper
import io.realm.RealmList
import org.matrix.android.sdk.internal.database.model.SyncFilterParamsEntity
import org.matrix.android.sdk.internal.sync.filter.SyncFilterParams
import javax.inject.Inject
internal class FilterParamsMapper @Inject constructor() {
fun map(entity: SyncFilterParamsEntity): SyncFilterParams {
val eventTypes = if (entity.listOfSupportedEventTypesHasBeenSet) {
entity.listOfSupportedEventTypes?.toList()
} else {
null
}
val stateEventTypes = if (entity.listOfSupportedStateEventTypesHasBeenSet) {
entity.listOfSupportedStateEventTypes?.toList()
} else {
null
}
return SyncFilterParams(
useThreadNotifications = entity.useThreadNotifications,
lazyLoadMembersForMessageEvents = entity.lazyLoadMembersForMessageEvents,
lazyLoadMembersForStateEvents = entity.lazyLoadMembersForStateEvents,
listOfSupportedEventTypes = eventTypes,
listOfSupportedStateEventTypes = stateEventTypes,
)
}
fun map(params: SyncFilterParams): SyncFilterParamsEntity {
return SyncFilterParamsEntity(
useThreadNotifications = params.useThreadNotifications,
lazyLoadMembersForMessageEvents = params.lazyLoadMembersForMessageEvents,
lazyLoadMembersForStateEvents = params.lazyLoadMembersForStateEvents,
listOfSupportedEventTypes = params.listOfSupportedEventTypes.toRealmList(),
listOfSupportedEventTypesHasBeenSet = params.listOfSupportedEventTypes != null,
listOfSupportedStateEventTypes = params.listOfSupportedStateEventTypes.toRealmList(),
listOfSupportedStateEventTypesHasBeenSet = params.listOfSupportedStateEventTypes != null,
)
}
private fun List<String>?.toRealmList(): RealmList<String>? {
return this?.toTypedArray()?.let { RealmList(*it) }
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2020 The Matrix.org Foundation C.I.C.
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,14 +14,14 @@
* limitations under the License.
*/
package org.matrix.android.sdk.api.session.sync
package org.matrix.android.sdk.internal.database.migration
import org.matrix.android.sdk.api.session.sync.filter.SyncFilterBuilder
import io.realm.DynamicRealm
import org.matrix.android.sdk.internal.util.database.RealmMigrator
interface FilterService {
internal class MigrateSessionTo047(realm: DynamicRealm) : RealmMigrator(realm, 47) {
/**
* Configure the filter for the sync.
*/
suspend fun setSyncFilter(filterBuilder: SyncFilterBuilder)
override fun doMigrate(realm: DynamicRealm) {
realm.schema.remove("SyncFilterParamsEntity")
}
}

View File

@ -72,7 +72,6 @@ import org.matrix.android.sdk.internal.database.model.threads.ThreadSummaryEntit
SpaceParentSummaryEntity::class,
UserPresenceEntity::class,
ThreadSummaryEntity::class,
SyncFilterParamsEntity::class,
ThreadListPageEntity::class
]
)

View File

@ -57,7 +57,6 @@ import org.matrix.android.sdk.api.session.search.SearchService
import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageService
import org.matrix.android.sdk.api.session.signout.SignOutService
import org.matrix.android.sdk.api.session.space.SpaceService
import org.matrix.android.sdk.api.session.sync.FilterService
import org.matrix.android.sdk.api.session.sync.SyncService
import org.matrix.android.sdk.api.session.terms.TermsService
import org.matrix.android.sdk.api.session.thirdparty.ThirdPartyService
@ -96,7 +95,6 @@ internal class DefaultSession @Inject constructor(
private val roomService: Lazy<RoomService>,
private val roomDirectoryService: Lazy<RoomDirectoryService>,
private val userService: Lazy<UserService>,
private val filterService: Lazy<FilterService>,
private val federationService: Lazy<FederationService>,
private val cacheService: Lazy<CacheService>,
private val signOutService: Lazy<SignOutService>,
@ -208,7 +206,6 @@ internal class DefaultSession @Inject constructor(
override fun roomDirectoryService(): RoomDirectoryService = roomDirectoryService.get()
override fun userService(): UserService = userService.get()
override fun signOutService(): SignOutService = signOutService.get()
override fun filterService(): FilterService = filterService.get()
override fun pushRuleService(): PushRuleService = pushRuleService.get()
override fun pushersService(): PushersService = pushersService.get()
override fun eventService(): EventService = eventService.get()

View File

@ -17,20 +17,15 @@
package org.matrix.android.sdk.internal.session.filter
import com.zhuinden.monarchy.Monarchy
import io.realm.kotlin.where
import org.matrix.android.sdk.internal.database.mapper.FilterParamsMapper
import org.matrix.android.sdk.internal.database.model.FilterEntity
import org.matrix.android.sdk.internal.database.model.SyncFilterParamsEntity
import org.matrix.android.sdk.internal.database.query.get
import org.matrix.android.sdk.internal.database.query.getOrCreate
import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.sync.filter.SyncFilterParams
import org.matrix.android.sdk.internal.util.awaitTransaction
import javax.inject.Inject
internal class DefaultFilterRepository @Inject constructor(
@SessionDatabase private val monarchy: Monarchy,
private val filterParamsMapper: FilterParamsMapper
) : FilterRepository {
override suspend fun storeSyncFilter(filter: Filter, filterId: String, roomEventFilter: RoomEventFilter) {
@ -69,19 +64,4 @@ internal class DefaultFilterRepository @Inject constructor(
FilterEntity.getOrCreate(it).roomEventFilterJson
}
}
override suspend fun getStoredFilterParams(): SyncFilterParams? {
return monarchy.awaitTransaction { realm ->
realm.where<SyncFilterParamsEntity>().findFirst()?.let {
filterParamsMapper.map(it)
}
}
}
override suspend fun storeFilterParams(params: SyncFilterParams) {
return monarchy.awaitTransaction { realm ->
val entity = filterParamsMapper.map(params)
realm.insertOrUpdate(entity)
}
}
}

View File

@ -1,43 +0,0 @@
/*
* Copyright 2020 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.internal.session.filter
import org.matrix.android.sdk.api.session.sync.FilterService
import org.matrix.android.sdk.api.session.sync.filter.SyncFilterBuilder
import org.matrix.android.sdk.internal.session.homeserver.HomeServerCapabilitiesDataSource
import javax.inject.Inject
internal class DefaultFilterService @Inject constructor(
private val saveFilterTask: SaveFilterTask,
private val filterRepository: FilterRepository,
private val homeServerCapabilitiesDataSource: HomeServerCapabilitiesDataSource,
) : FilterService {
// TODO Pass a list of support events instead
override suspend fun setSyncFilter(filterBuilder: SyncFilterBuilder) {
filterRepository.storeFilterParams(filterBuilder.extractParams())
// don't upload/store filter until homeserver capabilities are fetched
homeServerCapabilitiesDataSource.getHomeServerCapabilities()?.let { homeServerCapabilities ->
saveFilterTask.execute(
SaveFilterTask.Params(
filter = filterBuilder.build(homeServerCapabilities)
)
)
}
}
}

View File

@ -19,7 +19,6 @@ package org.matrix.android.sdk.internal.session.filter
import dagger.Binds
import dagger.Module
import dagger.Provides
import org.matrix.android.sdk.api.session.sync.FilterService
import org.matrix.android.sdk.internal.session.SessionScope
import retrofit2.Retrofit
@ -39,9 +38,6 @@ internal abstract class FilterModule {
@Binds
abstract fun bindFilterRepository(repository: DefaultFilterRepository): FilterRepository
@Binds
abstract fun bindFilterService(service: DefaultFilterService): FilterService
@Binds
abstract fun bindSaveFilterTask(task: DefaultSaveFilterTask): SaveFilterTask

View File

@ -16,8 +16,6 @@
package org.matrix.android.sdk.internal.session.filter
import org.matrix.android.sdk.internal.sync.filter.SyncFilterParams
/**
* Repository for request filters.
*/
@ -44,14 +42,4 @@ internal interface FilterRepository {
* Return the room filter.
*/
suspend fun getRoomFilterBody(): String
/**
* Returns filter params stored in local storage if it exists.
*/
suspend fun getStoredFilterParams(): SyncFilterParams?
/**
* Stores filter params to local storage.
*/
suspend fun storeFilterParams(params: SyncFilterParams)
}

View File

@ -16,9 +16,10 @@
package org.matrix.android.sdk.internal.session.filter
import org.matrix.android.sdk.api.MatrixConfiguration
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
import org.matrix.android.sdk.api.session.sync.filter.SyncFilterBuilder
import org.matrix.android.sdk.internal.session.homeserver.HomeServerCapabilitiesDataSource
import org.matrix.android.sdk.internal.sync.filter.SyncFilterBuilder
import org.matrix.android.sdk.internal.task.Task
import javax.inject.Inject
@ -27,7 +28,8 @@ internal interface GetCurrentFilterTask : Task<Unit, String>
internal class DefaultGetCurrentFilterTask @Inject constructor(
private val filterRepository: FilterRepository,
private val homeServerCapabilitiesDataSource: HomeServerCapabilitiesDataSource,
private val saveFilterTask: SaveFilterTask
private val saveFilterTask: SaveFilterTask,
private val matrixConfiguration: MatrixConfiguration
) : GetCurrentFilterTask {
override suspend fun execute(params: Unit): String {
@ -35,7 +37,7 @@ internal class DefaultGetCurrentFilterTask @Inject constructor(
val storedFilterBody = filterRepository.getStoredSyncFilterBody()
val homeServerCapabilities = homeServerCapabilitiesDataSource.getHomeServerCapabilities() ?: HomeServerCapabilities()
val currentFilter = SyncFilterBuilder()
.with(filterRepository.getStoredFilterParams())
.with(matrixConfiguration.syncConfig.syncFilterParams)
.build(homeServerCapabilities)
val currentFilterBody = currentFilter.toJSONString()

View File

@ -23,6 +23,7 @@ import io.realm.kotlin.createObject
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.runBlocking
import org.matrix.android.sdk.api.session.crypto.CryptoService
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
import org.matrix.android.sdk.api.session.room.model.Membership
@ -73,8 +74,9 @@ internal class DefaultCreateLocalRoomTask @Inject constructor(
override suspend fun execute(params: CreateRoomParams): String {
val createRoomBody = createRoomBodyBuilder.build(params)
val roomId = RoomLocalEcho.createLocalEchoId()
val eventList = createLocalRoomStateEventsTask.execute(CreateLocalRoomStateEventsTask.Params(createRoomBody))
monarchy.awaitTransaction { realm ->
createLocalRoomEntity(realm, roomId, createRoomBody)
createLocalRoomEntity(realm, roomId, eventList)
createLocalRoomSummaryEntity(realm, roomId, params, createRoomBody)
}
@ -96,10 +98,10 @@ internal class DefaultCreateLocalRoomTask @Inject constructor(
* Create a local room entity from the given room creation params.
* This will also generate and store in database the chunk and the events related to the room params in order to retrieve and display the local room.
*/
private fun createLocalRoomEntity(realm: Realm, roomId: String, createRoomBody: CreateRoomBody) {
private fun createLocalRoomEntity(realm: Realm, roomId: String, localStateEventList: List<Event>) {
RoomEntity.getOrCreate(realm, roomId).apply {
membership = Membership.JOIN
chunks.add(createLocalRoomChunk(realm, roomId, createRoomBody))
chunks.add(createLocalRoomChunk(realm, roomId, localStateEventList))
membersLoadStatus = RoomMembersLoadStatusType.LOADED
}
}
@ -145,23 +147,19 @@ internal class DefaultCreateLocalRoomTask @Inject constructor(
*
* @param realm the current instance of realm
* @param roomId the id of the local room
* @param createRoomBody the room creation params
* @param localStateEventList list of local state events for that room
*
* @return a chunk entity
*/
private fun createLocalRoomChunk(realm: Realm, roomId: String, createRoomBody: CreateRoomBody): ChunkEntity {
private fun createLocalRoomChunk(realm: Realm, roomId: String, localStateEventList: List<Event>): ChunkEntity {
val chunkEntity = realm.createObject<ChunkEntity>().apply {
isLastBackward = true
isLastForward = true
}
// Can't suspend when using realm as it could jump thread
val eventList = runBlocking {
createLocalRoomStateEventsTask.execute(CreateLocalRoomStateEventsTask.Params(createRoomBody))
}
val roomMemberContentsByUser = HashMap<String, RoomMemberContent?>()
for (event in eventList) {
for (event in localStateEventList) {
if (event.eventId == null || event.senderId == null || event.type == null) {
continue
}

View File

@ -192,6 +192,11 @@ internal class RoomSummaryUpdater @Inject constructor(
roomSummaryEntity.otherMemberIds.clear()
roomSummaryEntity.otherMemberIds.addAll(otherRoomMembers)
if (roomSummary?.joinedMembersCount == null) {
// in case m.joined_member_count from sync summary was null?
// better to use what we know
roomSummaryEntity.joinedMembersCount = otherRoomMembers.size + 1
}
if (roomSummaryEntity.isEncrypted && otherRoomMembers.isNotEmpty()) {
if (aggregator == null) {
// Do it now

View File

@ -14,15 +14,15 @@
* limitations under the License.
*/
package org.matrix.android.sdk.api.session.sync.filter
package org.matrix.android.sdk.internal.sync.filter
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
import org.matrix.android.sdk.api.session.sync.filter.SyncFilterParams
import org.matrix.android.sdk.internal.session.filter.Filter
import org.matrix.android.sdk.internal.session.filter.RoomEventFilter
import org.matrix.android.sdk.internal.session.filter.RoomFilter
import org.matrix.android.sdk.internal.sync.filter.SyncFilterParams
class SyncFilterBuilder {
internal class SyncFilterBuilder {
private var lazyLoadMembersForStateEvents: Boolean? = null
private var lazyLoadMembersForMessageEvents: Boolean? = null
private var useThreadNotifications: Boolean? = null
@ -54,16 +54,6 @@ class SyncFilterBuilder {
}
}
internal fun extractParams(): SyncFilterParams {
return SyncFilterParams(
useThreadNotifications = useThreadNotifications,
lazyLoadMembersForMessageEvents = lazyLoadMembersForMessageEvents,
lazyLoadMembersForStateEvents = lazyLoadMembersForStateEvents,
listOfSupportedEventTypes = listOfSupportedEventTypes,
listOfSupportedStateEventTypes = listOfSupportedStateEventTypes,
)
}
internal fun build(homeServerCapabilities: HomeServerCapabilities): Filter {
return Filter(
room = buildRoomFilter(homeServerCapabilities)

View File

@ -16,14 +16,17 @@
package org.matrix.android.sdk.internal.sync
import io.mockk.mockk
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.amshove.kluent.shouldBeEqualTo
import org.junit.Test
import org.matrix.android.sdk.api.MatrixConfiguration
import org.matrix.android.sdk.api.SyncConfig
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
import org.matrix.android.sdk.api.session.sync.filter.SyncFilterBuilder
import org.matrix.android.sdk.api.session.sync.filter.SyncFilterParams
import org.matrix.android.sdk.internal.session.filter.DefaultGetCurrentFilterTask
import org.matrix.android.sdk.internal.sync.filter.SyncFilterParams
import org.matrix.android.sdk.internal.sync.filter.SyncFilterBuilder
import org.matrix.android.sdk.test.fakes.FakeFilterRepository
import org.matrix.android.sdk.test.fakes.FakeHomeServerCapabilitiesDataSource
import org.matrix.android.sdk.test.fakes.FakeSaveFilterTask
@ -31,7 +34,6 @@ import org.matrix.android.sdk.test.fakes.FakeSaveFilterTask
private const val A_FILTER_ID = "filter-id"
private val A_HOMESERVER_CAPABILITIES = HomeServerCapabilities()
private val A_SYNC_FILTER_PARAMS = SyncFilterParams(
lazyLoadMembersForMessageEvents = true,
lazyLoadMembersForStateEvents = true,
useThreadNotifications = true
)
@ -46,13 +48,16 @@ class DefaultGetCurrentFilterTaskTest {
private val getCurrentFilterTask = DefaultGetCurrentFilterTask(
filterRepository = filterRepository,
homeServerCapabilitiesDataSource = homeServerCapabilitiesDataSource.instance,
saveFilterTask = saveFilterTask
saveFilterTask = saveFilterTask,
matrixConfiguration = MatrixConfiguration(
applicationFlavor = "TestFlavor",
roomDisplayNameFallbackProvider = mockk(),
syncConfig = SyncConfig(syncFilterParams = SyncFilterParams(lazyLoadMembersForStateEvents = true, useThreadNotifications = true)),
)
)
@Test
fun `given no filter is stored, when execute, then executes task to save new filter`() = runTest {
filterRepository.givenFilterParamsAreStored(A_SYNC_FILTER_PARAMS)
homeServerCapabilitiesDataSource.givenHomeServerCapabilities(A_HOMESERVER_CAPABILITIES)
filterRepository.givenFilterStored(null, null)
@ -68,8 +73,6 @@ class DefaultGetCurrentFilterTaskTest {
@Test
fun `given filter is stored and didn't change, when execute, then returns stored filter id`() = runTest {
filterRepository.givenFilterParamsAreStored(A_SYNC_FILTER_PARAMS)
homeServerCapabilitiesDataSource.givenHomeServerCapabilities(A_HOMESERVER_CAPABILITIES)
val filter = SyncFilterBuilder().with(A_SYNC_FILTER_PARAMS).build(A_HOMESERVER_CAPABILITIES)
@ -82,8 +85,6 @@ class DefaultGetCurrentFilterTaskTest {
@Test
fun `given filter is set and home server capabilities has changed, when execute, then executes task to save new filter`() = runTest {
filterRepository.givenFilterParamsAreStored(A_SYNC_FILTER_PARAMS)
homeServerCapabilitiesDataSource.givenHomeServerCapabilities(A_HOMESERVER_CAPABILITIES)
val filter = SyncFilterBuilder().with(A_SYNC_FILTER_PARAMS).build(A_HOMESERVER_CAPABILITIES)

View File

@ -19,7 +19,6 @@ package org.matrix.android.sdk.test.fakes
import io.mockk.coEvery
import io.mockk.mockk
import org.matrix.android.sdk.internal.session.filter.FilterRepository
import org.matrix.android.sdk.internal.sync.filter.SyncFilterParams
internal class FakeFilterRepository : FilterRepository by mockk() {
@ -27,8 +26,4 @@ internal class FakeFilterRepository : FilterRepository by mockk() {
coEvery { getStoredSyncFilterId() } returns filterId
coEvery { getStoredSyncFilterBody() } returns filterBody
}
fun givenFilterParamsAreStored(syncFilterParams: SyncFilterParams?) {
coEvery { getStoredFilterParams() } returns syncFilterParams
}
}

View File

@ -14362,7 +14362,11 @@
"plant",
"nature",
"branch",
"summer"
"summer",
"bamboo",
"wish",
"star_festival",
"tanzaku"
]
},
"pine-decoration": {
@ -14373,10 +14377,12 @@
"celebration",
"Japanese",
"pine",
"japanese",
"plant",
"nature",
"vegetable",
"panda"
"panda",
"new_years"
]
},
"japanese-dolls": {

View File

@ -37,7 +37,7 @@ ext.versionMinor = 5
// Note: even values are reserved for regular release, odd values for hotfix release.
// When creating a hotfix, you should decrease the value, since the current value
// is the value for the next regular release.
ext.versionPatch = 16
ext.versionPatch = 20
static def getGitTimestamp() {
def cmd = 'git show -s --format=%ct'

View File

@ -90,7 +90,7 @@ fun getString(@StringRes id: Int): String {
return EspressoHelper.getCurrentActivity()!!.resources.getString(id)
}
fun waitForView(viewMatcher: Matcher<View>, timeout: Long = 10_000, waitForDisplayed: Boolean = true): ViewAction {
fun waitForView(viewMatcher: Matcher<View>, timeout: Long = 20_000, waitForDisplayed: Boolean = true): ViewAction {
return object : ViewAction {
private val clock = DefaultClock()

View File

@ -28,7 +28,6 @@ import im.vector.app.espresso.tools.ScreenshotFailureRule
import im.vector.app.features.MainActivity
import im.vector.app.getString
import im.vector.app.ui.robot.ElementRobot
import im.vector.app.ui.robot.settings.labs.LabFeature
import im.vector.app.ui.robot.settings.labs.LabFeaturesPreferences
import im.vector.app.ui.robot.withDeveloperMode
import org.junit.Rule
@ -133,6 +132,10 @@ class UiAllScreensSanityTest {
}
}
// Some instability with the bottomsheet
// not sure what's the source, maybe the expanded state?
Thread.sleep(10_000)
elementRobot.space { selectSpace(spaceName) }
elementRobot.layoutPreferences {
@ -175,7 +178,6 @@ class UiAllScreensSanityTest {
* Testing multiple threads screens
*/
private fun testThreadScreens() {
elementRobot.toggleLabFeature(LabFeature.THREAD_MESSAGES)
elementRobot.newRoom {
createNewRoom {
crawl()
@ -189,6 +191,5 @@ class UiAllScreensSanityTest {
}
}
}
elementRobot.toggleLabFeature(LabFeature.THREAD_MESSAGES)
}
}

View File

@ -28,7 +28,6 @@ import androidx.test.espresso.matcher.ViewMatchers.withText
import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
import im.vector.app.R
import im.vector.app.espresso.tools.waitUntilActivityVisible
import im.vector.app.espresso.tools.waitUntilDialogVisible
import im.vector.app.espresso.tools.waitUntilViewVisible
import im.vector.app.features.home.HomeActivity
import im.vector.app.features.home.room.detail.RoomDetailActivity
@ -86,14 +85,17 @@ class SpaceCreateRobot {
clickOn(R.id.nextButton)
waitUntilViewVisible(withId(R.id.recyclerView))
clickOn(R.id.nextButton)
// waitUntilActivityVisible<RoomDetailActivity> {
// waitUntilDialogVisible(withId(R.id.inviteByMxidButton))
// }
// // close invite dialog
// pressBack()
waitUntilActivityVisible<RoomDetailActivity> {
waitUntilDialogVisible(withId(R.id.inviteByMxidButton))
pressBack()
}
// close invite dialog
pressBack()
waitUntilViewVisible(withId(R.id.timelineRecyclerView))
// waitUntilViewVisible(withId(R.id.timelineRecyclerView))
// close room
pressBack()
// pressBack()
waitUntilViewVisible(withId(R.id.roomListContainer))
}
}

View File

@ -89,9 +89,8 @@ class SpaceMenuRobot {
clickOnSheet(R.id.leaveSpace)
waitUntilActivityVisible<SpaceLeaveAdvancedActivity> {
waitUntilViewVisible(ViewMatchers.withId(R.id.roomList))
}
clickOn(R.id.spaceLeaveSelectAll)
clickOn(R.id.spaceLeaveButton)
waitUntilViewVisible(ViewMatchers.withId(R.id.groupListView))
}
}
}

View File

@ -70,11 +70,13 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.SupervisorJob
import org.matrix.android.sdk.api.Matrix
import org.matrix.android.sdk.api.MatrixConfiguration
import org.matrix.android.sdk.api.SyncConfig
import org.matrix.android.sdk.api.auth.AuthenticationService
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
import org.matrix.android.sdk.api.legacy.LegacySessionImporter
import org.matrix.android.sdk.api.raw.RawService
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.sync.filter.SyncFilterParams
import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
import javax.inject.Singleton
@ -159,6 +161,9 @@ import javax.inject.Singleton
metricPlugins = vectorPlugins.plugins(),
cryptoAnalyticsPlugin = vectorPlugins.cryptoMetricPlugin,
customEventTypesProvider = vectorCustomEventTypesProvider,
syncConfig = SyncConfig(
syncFilterParams = SyncFilterParams(lazyLoadMembersForStateEvents = true, useThreadNotifications = true)
)
)
}

View File

@ -25,7 +25,6 @@ import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.session.coroutineScope
import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.settings.devices.v2.notification.UpdateNotificationSettingsAccountDataUseCase
import im.vector.app.features.sync.SyncUtils
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.session.Session
import timber.log.Timber
@ -43,9 +42,6 @@ class ConfigureAndStartSessionUseCase @Inject constructor(
fun execute(session: Session, startSyncing: Boolean = true) {
Timber.i("Configure and start session for ${session.myUserId}. startSyncing: $startSyncing")
session.open()
session.coroutineScope.launch {
session.filterService().setSyncFilter(SyncUtils.getSyncFilterBuilder())
}
if (startSyncing) {
session.startSyncing(context)
}

View File

@ -1,48 +0,0 @@
/*
* Copyright (c) 2022 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.app.features.sync
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.sync.filter.SyncFilterBuilder
object SyncUtils {
// Get only managed types by Element
private val listOfSupportedTimelineEventTypes = listOf(
// TODO Complete the list
EventType.MESSAGE
)
// Get only managed types by Element
private val listOfSupportedStateEventTypes = listOf(
// TODO Complete the list
EventType.STATE_ROOM_MEMBER
)
fun getSyncFilterBuilder(): SyncFilterBuilder {
return SyncFilterBuilder()
.useThreadNotifications(true)
.lazyLoadMembersForStateEvents(true)
/**
* Currently we don't set [lazy_load_members = true] for Filter.room.timeline even though we set it for RoomFilter which is used later to
* fetch messages in a room. It's not clear if it's done so by mistake or intentionally, so changing it could case side effects and need
* careful testing
* */
// .lazyLoadMembersForMessageEvents(true)
// .listOfSupportedStateEventTypes(listOfSupportedStateEventTypes)
// .listOfSupportedTimelineEventTypes(listOfSupportedTimelineEventTypes)
}
}

File diff suppressed because one or more lines are too long

View File

@ -20,7 +20,6 @@ import im.vector.app.core.extensions.startSyncing
import im.vector.app.core.session.clientinfo.UpdateMatrixClientInfoUseCase
import im.vector.app.features.session.coroutineScope
import im.vector.app.features.settings.devices.v2.notification.UpdateNotificationSettingsAccountDataUseCase
import im.vector.app.features.sync.SyncUtils
import im.vector.app.test.fakes.FakeContext
import im.vector.app.test.fakes.FakeNotificationsSettingUpdater
import im.vector.app.test.fakes.FakeSession
@ -87,7 +86,6 @@ class ConfigureAndStartSessionUseCaseTest {
// Then
verify { aSession.startSyncing(fakeContext.instance) }
aSession.fakeFilterService.verifySetSyncFilter(SyncUtils.getSyncFilterBuilder())
aSession.fakePushersService.verifyRefreshPushers()
fakeWebRtcCallManager.verifyCheckForProtocolsSupportIfNeeded()
coVerify {
@ -112,7 +110,6 @@ class ConfigureAndStartSessionUseCaseTest {
// Then
verify { aSession.startSyncing(fakeContext.instance) }
aSession.fakeFilterService.verifySetSyncFilter(SyncUtils.getSyncFilterBuilder())
aSession.fakePushersService.verifyRefreshPushers()
fakeWebRtcCallManager.verifyCheckForProtocolsSupportIfNeeded()
coVerify(inverse = true) {
@ -140,7 +137,6 @@ class ConfigureAndStartSessionUseCaseTest {
// Then
verify(inverse = true) { aSession.startSyncing(fakeContext.instance) }
aSession.fakeFilterService.verifySetSyncFilter(SyncUtils.getSyncFilterBuilder())
aSession.fakePushersService.verifyRefreshPushers()
fakeWebRtcCallManager.verifyCheckForProtocolsSupportIfNeeded()
coVerify {
@ -152,7 +148,6 @@ class ConfigureAndStartSessionUseCaseTest {
private fun givenASession(): FakeSession {
val fakeSession = FakeSession()
every { fakeSession.open() } just runs
fakeSession.fakeFilterService.givenSetFilterSucceeds()
every { fakeSession.startSyncing(any()) } just runs
fakeSession.fakePushersService.givenRefreshPushersSucceeds()
return fakeSession

View File

@ -1,36 +0,0 @@
/*
* Copyright (c) 2022 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.app.test.fakes
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.just
import io.mockk.mockk
import io.mockk.runs
import org.matrix.android.sdk.api.session.sync.FilterService
import org.matrix.android.sdk.api.session.sync.filter.SyncFilterBuilder
class FakeFilterService : FilterService by mockk() {
fun givenSetFilterSucceeds() {
coEvery { setSyncFilter(any()) } just runs
}
fun verifySetSyncFilter(filterBuilder: SyncFilterBuilder) {
coVerify { setSyncFilter(filterBuilder) }
}
}

View File

@ -43,8 +43,7 @@ class FakeSession(
val fakeRoomService: FakeRoomService = FakeRoomService(),
val fakePushersService: FakePushersService = FakePushersService(),
private val fakeEventService: FakeEventService = FakeEventService(),
val fakeSessionAccountDataService: FakeSessionAccountDataService = FakeSessionAccountDataService(),
val fakeFilterService: FakeFilterService = FakeFilterService(),
val fakeSessionAccountDataService: FakeSessionAccountDataService = FakeSessionAccountDataService()
) : Session by mockk(relaxed = true) {
init {
@ -63,7 +62,6 @@ class FakeSession(
override fun eventService() = fakeEventService
override fun pushersService() = fakePushersService
override fun accountDataService() = fakeSessionAccountDataService
override fun filterService() = fakeFilterService
fun givenVectorStore(vectorSessionStore: VectorSessionStore) {
coEvery {