From c9ab0927f06309f56f71b460321c54abadbd9c47 Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Wed, 11 May 2022 16:19:33 +0200 Subject: [PATCH 001/131] Start DM - Add feature flag --- .../debug/features/DebugFeaturesStateFactory.kt | 5 +++++ .../features/debug/features/DebugVectorFeatures.kt | 4 ++++ .../java/im/vector/app/features/VectorFeatures.kt | 2 ++ .../createdirect/CreateDirectRoomViewModel.kt | 11 +++++++++-- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt b/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt index 248d9d232b..5506c2497c 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt +++ b/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt @@ -70,6 +70,11 @@ class DebugFeaturesStateFactory @Inject constructor( key = DebugFeatureKeys.allowExternalUnifiedPushDistributors, factory = VectorFeatures::allowExternalUnifiedPushDistributors ), + createBooleanFeature( + label = "Start DM on first message", + key = DebugFeatureKeys.startDmOnFirstMsg, + factory = VectorFeatures::shouldStartDmOnFirstMessage + ), ) ) } diff --git a/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt b/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt index 919cc6635e..617284d9e4 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt +++ b/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt @@ -66,6 +66,9 @@ class DebugVectorFeatures( override fun isScreenSharingEnabled(): Boolean = read(DebugFeatureKeys.screenSharing) ?: vectorFeatures.isScreenSharingEnabled() + override fun shouldStartDmOnFirstMessage(): Boolean = read(DebugFeatureKeys.startDmOnFirstMsg) + ?: vectorFeatures.shouldStartDmOnFirstMessage() + fun override(value: T?, key: Preferences.Key) = updatePreferences { if (value == null) { it.remove(key) @@ -123,4 +126,5 @@ object DebugFeatureKeys { val allowExternalUnifiedPushDistributors = booleanPreferencesKey("allow-external-unified-push-distributors") val liveLocationSharing = booleanPreferencesKey("live-location-sharing") val screenSharing = booleanPreferencesKey("screen-sharing") + val startDmOnFirstMsg = booleanPreferencesKey("start-dm-on-first-msg") } diff --git a/vector/src/main/java/im/vector/app/features/VectorFeatures.kt b/vector/src/main/java/im/vector/app/features/VectorFeatures.kt index 6fe4beff95..ad49916a07 100644 --- a/vector/src/main/java/im/vector/app/features/VectorFeatures.kt +++ b/vector/src/main/java/im/vector/app/features/VectorFeatures.kt @@ -30,6 +30,7 @@ interface VectorFeatures { fun isOnboardingCombinedLoginEnabled(): Boolean fun allowExternalUnifiedPushDistributors(): Boolean fun isScreenSharingEnabled(): Boolean + fun shouldStartDmOnFirstMessage(): Boolean enum class OnboardingVariant { LEGACY, @@ -48,4 +49,5 @@ class DefaultVectorFeatures : VectorFeatures { override fun isOnboardingCombinedLoginEnabled() = false override fun allowExternalUnifiedPushDistributors(): Boolean = Config.ALLOW_EXTERNAL_UNIFIED_PUSH_DISTRIBUTORS override fun isScreenSharingEnabled(): Boolean = true + override fun shouldStartDmOnFirstMessage(): Boolean = false } diff --git a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt index 8374f9d513..5574ce3e63 100644 --- a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt @@ -26,6 +26,7 @@ import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.mvrx.runCatchingToAsync import im.vector.app.core.platform.VectorViewModel +import im.vector.app.features.VectorFeatures import im.vector.app.features.analytics.AnalyticsTracker import im.vector.app.features.analytics.plan.CreatedRoom import im.vector.app.features.raw.wellknown.getElementWellknown @@ -46,7 +47,8 @@ class CreateDirectRoomViewModel @AssistedInject constructor( @Assisted initialState: CreateDirectRoomViewState, private val rawService: RawService, val session: Session, - val analyticsTracker: AnalyticsTracker + val analyticsTracker: AnalyticsTracker, + val vectorFeatures: VectorFeatures ) : VectorViewModel(initialState) { @@ -124,7 +126,12 @@ class CreateDirectRoomViewModel @AssistedInject constructor( } val result = runCatchingToAsync { - session.roomService().createRoom(roomParams) + if (vectorFeatures.shouldStartDmOnFirstMessage()) { + // Todo: Prepare direct room creation + throw Throwable("Start DM on first message is not implemented yet.") + } else { + session.roomService().createRoom(roomParams) + } } analyticsTracker.capture(CreatedRoom(isDM = roomParams.isDirect.orFalse())) From ba3d3501274bd7c2f372f54a87ee04f3527a4f81 Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Wed, 11 May 2022 16:20:27 +0200 Subject: [PATCH 002/131] Fix VectorFeature pref key --- .../vector/app/features/debug/features/DebugVectorFeatures.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt b/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt index 617284d9e4..7f74737719 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt +++ b/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt @@ -119,7 +119,7 @@ private fun > enumPreferencesKey(type: KClass) = stringPreference object DebugFeatureKeys { val onboardingAlreadyHaveAnAccount = booleanPreferencesKey("onboarding-already-have-an-account") val onboardingSplashCarousel = booleanPreferencesKey("onboarding-splash-carousel") - val onboardingUseCase = booleanPreferencesKey("onboarding-splash-carousel") + val onboardingUseCase = booleanPreferencesKey("onboarding-use-case") val onboardingPersonalize = booleanPreferencesKey("onboarding-personalize") val onboardingCombinedRegister = booleanPreferencesKey("onboarding-combined-register") val onboardingCombinedLogin = booleanPreferencesKey("onboarding-combined-login") From 26d1a12b74955df839ef513b6987d5d520662ec9 Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Wed, 16 Mar 2022 17:43:29 +0100 Subject: [PATCH 003/131] Start DM - Rename action button to "go" --- vector/src/main/res/menu/vector_create_direct_room.xml | 2 +- vector/src/main/res/values/strings.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/vector/src/main/res/menu/vector_create_direct_room.xml b/vector/src/main/res/menu/vector_create_direct_room.xml index 8c6eab1c52..10b2adf23d 100755 --- a/vector/src/main/res/menu/vector_create_direct_room.xml +++ b/vector/src/main/res/menu/vector_create_direct_room.xml @@ -4,7 +4,7 @@ diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index f60da53c09..b507ed473f 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -1623,6 +1623,7 @@ "CREATE" + Go "Room name" "Name" "Room topic (optional)" From 10d683ad5d1bf931b7578cfa558108826c7fb407 Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Thu, 17 Mar 2022 10:37:04 +0100 Subject: [PATCH 004/131] Start DM - display a local room before creating the real one Add CreateLocalRoomTask interface and remove DI annotations --- .../sdk/api/session/room/RoomService.kt | 7 + .../room/model/localecho/RoomLocalEcho.kt | 28 ++ .../session/room/DefaultRoomService.kt | 6 + .../sdk/internal/session/room/RoomModule.kt | 5 + .../room/create/CreateLocalRoomTask.kt | 267 ++++++++++++++++++ .../session/room/create/CreateRoomBody.kt | 17 ++ .../session/room/create/CreateRoomTask.kt | 29 +- .../session/room/timeline/DefaultTimeline.kt | 2 + .../createdirect/CreateDirectRoomAction.kt | 4 +- .../createdirect/CreateDirectRoomActivity.kt | 2 +- .../createdirect/CreateDirectRoomViewModel.kt | 20 +- .../createdirect/CreateDirectRoomViewState.kt | 2 + 12 files changed, 352 insertions(+), 37 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/localecho/RoomLocalEcho.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt index 5dfb8961e3..41a215636d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt @@ -40,6 +40,13 @@ interface RoomService { */ suspend fun createRoom(createRoomParams: CreateRoomParams): String + /** + * Create a room locally. + * This room will not be synchronized with the server and will not come back from the sync, so all the events related to this room will be generated + * locally. + */ + suspend fun createLocalRoom(createRoomParams: CreateRoomParams): String + /** * Create a direct room asynchronously. This is a facility method to create a direct room with the necessary parameters. */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/localecho/RoomLocalEcho.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/localecho/RoomLocalEcho.kt new file mode 100644 index 0000000000..a9804c6dac --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/localecho/RoomLocalEcho.kt @@ -0,0 +1,28 @@ +/* + * 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.api.session.room.model.localecho + +import java.util.UUID + +object RoomLocalEcho { + + private const val PREFIX = "!local." + + fun isLocalEchoId(roomId: String) = roomId.startsWith(PREFIX) + + fun createLocalEchoId() = "${PREFIX}${UUID.randomUUID()}" +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt index 5e6d052443..cc5e935f87 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt @@ -43,6 +43,7 @@ import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntityFie import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.session.room.alias.DeleteRoomAliasTask import org.matrix.android.sdk.internal.session.room.alias.GetRoomIdByAliasTask +import org.matrix.android.sdk.internal.session.room.create.CreateLocalRoomTask import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask import org.matrix.android.sdk.internal.session.room.membership.RoomChangeMembershipStateDataSource import org.matrix.android.sdk.internal.session.room.membership.RoomMemberHelper @@ -60,6 +61,7 @@ import javax.inject.Inject internal class DefaultRoomService @Inject constructor( @SessionDatabase private val monarchy: Monarchy, private val createRoomTask: CreateRoomTask, + private val createLocalRoomTask: CreateLocalRoomTask, private val joinRoomTask: JoinRoomTask, private val markAllRoomsReadTask: MarkAllRoomsReadTask, private val updateBreadcrumbsTask: UpdateBreadcrumbsTask, @@ -78,6 +80,10 @@ internal class DefaultRoomService @Inject constructor( return createRoomTask.executeRetry(createRoomParams, 3) } + override suspend fun createLocalRoom(createRoomParams: CreateRoomParams): String { + return createLocalRoomTask.execute(createRoomParams) + } + override fun getRoom(roomId: String): Room? { return roomGetter.getRoom(roomId) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt index f3845f1f15..bb92287ead 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt @@ -43,7 +43,9 @@ import org.matrix.android.sdk.internal.session.room.alias.DefaultGetRoomLocalAli import org.matrix.android.sdk.internal.session.room.alias.DeleteRoomAliasTask import org.matrix.android.sdk.internal.session.room.alias.GetRoomIdByAliasTask import org.matrix.android.sdk.internal.session.room.alias.GetRoomLocalAliasesTask +import org.matrix.android.sdk.internal.session.room.create.CreateLocalRoomTask import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask +import org.matrix.android.sdk.internal.session.room.create.DefaultCreateLocalRoomTask import org.matrix.android.sdk.internal.session.room.create.DefaultCreateRoomTask import org.matrix.android.sdk.internal.session.room.directory.DefaultGetPublicRoomTask import org.matrix.android.sdk.internal.session.room.directory.DefaultGetRoomDirectoryVisibilityTask @@ -192,6 +194,9 @@ internal abstract class RoomModule { @Binds abstract fun bindCreateRoomTask(task: DefaultCreateRoomTask): CreateRoomTask + @Binds + abstract fun bindCreateLocalRoomTask(task: DefaultCreateLocalRoomTask): CreateLocalRoomTask + @Binds abstract fun bindGetPublicRoomTask(task: DefaultGetPublicRoomTask): GetPublicRoomTask diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt new file mode 100644 index 0000000000..e650039d75 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt @@ -0,0 +1,267 @@ +/* + * 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.session.room.create + +import com.zhuinden.monarchy.Monarchy +import io.realm.Realm +import io.realm.RealmConfiguration +import io.realm.kotlin.createObject +import kotlinx.coroutines.TimeoutCancellationException +import org.matrix.android.sdk.api.extensions.orFalse +import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.api.session.events.model.Content +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.events.model.toContent +import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure +import org.matrix.android.sdk.api.session.room.model.GuestAccess +import org.matrix.android.sdk.api.session.room.model.Membership +import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility +import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility +import org.matrix.android.sdk.api.session.room.model.RoomMemberContent +import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams +import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent +import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho +import org.matrix.android.sdk.api.session.room.send.SendState +import org.matrix.android.sdk.api.session.sync.model.RoomSyncSummary +import org.matrix.android.sdk.api.session.user.UserService +import org.matrix.android.sdk.api.session.user.model.User +import org.matrix.android.sdk.internal.database.awaitNotEmptyResult +import org.matrix.android.sdk.internal.database.helper.addTimelineEvent +import org.matrix.android.sdk.internal.database.mapper.asDomain +import org.matrix.android.sdk.internal.database.mapper.toEntity +import org.matrix.android.sdk.internal.database.model.ChunkEntity +import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity +import org.matrix.android.sdk.internal.database.model.EventInsertType +import org.matrix.android.sdk.internal.database.model.RoomEntity +import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity +import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields +import org.matrix.android.sdk.internal.database.query.copyToRealmOrIgnore +import org.matrix.android.sdk.internal.database.query.getOrCreate +import org.matrix.android.sdk.internal.database.query.getOrNull +import org.matrix.android.sdk.internal.di.SessionDatabase +import org.matrix.android.sdk.internal.di.UserId +import org.matrix.android.sdk.internal.session.events.getFixedRoomMemberContent +import org.matrix.android.sdk.internal.session.room.membership.RoomMemberEventHandler +import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryUpdater +import org.matrix.android.sdk.internal.session.room.timeline.PaginationDirection +import org.matrix.android.sdk.internal.task.Task +import org.matrix.android.sdk.internal.util.awaitTransaction +import org.matrix.android.sdk.internal.util.time.Clock +import java.util.UUID +import java.util.concurrent.TimeUnit +import javax.inject.Inject + +internal interface CreateLocalRoomTask : Task + +internal class DefaultCreateLocalRoomTask @Inject constructor( + @UserId private val userId: String, + @SessionDatabase private val monarchy: Monarchy, + private val roomMemberEventHandler: RoomMemberEventHandler, + private val roomSummaryUpdater: RoomSummaryUpdater, + @SessionDatabase private val realmConfiguration: RealmConfiguration, + private val createRoomBodyBuilder: CreateRoomBodyBuilder, + private val userService: UserService, + private val clock: Clock, +) : CreateLocalRoomTask { + + override suspend fun execute(params: CreateRoomParams): String { + val createRoomBody = createRoomBodyBuilder.build(params.withDefault()) + val roomId = RoomLocalEcho.createLocalEchoId() + monarchy.awaitTransaction { realm -> + createLocalRoomEntity(realm, roomId, createRoomBody) + createLocalRoomSummaryEntity(realm, roomId, createRoomBody) + } + + // Wait for room to be created in DB + try { + awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm -> + realm.where(RoomSummaryEntity::class.java) + .equalTo(RoomSummaryEntityFields.ROOM_ID, roomId) + .equalTo(RoomSummaryEntityFields.MEMBERSHIP_STR, Membership.JOIN.name) + } + } catch (exception: TimeoutCancellationException) { + throw CreateRoomFailure.CreatedWithTimeout(roomId) + } + + return roomId + } + + /** + * 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 suspend fun createLocalRoomEntity(realm: Realm, roomId: String, createRoomBody: CreateRoomBody) { + RoomEntity.getOrCreate(realm, roomId).apply { + membership = Membership.JOIN + chunks.add(createLocalRoomChunk(realm, roomId, createRoomBody)) + } + } + + private fun createLocalRoomSummaryEntity(realm: Realm, roomId: String, createRoomBody: CreateRoomBody) { + val otherUserId = createRoomBody.getDirectUserId() + if (otherUserId != null) { + RoomSummaryEntity.getOrCreate(realm, roomId).apply { + isDirect = true + directUserId = otherUserId + } + } + roomSummaryUpdater.update( + realm = realm, + roomId = roomId, + membership = Membership.JOIN, + roomSummary = RoomSyncSummary( + heroes = createRoomBody.invitedUserIds.orEmpty().take(5), + joinedMembersCount = 1, + invitedMembersCount = createRoomBody.invitedUserIds?.size ?: 0 + ), + updateMembers = !createRoomBody.invitedUserIds.isNullOrEmpty() + ) + } + + /** + * Create a single chunk containing the necessary events to display the local room. + * + * @param realm the current instance of realm + * @param roomId the id of the local room + * @param createRoomBody the room creation params + * + * @return a chunk entity + */ + private suspend fun createLocalRoomChunk(realm: Realm, roomId: String, createRoomBody: CreateRoomBody): ChunkEntity { + val chunkEntity = realm.createObject().apply { + isLastBackward = true + isLastForward = true + } + + val eventList = createLocalRoomEvents(createRoomBody) + val eventIds = ArrayList(eventList.size) + val roomMemberContentsByUser = HashMap() + + for (event in eventList) { + if (event.eventId == null || event.senderId == null || event.type == null) { + continue + } + + eventIds.add(event.eventId) + + val eventEntity = event.toEntity(roomId, SendState.SYNCED, null).copyToRealmOrIgnore(realm, EventInsertType.INCREMENTAL_SYNC) + if (event.stateKey != null) { + CurrentStateEventEntity.getOrCreate(realm, roomId, event.stateKey, event.type).apply { + eventId = event.eventId + root = eventEntity + } + if (event.type == EventType.STATE_ROOM_MEMBER) { + roomMemberContentsByUser[event.stateKey] = event.getFixedRoomMemberContent() + roomMemberEventHandler.handle(realm, roomId, event, false) + } + } + + roomMemberContentsByUser.getOrPut(event.senderId) { + // If we don't have any new state on this user, get it from db + val rootStateEvent = CurrentStateEventEntity.getOrNull(realm, roomId, event.senderId, EventType.STATE_ROOM_MEMBER)?.root + rootStateEvent?.asDomain()?.getFixedRoomMemberContent() + } + + chunkEntity.addTimelineEvent( + roomId = roomId, + eventEntity = eventEntity, + direction = PaginationDirection.FORWARDS, + roomMemberContentsByUser = roomMemberContentsByUser + ) + } + + return chunkEntity + } + + /** + * Build the list of the events related to the room creation params. + * + * @param createRoomBody the room creation params + * + * @return the list of events + */ + private suspend fun createLocalRoomEvents(createRoomBody: CreateRoomBody): List { + val myUser = userService.getUser(userId) ?: User(userId) + val invitedUsers = createRoomBody.invitedUserIds.orEmpty() + .mapNotNull { tryOrNull { userService.resolveUser(it) } } + + val createRoomEvent = createFakeEvent( + type = EventType.STATE_ROOM_CREATE, + content = RoomCreateContent( + creator = userId + ).toContent() + ) + val myRoomMemberEvent = createFakeEvent( + type = EventType.STATE_ROOM_MEMBER, + content = RoomMemberContent( + membership = Membership.JOIN, + displayName = myUser.displayName, + avatarUrl = myUser.avatarUrl + ).toContent(), + stateKey = userId + ) + val roomMemberEvents = invitedUsers.map { + createFakeEvent( + type = EventType.STATE_ROOM_MEMBER, + content = RoomMemberContent( + isDirect = createRoomBody.isDirect.orFalse(), + membership = Membership.INVITE, + displayName = it.displayName, + avatarUrl = it.avatarUrl + ).toContent(), + stateKey = it.userId + ) + } + + return buildList { + add(createRoomEvent) + add(myRoomMemberEvent) + addAll(createRoomBody.initialStates.orEmpty().map { createFakeEvent(it.type, it.content, it.stateKey) }) + addAll(roomMemberEvents) + } + } + + /** + * Generate a local event from the given parameters. + * + * @param type the event type, see [EventType] + * @param content the content of the Event + * @param stateKey the stateKey, if any + * + * @return a fake event + */ + private fun createFakeEvent(type: String?, content: Content?, stateKey: String? = ""): Event { + return Event( + type = type, + senderId = userId, + stateKey = stateKey, + content = content, + originServerTs = clock.epochMillis(), + eventId = UUID.randomUUID().toString() + ) + } + + /** + * Setup default values to the CreateRoomParams as the room is created locally (the default values will not be defined by the server). + */ + private fun CreateRoomParams.withDefault() = this.apply { + if (visibility == null) visibility = RoomDirectoryVisibility.PRIVATE + if (historyVisibility == null) historyVisibility = RoomHistoryVisibility.SHARED + if (guestAccess == null) guestAccess = GuestAccess.Forbidden + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBody.kt index cffa632768..b326c3618c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBody.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBody.kt @@ -120,3 +120,20 @@ internal data class CreateRoomBody( @Json(name = "room_version") val roomVersion: String? ) + +/** + * Tells if the created room can be a direct chat one. + * + * @return true if it is a direct chat + */ +private fun CreateRoomBody.isDirect(): Boolean { + return preset == CreateRoomPreset.PRESET_TRUSTED_PRIVATE_CHAT && isDirect == true +} + +internal fun CreateRoomBody.getDirectUserId(): String? { + return if (isDirect()) { + invitedUserIds?.firstOrNull() + ?: invite3pids?.firstOrNull()?.address + ?: throw IllegalStateException("You can't create a direct room without an invitedUser") + } else null +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomTask.kt index 6dd2c91048..d76640573f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomTask.kt @@ -62,11 +62,6 @@ internal class DefaultCreateRoomTask @Inject constructor( ) : CreateRoomTask { override suspend fun execute(params: CreateRoomParams): String { - val otherUserId = if (params.isDirect()) { - params.getFirstInvitedUserId() - ?: throw IllegalStateException("You can't create a direct room without an invitedUser") - } else null - if (params.preset == CreateRoomPreset.PRESET_PUBLIC_CHAT) { try { aliasAvailabilityChecker.check(params.roomAliasName) @@ -111,14 +106,13 @@ internal class DefaultCreateRoomTask @Inject constructor( RoomSummaryEntity.where(it, roomId).findFirst()?.lastActivityTime = clock.epochMillis() } - if (otherUserId != null) { - handleDirectChatCreation(roomId, otherUserId) - } + handleDirectChatCreation(roomId, createRoomBody.getDirectUserId()) setReadMarkers(roomId) return roomId } - private suspend fun handleDirectChatCreation(roomId: String, otherUserId: String) { + private suspend fun handleDirectChatCreation(roomId: String, otherUserId: String?) { + otherUserId ?: return // This is not a direct room monarchy.awaitTransaction { realm -> RoomSummaryEntity.where(realm, roomId).findFirst()?.apply { this.directUserId = otherUserId @@ -133,21 +127,4 @@ internal class DefaultCreateRoomTask @Inject constructor( val setReadMarkerParams = SetReadMarkersTask.Params(roomId, forceReadReceipt = true, forceReadMarker = true) return readMarkersTask.execute(setReadMarkerParams) } - - /** - * Tells if the created room can be a direct chat one. - * - * @return true if it is a direct chat - */ - private fun CreateRoomParams.isDirect(): Boolean { - return preset == CreateRoomPreset.PRESET_TRUSTED_PRIVATE_CHAT && - isDirect == true - } - - /** - * @return the first invited user id - */ - private fun CreateRoomParams.getFirstInvitedUserId(): String? { - return invitedUserIds.firstOrNull() ?: invite3pids.firstOrNull()?.value - } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt index 44a786a95d..05379a1a7b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt @@ -32,6 +32,7 @@ import kotlinx.coroutines.withContext import okhttp3.internal.closeQuietly import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho 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 @@ -383,6 +384,7 @@ internal class DefaultTimeline( } private suspend fun loadRoomMembersIfNeeded() { + if (RoomLocalEcho.isLocalEchoId(roomId)) return val loadRoomMembersParam = LoadRoomMembersTask.Params(roomId) try { loadRoomMembersTask.execute(loadRoomMembersParam) diff --git a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomAction.kt b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomAction.kt index 83c7f0a13b..b5657598ee 100644 --- a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomAction.kt +++ b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomAction.kt @@ -20,10 +20,12 @@ import im.vector.app.core.platform.VectorViewModelAction import im.vector.app.features.userdirectory.PendingSelection sealed class CreateDirectRoomAction : VectorViewModelAction { - data class CreateRoomAndInviteSelectedUsers( + data class PrepareRoomWithSelectedUsers( val selections: Set ) : CreateDirectRoomAction() + object CreateRoomAndInviteSelectedUsers : CreateDirectRoomAction() + data class QrScannedAction( val result: String ) : CreateDirectRoomAction() diff --git a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt index 6292217b67..377acd2271 100644 --- a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt +++ b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt @@ -161,7 +161,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { private fun onMenuItemSelected(action: UserListSharedAction.OnMenuItemSelected) { if (action.itemId == R.id.action_create_direct_room) { - viewModel.handle(CreateDirectRoomAction.CreateRoomAndInviteSelectedUsers(action.selections)) + viewModel.handle(CreateDirectRoomAction.PrepareRoomWithSelectedUsers(action.selections)) } } diff --git a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt index 5574ce3e63..b306cb6e03 100644 --- a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt @@ -61,7 +61,8 @@ class CreateDirectRoomViewModel @AssistedInject constructor( override fun handle(action: CreateDirectRoomAction) { when (action) { - is CreateDirectRoomAction.CreateRoomAndInviteSelectedUsers -> onSubmitInvitees(action.selections) + is CreateDirectRoomAction.PrepareRoomWithSelectedUsers -> onSubmitInvitees(action.selections) + is CreateDirectRoomAction.CreateRoomAndInviteSelectedUsers -> onCreateRoomWithInvitees() is CreateDirectRoomAction.QrScannedAction -> onCodeParsed(action) } } @@ -96,16 +97,18 @@ class CreateDirectRoomViewModel @AssistedInject constructor( } if (existingRoomId != null) { // Do not create a new DM, just tell that the creation is successful by passing the existing roomId - setState { - copy(createAndInviteState = Success(existingRoomId)) - } + setState { copy(createAndInviteState = Success(existingRoomId)) } } else { - // Create the DM - createRoomAndInviteSelectedUsers(selections) + createLocalRoomWithSelectedUsers(selections) } } - private fun createRoomAndInviteSelectedUsers(selections: Set) { + private fun onCreateRoomWithInvitees() { + // Create the DM + withState { createLocalRoomWithSelectedUsers(it.pendingSelections) } + } + + private fun createLocalRoomWithSelectedUsers(selections: Set) { setState { copy(createAndInviteState = Loading()) } viewModelScope.launch(Dispatchers.IO) { @@ -127,8 +130,7 @@ class CreateDirectRoomViewModel @AssistedInject constructor( val result = runCatchingToAsync { if (vectorFeatures.shouldStartDmOnFirstMessage()) { - // Todo: Prepare direct room creation - throw Throwable("Start DM on first message is not implemented yet.") + session.roomService().createLocalRoom(roomParams) } else { session.roomService().createRoom(roomParams) } diff --git a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewState.kt b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewState.kt index 41366a7110..33360ac20c 100644 --- a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewState.kt +++ b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewState.kt @@ -19,7 +19,9 @@ package im.vector.app.features.createdirect import com.airbnb.mvrx.Async import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.Uninitialized +import im.vector.app.features.userdirectory.PendingSelection data class CreateDirectRoomViewState( + val pendingSelections: Set = emptySet(), val createAndInviteState: Async = Uninitialized ) : MavericksState From 7ea2d0a86da9da63a9bab8ce8d33a66416649e94 Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Thu, 12 May 2022 11:32:31 +0200 Subject: [PATCH 005/131] Delete the local rooms when the room list is shown --- .../sdk/api/session/room/RoomService.kt | 5 ++ .../query/CurrentStateEventEntityQueries.kt | 11 ++- .../session/room/DefaultRoomService.kt | 6 ++ .../sdk/internal/session/room/RoomModule.kt | 5 ++ .../room/delete/DeleteLocalRoomTask.kt | 77 +++++++++++++++++++ .../home/room/detail/RoomDetailViewState.kt | 3 + .../home/room/detail/TimelineFragment.kt | 61 +++++++++------ .../home/room/detail/TimelineViewModel.kt | 42 +++++----- .../home/room/list/RoomListFragment.kt | 4 + .../home/room/list/RoomListViewModel.kt | 29 +++++++ .../home/room/list/RoomListViewState.kt | 3 +- 11 files changed, 201 insertions(+), 45 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/delete/DeleteLocalRoomTask.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt index 41a215636d..90f3f323b2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt @@ -47,6 +47,11 @@ interface RoomService { */ suspend fun createLocalRoom(createRoomParams: CreateRoomParams): String + /** + * Delete a local room with all its related events. + */ + suspend fun deleteLocalRoom(roomId: String) + /** * Create a direct room asynchronously. This is a facility method to create a direct room with the necessary parameters. */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/CurrentStateEventEntityQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/CurrentStateEventEntityQueries.kt index e0dbf2eee8..e17d07c584 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/CurrentStateEventEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/CurrentStateEventEntityQueries.kt @@ -23,13 +23,20 @@ import io.realm.kotlin.createObject import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntityFields +internal fun CurrentStateEventEntity.Companion.whereRoomId( + realm: Realm, + roomId: String +): RealmQuery { + return realm.where(CurrentStateEventEntity::class.java) + .equalTo(CurrentStateEventEntityFields.ROOM_ID, roomId) +} + internal fun CurrentStateEventEntity.Companion.whereType( realm: Realm, roomId: String, type: String ): RealmQuery { - return realm.where(CurrentStateEventEntity::class.java) - .equalTo(CurrentStateEventEntityFields.ROOM_ID, roomId) + return whereRoomId(realm = realm, roomId = roomId) .equalTo(CurrentStateEventEntityFields.TYPE, type) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt index cc5e935f87..6fd4f752a8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt @@ -45,6 +45,7 @@ import org.matrix.android.sdk.internal.session.room.alias.DeleteRoomAliasTask import org.matrix.android.sdk.internal.session.room.alias.GetRoomIdByAliasTask import org.matrix.android.sdk.internal.session.room.create.CreateLocalRoomTask import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask +import org.matrix.android.sdk.internal.session.room.delete.DeleteLocalRoomTask import org.matrix.android.sdk.internal.session.room.membership.RoomChangeMembershipStateDataSource import org.matrix.android.sdk.internal.session.room.membership.RoomMemberHelper import org.matrix.android.sdk.internal.session.room.membership.joining.JoinRoomTask @@ -62,6 +63,7 @@ internal class DefaultRoomService @Inject constructor( @SessionDatabase private val monarchy: Monarchy, private val createRoomTask: CreateRoomTask, private val createLocalRoomTask: CreateLocalRoomTask, + private val deleteLocalRoomTask: DeleteLocalRoomTask, private val joinRoomTask: JoinRoomTask, private val markAllRoomsReadTask: MarkAllRoomsReadTask, private val updateBreadcrumbsTask: UpdateBreadcrumbsTask, @@ -84,6 +86,10 @@ internal class DefaultRoomService @Inject constructor( return createLocalRoomTask.execute(createRoomParams) } + override suspend fun deleteLocalRoom(roomId: String) { + deleteLocalRoomTask.execute(DeleteLocalRoomTask.Params(roomId)) + } + override fun getRoom(roomId: String): Room? { return roomGetter.getRoom(roomId) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt index bb92287ead..556e31356e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt @@ -47,6 +47,8 @@ import org.matrix.android.sdk.internal.session.room.create.CreateLocalRoomTask import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask import org.matrix.android.sdk.internal.session.room.create.DefaultCreateLocalRoomTask import org.matrix.android.sdk.internal.session.room.create.DefaultCreateRoomTask +import org.matrix.android.sdk.internal.session.room.delete.DefaultDeleteLocalRoomTask +import org.matrix.android.sdk.internal.session.room.delete.DeleteLocalRoomTask import org.matrix.android.sdk.internal.session.room.directory.DefaultGetPublicRoomTask import org.matrix.android.sdk.internal.session.room.directory.DefaultGetRoomDirectoryVisibilityTask import org.matrix.android.sdk.internal.session.room.directory.DefaultSetRoomDirectoryVisibilityTask @@ -197,6 +199,9 @@ internal abstract class RoomModule { @Binds abstract fun bindCreateLocalRoomTask(task: DefaultCreateLocalRoomTask): CreateLocalRoomTask + @Binds + abstract fun bindDeleteLocalRoomTask(task: DefaultDeleteLocalRoomTask): DeleteLocalRoomTask + @Binds abstract fun bindGetPublicRoomTask(task: DefaultGetPublicRoomTask): GetPublicRoomTask diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/delete/DeleteLocalRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/delete/DeleteLocalRoomTask.kt new file mode 100644 index 0000000000..689fd24a97 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/delete/DeleteLocalRoomTask.kt @@ -0,0 +1,77 @@ +/* + * 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.session.room.delete + +import com.zhuinden.monarchy.Monarchy +import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho +import org.matrix.android.sdk.internal.database.model.ChunkEntity +import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity +import org.matrix.android.sdk.internal.database.model.EventEntity +import org.matrix.android.sdk.internal.database.model.RoomEntity +import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntity +import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity +import org.matrix.android.sdk.internal.database.model.TimelineEventEntity +import org.matrix.android.sdk.internal.database.query.where +import org.matrix.android.sdk.internal.database.query.whereRoomId +import org.matrix.android.sdk.internal.di.SessionDatabase +import org.matrix.android.sdk.internal.session.room.delete.DeleteLocalRoomTask.Params +import org.matrix.android.sdk.internal.task.Task +import org.matrix.android.sdk.internal.util.awaitTransaction +import timber.log.Timber +import javax.inject.Inject + +internal interface DeleteLocalRoomTask : Task { + data class Params(val roomId: String) +} + +internal class DefaultDeleteLocalRoomTask @Inject constructor( + @SessionDatabase private val monarchy: Monarchy, +) : DeleteLocalRoomTask { + + override suspend fun execute(params: Params) { + val roomId = params.roomId + + if (RoomLocalEcho.isLocalEchoId(roomId)) { + monarchy.awaitTransaction { realm -> + Timber.i("## DeleteLocalRoomTask - delete local room id $roomId") + RoomMemberSummaryEntity.where(realm, roomId = roomId).findAll() + ?.also { Timber.i("## DeleteLocalRoomTask - RoomMemberSummaryEntity - delete ${it.size} entries") } + ?.deleteAllFromRealm() + CurrentStateEventEntity.whereRoomId(realm, roomId = roomId).findAll() + ?.also { Timber.i("## DeleteLocalRoomTask - CurrentStateEventEntity - delete ${it.size} entries") } + ?.deleteAllFromRealm() + EventEntity.whereRoomId(realm, roomId = roomId).findAll() + ?.also { Timber.i("## DeleteLocalRoomTask - EventEntity - delete ${it.size} entries") } + ?.deleteAllFromRealm() + TimelineEventEntity.whereRoomId(realm, roomId = roomId).findAll() + ?.also { Timber.i("## DeleteLocalRoomTask - TimelineEventEntity - delete ${it.size} entries") } + ?.deleteAllFromRealm() + ChunkEntity.where(realm, roomId = roomId).findAll() + ?.also { Timber.i("## DeleteLocalRoomTask - RoomMemberSummaryEntity - delete ${it.size} entries") } + ?.deleteAllFromRealm() + RoomSummaryEntity.where(realm, roomId = roomId).findAll() + ?.also { Timber.i("## DeleteLocalRoomTask - RoomSummaryEntity - delete ${it.size} entries") } + ?.deleteAllFromRealm() + RoomEntity.where(realm, roomId = roomId).findAll() + ?.also { Timber.i("## DeleteLocalRoomTask - RoomEntity - delete ${it.size} entries") } + ?.deleteAllFromRealm() + } + } else { + Timber.i("## DeleteLocalRoomTask - Failed to remove room id $roomId: not a local room") + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewState.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewState.kt index 47db50d0d4..3ec7166739 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewState.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewState.kt @@ -25,6 +25,7 @@ import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary +import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho import org.matrix.android.sdk.api.session.room.sender.SenderInfo import org.matrix.android.sdk.api.session.sync.SyncRequestState import org.matrix.android.sdk.api.session.sync.SyncState @@ -103,4 +104,6 @@ data class RoomDetailViewState( fun isDm() = asyncRoomSummary()?.isDirect == true fun isThreadTimeline() = rootThreadEventId != null + + fun isLocalRoom() = RoomLocalEcho.isLocalEchoId(roomId) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt index 2b99bc67ef..0e818acec3 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt @@ -1695,31 +1695,41 @@ class TimelineFragment @Inject constructor( } private fun renderToolbar(roomSummary: RoomSummary?) { - if (!isThreadTimeLine()) { - views.includeRoomToolbar.roomToolbarContentView.isVisible = true - views.includeThreadToolbar.roomToolbarThreadConstraintLayout.isVisible = false - if (roomSummary == null) { - views.includeRoomToolbar.roomToolbarContentView.isClickable = false - } else { - views.includeRoomToolbar.roomToolbarContentView.isClickable = roomSummary.membership == Membership.JOIN - views.includeRoomToolbar.roomToolbarTitleView.text = roomSummary.displayName - avatarRenderer.render(roomSummary.toMatrixItem(), views.includeRoomToolbar.roomToolbarAvatarImageView) - val showPresence = roomSummary.isDirect - views.includeRoomToolbar.roomToolbarPresenceImageView.render(showPresence, roomSummary.directUserPresence) - val shieldView = if (showPresence) views.includeRoomToolbar.roomToolbarTitleShield else views.includeRoomToolbar.roomToolbarAvatarShield - shieldView.render(roomSummary.roomEncryptionTrustLevel) - views.includeRoomToolbar.roomToolbarPublicImageView.isVisible = roomSummary.isPublic && !roomSummary.isDirect + when { + isLocalRoom() -> { + views.includeRoomToolbar.roomToolbarContentView.isVisible = false + views.includeThreadToolbar.roomToolbarThreadConstraintLayout.isVisible = false + setupToolbar(views.roomToolbar) + .setTitle(R.string.fab_menu_create_chat) + .allowBack(useCross = true) } - } else { - views.includeRoomToolbar.roomToolbarContentView.isVisible = false - views.includeThreadToolbar.roomToolbarThreadConstraintLayout.isVisible = true - timelineArgs.threadTimelineArgs?.let { - val matrixItem = MatrixItem.RoomItem(it.roomId, it.displayName, it.avatarUrl) - avatarRenderer.render(matrixItem, views.includeThreadToolbar.roomToolbarThreadImageView) - views.includeThreadToolbar.roomToolbarThreadShieldImageView.render(it.roomEncryptionTrustLevel) - views.includeThreadToolbar.roomToolbarThreadSubtitleTextView.text = it.displayName + isThreadTimeLine() -> { + views.includeRoomToolbar.roomToolbarContentView.isVisible = false + views.includeThreadToolbar.roomToolbarThreadConstraintLayout.isVisible = true + timelineArgs.threadTimelineArgs?.let { + val matrixItem = MatrixItem.RoomItem(it.roomId, it.displayName, it.avatarUrl) + avatarRenderer.render(matrixItem, views.includeThreadToolbar.roomToolbarThreadImageView) + views.includeThreadToolbar.roomToolbarThreadShieldImageView.render(it.roomEncryptionTrustLevel) + views.includeThreadToolbar.roomToolbarThreadSubtitleTextView.text = it.displayName + } + views.includeThreadToolbar.roomToolbarThreadTitleTextView.text = resources.getText(R.string.thread_timeline_title) + } + else -> { + views.includeRoomToolbar.roomToolbarContentView.isVisible = true + views.includeThreadToolbar.roomToolbarThreadConstraintLayout.isVisible = false + if (roomSummary == null) { + views.includeRoomToolbar.roomToolbarContentView.isClickable = false + } else { + views.includeRoomToolbar.roomToolbarContentView.isClickable = roomSummary.membership == Membership.JOIN + views.includeRoomToolbar.roomToolbarTitleView.text = roomSummary.displayName + avatarRenderer.render(roomSummary.toMatrixItem(), views.includeRoomToolbar.roomToolbarAvatarImageView) + val showPresence = roomSummary.isDirect + views.includeRoomToolbar.roomToolbarPresenceImageView.render(showPresence, roomSummary.directUserPresence) + val shieldView = if (showPresence) views.includeRoomToolbar.roomToolbarTitleShield else views.includeRoomToolbar.roomToolbarAvatarShield + shieldView.render(roomSummary.roomEncryptionTrustLevel) + views.includeRoomToolbar.roomToolbarPublicImageView.isVisible = roomSummary.isPublic && !roomSummary.isDirect + } } - views.includeThreadToolbar.roomToolbarThreadTitleTextView.text = resources.getText(R.string.thread_timeline_title) } } @@ -2658,6 +2668,11 @@ class TimelineFragment @Inject constructor( */ private fun isThreadTimeLine(): Boolean = timelineArgs.threadTimelineArgs?.rootThreadEventId != null + /** + * Returns true if the current room is a local room, false otherwise. + */ + private fun isLocalRoom(): Boolean = withState(timelineViewModel) { it.isLocalRoom() } + /** * Returns the root thread event if we are in a thread room, otherwise returns null. */ diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt index 07b20b4914..6ad356e82d 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt @@ -732,26 +732,30 @@ class TimelineViewModel @AssistedInject constructor( return@withState false } - if (initialState.isThreadTimeline()) { - when (itemId) { - R.id.menu_thread_timeline_view_in_room, - R.id.menu_thread_timeline_copy_link, - R.id.menu_thread_timeline_share -> true - else -> false + when { + initialState.isLocalRoom() -> false + initialState.isThreadTimeline() -> { + when (itemId) { + R.id.menu_thread_timeline_view_in_room, + R.id.menu_thread_timeline_copy_link, + R.id.menu_thread_timeline_share -> true + else -> false + } } - } else { - when (itemId) { - R.id.timeline_setting -> true - R.id.invite -> state.canInvite - R.id.open_matrix_apps -> true - R.id.voice_call -> state.isCallOptionAvailable() - R.id.video_call -> state.isCallOptionAvailable() || state.jitsiState.confId == null || state.jitsiState.hasJoined - // Show Join conference button only if there is an active conf id not joined. Otherwise fallback to default video disabled. ^ - R.id.join_conference -> !state.isCallOptionAvailable() && state.jitsiState.confId != null && !state.jitsiState.hasJoined - R.id.search -> state.isSearchAvailable() - R.id.menu_timeline_thread_list -> vectorPreferences.areThreadMessagesEnabled() - R.id.dev_tools -> vectorPreferences.developerMode() - else -> false + else -> { + when (itemId) { + R.id.timeline_setting -> true + R.id.invite -> state.canInvite + R.id.open_matrix_apps -> true + R.id.voice_call -> state.isCallOptionAvailable() + R.id.video_call -> state.isCallOptionAvailable() || state.jitsiState.confId == null || state.jitsiState.hasJoined + // Show Join conference button only if there is an active conf id not joined. Otherwise fallback to default video disabled. ^ + R.id.join_conference -> !state.isCallOptionAvailable() && state.jitsiState.confId != null && !state.jitsiState.hasJoined + R.id.search -> state.isSearchAvailable() + R.id.menu_timeline_thread_list -> vectorPreferences.areThreadMessagesEnabled() + R.id.dev_tools -> vectorPreferences.developerMode() + else -> false + } } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt index 5539986118..c25fe546c3 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt @@ -146,6 +146,10 @@ class RoomListFragment @Inject constructor( (it.contentEpoxyController as? RoomSummaryPagedController)?.roomChangeMembershipStates = ms } } + roomListViewModel.onEach(RoomListViewState::localRoomIds) { + // Local rooms should not exist anymore when the room list is shown + roomListViewModel.deleteLocalRooms(it) + } } private fun refreshCollapseStates() { diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt index 49467c0531..cd4bb06949 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt @@ -48,7 +48,10 @@ import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.getRoomSummary import org.matrix.android.sdk.api.session.room.UpdatableLivePageResult import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState +import org.matrix.android.sdk.api.session.room.model.Membership +import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho import org.matrix.android.sdk.api.session.room.model.tag.RoomTag +import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams import org.matrix.android.sdk.api.session.room.state.isPublic import org.matrix.android.sdk.api.util.toMatrixItem import org.matrix.android.sdk.flow.flow @@ -96,6 +99,7 @@ class RoomListViewModel @AssistedInject constructor( init { observeMembershipChanges() + observeLocalRooms() appStateHandler.selectedRoomGroupingFlow .distinctUntilChanged() @@ -123,6 +127,23 @@ class RoomListViewModel @AssistedInject constructor( } } + private fun observeLocalRooms() { + val queryParams = roomSummaryQueryParams { + memberships = listOf(Membership.JOIN) + } + session + .flow() + .liveRoomSummaries(queryParams) + .map { roomSummaries -> + roomSummaries.mapNotNull { summary -> + summary.roomId.takeIf { RoomLocalEcho.isLocalEchoId(it) } + }.toSet() + } + .setOnEach { roomIds -> + copy(localRoomIds = roomIds) + } + } + companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() private val roomListSectionBuilder = if (appStateHandler.getCurrentRoomGroupingMethod() is RoomGroupingMethod.BySpace) { @@ -173,6 +194,14 @@ class RoomListViewModel @AssistedInject constructor( return session.getRoom(roomId)?.stateService()?.isPublic().orFalse() } + fun deleteLocalRooms(roomsIds: Set) { + viewModelScope.launch { + roomsIds.forEach { + session.roomService().deleteLocalRoom(it) + } + } + } + // PRIVATE METHODS ***************************************************************************** private fun handleSelectRoom(action: RoomListAction.SelectRoom) = withState { diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewState.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewState.kt index 46ff6c242b..9d386b679a 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewState.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewState.kt @@ -30,7 +30,8 @@ data class RoomListViewState( val roomMembershipChanges: Map = emptyMap(), val asyncSuggestedRooms: Async> = Uninitialized, val currentUserName: String? = null, - val currentRoomGrouping: Async = Uninitialized + val currentRoomGrouping: Async = Uninitialized, + val localRoomIds: Set = emptySet() ) : MavericksState { constructor(args: RoomListParams) : this(displayMode = args.displayMode) From e86f9193dd61c08c80dffb8aea354bbeba2a1029 Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Fri, 13 May 2022 18:09:39 +0200 Subject: [PATCH 006/131] Display timeline from the top of the screen for local rooms --- .../app/features/home/room/detail/TimelineFragment.kt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt index 0e818acec3..a3d342ef48 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt @@ -1426,6 +1426,9 @@ class TimelineFragment @Inject constructor( updateJumpToReadMarkerViewVisibility() jumpToBottomViewVisibilityManager.maybeShowJumpToBottomViewVisibilityWithDelay() } + }.apply { + // For local rooms, pin the view's content to the top edge (the layout is reversed) + stackFromEnd = isLocalRoom() } val stateRestorer = LayoutManagerStateRestorer(layoutManager).register() scrollOnNewMessageCallback = ScrollOnNewMessageCallback(layoutManager, timelineEventController) @@ -1696,14 +1699,14 @@ class TimelineFragment @Inject constructor( private fun renderToolbar(roomSummary: RoomSummary?) { when { - isLocalRoom() -> { + isLocalRoom() -> { views.includeRoomToolbar.roomToolbarContentView.isVisible = false views.includeThreadToolbar.roomToolbarThreadConstraintLayout.isVisible = false setupToolbar(views.roomToolbar) .setTitle(R.string.fab_menu_create_chat) .allowBack(useCross = true) } - isThreadTimeLine() -> { + isThreadTimeLine() -> { views.includeRoomToolbar.roomToolbarContentView.isVisible = false views.includeThreadToolbar.roomToolbarThreadConstraintLayout.isVisible = true timelineArgs.threadTimelineArgs?.let { @@ -1714,7 +1717,7 @@ class TimelineFragment @Inject constructor( } views.includeThreadToolbar.roomToolbarThreadTitleTextView.text = resources.getText(R.string.thread_timeline_title) } - else -> { + else -> { views.includeRoomToolbar.roomToolbarContentView.isVisible = true views.includeThreadToolbar.roomToolbarThreadConstraintLayout.isVisible = false if (roomSummary == null) { From b144bac578c721e2593d6f02556657d7fad7503c Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Fri, 13 May 2022 13:56:56 +0200 Subject: [PATCH 007/131] Update wordings for local room timeline --- .../timeline/factory/EncryptionItemFactory.kt | 16 +++++-- .../factory/MergedHeaderItemFactory.kt | 2 + .../detail/timeline/item/BasedMergedItem.kt | 1 + .../timeline/item/MergedRoomCreationItem.kt | 45 +++++++++++++------ vector/src/main/res/values/strings.xml | 4 +- 5 files changed, 50 insertions(+), 18 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt index dd058197b4..5f32696334 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt @@ -30,6 +30,7 @@ import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.getRoomSummary +import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho import javax.inject.Inject class EncryptionItemFactory @Inject constructor( @@ -55,12 +56,19 @@ class EncryptionItemFactory @Inject constructor( val description: String val shield: StatusTileTimelineItem.ShieldUIState if (isSafeAlgorithm) { + val isDirect = session.getRoomSummary(event.root.roomId.orEmpty())?.isDirect.orFalse() title = stringProvider.getString(R.string.encryption_enabled) description = stringProvider.getString( - if (session.getRoomSummary(event.root.roomId ?: "")?.isDirect.orFalse()) { - R.string.direct_room_encryption_enabled_tile_description - } else { - R.string.encryption_enabled_tile_description + when { + isDirect && RoomLocalEcho.isLocalEchoId(event.root.roomId.orEmpty()) -> { + R.string.direct_room_encryption_enabled_tile_description_future + } + isDirect -> { + R.string.direct_room_encryption_enabled_tile_description + } + else -> { + R.string.encryption_enabled_tile_description + } } ) shield = StatusTileTimelineItem.ShieldUIState.BLACK diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt index 771e42b63c..800fc27e77 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt @@ -117,6 +117,7 @@ class MergedHeaderItemFactory @Inject constructor( highlighted = true } val data = BasedMergedItem.Data( + roomId = mergedEvent.root.roomId, userId = mergedEvent.root.senderId ?: "", avatarUrl = mergedEvent.senderInfo.avatarUrl, memberName = mergedEvent.senderInfo.disambiguatedDisplayName, @@ -199,6 +200,7 @@ class MergedHeaderItemFactory @Inject constructor( highlighted = true } val data = BasedMergedItem.Data( + roomId = mergedEvent.root.roomId, userId = mergedEvent.root.senderId ?: "", avatarUrl = mergedEvent.senderInfo.avatarUrl, memberName = mergedEvent.senderInfo.disambiguatedDisplayName, diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/BasedMergedItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/BasedMergedItem.kt index 1c56a0809e..4999036e9d 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/BasedMergedItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/BasedMergedItem.kt @@ -54,6 +54,7 @@ abstract class BasedMergedItem : BaseEventItem() } data class Data( + val roomId: String?, val localId: Long, val eventId: String, val userId: String, diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt index f41c17d9e7..5b8d973a04 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt @@ -40,6 +40,7 @@ import im.vector.app.features.home.room.detail.timeline.TimelineEventController import im.vector.app.features.home.room.detail.timeline.tools.linkify import me.gujun.android.span.span import org.matrix.android.sdk.api.session.room.model.RoomSummary +import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho import org.matrix.android.sdk.api.util.toMatrixItem @EpoxyModelClass(layout = R.layout.item_timeline_event_base_noinfo) @@ -102,10 +103,16 @@ abstract class MergedRoomCreationItem : BasedMergedItem { + holder.expandView.resources.getString(R.string.direct_room_encryption_enabled_tile_description_future) + } + data?.isDirectRoom == true -> { + holder.expandView.resources.getString(R.string.direct_room_encryption_enabled_tile_description) + } + else -> { + holder.expandView.resources.getString(R.string.encryption_enabled_tile_description) + } } holder.e2eTitleDescriptionView.textAlignment = View.TEXT_ALIGNMENT_CENTER holder.e2eTitleTextView.setCompoundDrawablesWithIntrinsicBounds( @@ -130,17 +137,29 @@ abstract class MergedRoomCreationItem : BasedMergedItem { + if (isLocalRoom) { + holder.roomDescriptionText.text = holder.view.resources.getString( + R.string.send_your_first_msg_to_invite, + roomSummary?.displayName.orEmpty() + ) + } else { + holder.roomDescriptionText.text = holder.view.resources.getString( + R.string.this_is_the_beginning_of_dm, + roomSummary?.displayName.orEmpty() + ) + } + } + roomDisplayName.isNullOrBlank() || roomSummary.name.isBlank() -> { + holder.roomDescriptionText.text = holder.view.resources.getString(R.string.this_is_the_beginning_of_room_no_name) + } + else -> { + holder.roomDescriptionText.text = holder.view.resources.getString(R.string.this_is_the_beginning_of_room, roomDisplayName) + } } val topic = roomSummary?.topic diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index b507ed473f..f684ccadad 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -2399,7 +2399,8 @@ Encryption enabled Messages in this room are end-to-end encrypted. Learn more & verify users in their profile. - Messages in this room are end-to-end encrypted. + Messages in this chat are end-to-end encrypted. + Messages in this chat will be end-to-end encrypted. Encryption not enabled Encryption is misconfigured The encryption used by this room is not supported @@ -2411,6 +2412,7 @@ This is the beginning of %s. This is the beginning of this conversation. This is the beginning of your direct message history with %s. + Send your first message to invite %s to chat %s to let people know what this room is about. Add a topic From a46d7ed8dd17064abde7e78ec1a16baddfd90f5b Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Fri, 13 May 2022 17:48:30 +0200 Subject: [PATCH 008/131] Hide unwanted events from local room timeline --- .../detail/timeline/TimelineEventController.kt | 15 +++++++++------ .../helper/TimelineEventVisibilityHelper.kt | 8 ++++++++ .../timeline/item/MergedRoomCreationItem.kt | 6 ++++++ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt index a02eaa3202..6ef4b21387 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt @@ -69,6 +69,7 @@ import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.ReadReceipt import org.matrix.android.sdk.api.session.room.model.RoomMemberContent import org.matrix.android.sdk.api.session.room.model.RoomSummary +import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent import org.matrix.android.sdk.api.session.room.model.message.MessageImageInfoContent import org.matrix.android.sdk.api.session.room.model.message.MessageVideoContent @@ -603,12 +604,14 @@ class TimelineEventController @Inject constructor( } private fun wantsDateSeparator(event: TimelineEvent, nextEvent: TimelineEvent?): Boolean { - return if (hasReachedInvite && hasUTD) { - true - } else { - val date = event.root.localDateTime() - val nextDate = nextEvent?.root?.localDateTime() - date.toLocalDate() != nextDate?.toLocalDate() + return when { + RoomLocalEcho.isLocalEchoId(partialState.roomSummary?.roomId.orEmpty()) -> false + hasReachedInvite && hasUTD -> true + else -> { + val date = event.root.localDateTime() + val nextDate = nextEvent?.root?.localDateTime() + date.toLocalDate() != nextDate?.toLocalDate() + } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineEventVisibilityHelper.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineEventVisibilityHelper.kt index e4e0ea8352..488aebde13 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineEventVisibilityHelper.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineEventVisibilityHelper.kt @@ -26,6 +26,7 @@ import org.matrix.android.sdk.api.session.events.model.isThread import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomMemberContent +import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import javax.inject.Inject @@ -176,6 +177,13 @@ class TimelineEventVisibilityHelper @Inject constructor(private val userPreferen return true } + // Hide fake events for local rooms + if (RoomLocalEcho.isLocalEchoId(roomId) && + root.getClearType() == EventType.STATE_ROOM_MEMBER || + root.getClearType() == EventType.STATE_ROOM_HISTORY_VISIBILITY) { + return true + } + // Allow only the the threads within the rootThreadEventId along with the root event if (userPreferencesProvider.areThreadMessagesEnabled() && isFromThreadTimeline) { return if (root.getRootThreadEventId() == rootThreadEventId) { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt index 5b8d973a04..5b7c4efc7f 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt @@ -58,7 +58,12 @@ abstract class MergedRoomCreationItem : BasedMergedItem(R.id.mergedSumContainer) val summaryView by bind(R.id.itemNoticeTextView) val avatarView by bind(R.id.itemNoticeAvatarView) val encryptionTile by bind(R.id.creationEncryptionTile) From 554d35fe96712e0faa64f5e83e66ff7a649cbf10 Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Sat, 21 May 2022 00:18:27 +0200 Subject: [PATCH 009/131] Add changelog --- changelog.d/5525.wip | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/5525.wip diff --git a/changelog.d/5525.wip b/changelog.d/5525.wip new file mode 100644 index 0000000000..c4ac0ff008 --- /dev/null +++ b/changelog.d/5525.wip @@ -0,0 +1 @@ +Create DM room only on first message - Design implementation & debug feature flag From 398e98ae85a387eead479b695bf800fa65352fa3 Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Tue, 24 May 2022 00:32:16 +0200 Subject: [PATCH 010/131] Remove useless variable --- .../sdk/internal/session/room/create/CreateLocalRoomTask.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt index e650039d75..1fa2cfe35b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt @@ -149,7 +149,6 @@ internal class DefaultCreateLocalRoomTask @Inject constructor( } val eventList = createLocalRoomEvents(createRoomBody) - val eventIds = ArrayList(eventList.size) val roomMemberContentsByUser = HashMap() for (event in eventList) { @@ -157,8 +156,6 @@ internal class DefaultCreateLocalRoomTask @Inject constructor( continue } - eventIds.add(event.eventId) - val eventEntity = event.toEntity(roomId, SendState.SYNCED, null).copyToRealmOrIgnore(realm, EventInsertType.INCREMENTAL_SYNC) if (event.stateKey != null) { CurrentStateEventEntity.getOrCreate(realm, roomId, event.stateKey, event.type).apply { From d42a3da5b7b5dc664fd0f01f847fe5f0d013f07c Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Tue, 14 Jun 2022 15:16:17 +0200 Subject: [PATCH 011/131] Reduce code smell --- .../timeline/item/MergedRoomCreationItem.kt | 82 +++++++++++-------- 1 file changed, 46 insertions(+), 36 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt index 5b7c4efc7f..cd60057379 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt @@ -16,6 +16,7 @@ package im.vector.app.features.home.room.detail.timeline.item +import android.content.res.Resources import android.text.SpannableString import android.text.method.MovementMethod import android.text.style.ClickableSpan @@ -25,7 +26,6 @@ import android.widget.ImageView import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.ContextCompat -import androidx.core.view.isGone import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams import com.airbnb.epoxy.EpoxyAttribute @@ -39,6 +39,7 @@ import im.vector.app.features.home.room.detail.RoomDetailAction import im.vector.app.features.home.room.detail.timeline.TimelineEventController import im.vector.app.features.home.room.detail.timeline.tools.linkify import me.gujun.android.span.span +import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho import org.matrix.android.sdk.api.util.toMatrixItem @@ -62,44 +63,45 @@ abstract class MergedRoomCreationItem : BasedMergedItem { - holder.expandView.resources.getString(R.string.direct_room_encryption_enabled_tile_description_future) - } - data?.isDirectRoom == true -> { - holder.expandView.resources.getString(R.string.direct_room_encryption_enabled_tile_description) - } - else -> { - holder.expandView.resources.getString(R.string.encryption_enabled_tile_description) - } - } + holder.e2eTitleDescriptionView.text = getE2ESecureDescriptionText(holder.expandView.resources, data) holder.e2eTitleDescriptionView.textAlignment = View.TEXT_ALIGNMENT_CENTER holder.e2eTitleTextView.setCompoundDrawablesWithIntrinsicBounds( ContextCompat.getDrawable(holder.view.context, R.drawable.ic_shield_black), @@ -137,17 +129,32 @@ abstract class MergedRoomCreationItem : BasedMergedItem { + if (attributes.isLocalRoom) { + resources.getString(R.string.direct_room_encryption_enabled_tile_description_future) + } else { + resources.getString(R.string.direct_room_encryption_enabled_tile_description) + } + } + else -> { + resources.getString(R.string.encryption_enabled_tile_description) + } + } + } + private fun bindCreationSummaryTile(holder: Holder) { val roomSummary = attributes.roomSummary val roomDisplayName = roomSummary?.displayName holder.roomNameText.setTextOrHide(roomDisplayName) val isDirect = roomSummary?.isDirect == true - val isLocalRoom = RoomLocalEcho.isLocalEchoId(roomSummary?.roomId.orEmpty()) val membersCount = roomSummary?.otherMemberIds?.size ?: 0 when { isDirect -> { - if (isLocalRoom) { + if (attributes.isLocalRoom) { holder.roomDescriptionText.text = holder.view.resources.getString( R.string.send_your_first_msg_to_invite, roomSummary?.displayName.orEmpty() @@ -261,5 +268,8 @@ abstract class MergedRoomCreationItem : BasedMergedItem Date: Wed, 29 Jun 2022 23:10:12 +0000 Subject: [PATCH 012/131] Bump lifecycle from 2.4.1 to 2.5.0 Bumps `lifecycle` from 2.4.1 to 2.5.0. Updates `lifecycle-common` from 2.4.1 to 2.5.0 Updates `lifecycle-livedata-ktx` from 2.4.1 to 2.5.0 Updates `lifecycle-process` from 2.4.1 to 2.5.0 Updates `lifecycle-runtime-ktx` from 2.4.1 to 2.5.0 --- updated-dependencies: - dependency-name: androidx.lifecycle:lifecycle-common dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: androidx.lifecycle:lifecycle-livedata-ktx dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: androidx.lifecycle:lifecycle-process dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: androidx.lifecycle:lifecycle-runtime-ktx dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index db9278b975..90595e61f6 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -19,7 +19,7 @@ def retrofit = "2.9.0" def arrow = "0.8.2" def markwon = "4.6.2" def moshi = "1.13.0" -def lifecycle = "2.4.1" +def lifecycle = "2.5.0" def flowBinding = "1.2.0" def flipper = "0.151.1" def epoxy = "4.6.2" From 71320e42d0a750bfe6357f3aa334b6d593b0642c Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Fri, 1 Jul 2022 09:33:21 +0200 Subject: [PATCH 013/131] Show date separator in local room timeline --- .../home/room/detail/timeline/TimelineEventController.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt index 6ef4b21387..5b81b327aa 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt @@ -605,7 +605,6 @@ class TimelineEventController @Inject constructor( private fun wantsDateSeparator(event: TimelineEvent, nextEvent: TimelineEvent?): Boolean { return when { - RoomLocalEcho.isLocalEchoId(partialState.roomSummary?.roomId.orEmpty()) -> false hasReachedInvite && hasUTD -> true else -> { val date = event.root.localDateTime() From c7db89613c40add99d8b88242e5817e158997582 Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Thu, 30 Jun 2022 15:24:42 +0200 Subject: [PATCH 014/131] Split code in MergedRoomCreationItem --- .../timeline/item/MergedRoomCreationItem.kt | 168 ++++++++++-------- 1 file changed, 93 insertions(+), 75 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt index 6371440d1a..b5c24a4480 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt @@ -16,7 +16,6 @@ package im.vector.app.features.home.room.detail.timeline.item -import android.content.res.Resources import android.text.SpannableString import android.text.method.MovementMethod import android.text.style.ClickableSpan @@ -39,7 +38,6 @@ import im.vector.app.features.home.room.detail.RoomDetailAction import im.vector.app.features.home.room.detail.timeline.TimelineEventController import im.vector.app.features.home.room.detail.timeline.tools.linkify import me.gujun.android.span.span -import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho import org.matrix.android.sdk.api.util.toMatrixItem @@ -53,6 +51,14 @@ abstract class MergedRoomCreationItem : BasedMergedItem { this.marginEnd = leftGuideline } if (attributes.isEncryptionAlgorithmSecure) { - holder.e2eTitleTextView.text = holder.expandView.resources.getString(R.string.encryption_enabled) - holder.e2eTitleDescriptionView.text = getE2ESecureDescriptionText(holder.expandView.resources, data) - holder.e2eTitleDescriptionView.textAlignment = View.TEXT_ALIGNMENT_CENTER - holder.e2eTitleTextView.setCompoundDrawablesWithIntrinsicBounds( - ContextCompat.getDrawable(holder.view.context, R.drawable.ic_shield_black), - null, null, null - ) + renderE2ESecureTile(holder) } else { - holder.e2eTitleTextView.text = holder.expandView.resources.getString(R.string.encryption_not_enabled) - holder.e2eTitleDescriptionView.text = holder.expandView.resources.getString(R.string.encryption_unknown_algorithm_tile_description) - holder.e2eTitleTextView.setCompoundDrawablesWithIntrinsicBounds( - ContextCompat.getDrawable(holder.view.context, R.drawable.ic_shield_warning), - null, null, null - ) + renderE2EUnsecureTile(holder) } } else { holder.encryptionTile.isVisible = false } } - private fun getE2ESecureDescriptionText(resources: Resources, data: Data?): String { - val isDirectRoom = data?.isDirectRoom.orFalse() - return when { + private fun renderE2ESecureTile(holder: Holder) { + val resources = holder.expandView.resources + val description = when { isDirectRoom -> { if (attributes.isLocalRoom) { resources.getString(R.string.direct_room_encryption_enabled_tile_description_future) @@ -143,65 +138,36 @@ abstract class MergedRoomCreationItem : BasedMergedItem { - if (attributes.isLocalRoom) { - holder.roomDescriptionText.text = holder.view.resources.getString( - R.string.send_your_first_msg_to_invite, - roomSummary?.displayName.orEmpty() - ) - } else { - holder.roomDescriptionText.text = holder.view.resources.getString( - R.string.this_is_the_beginning_of_dm, - roomSummary?.displayName.orEmpty() - ) - } - } - roomDisplayName.isNullOrBlank() || roomSummary.name.isBlank() -> { - holder.roomDescriptionText.text = holder.view.resources.getString(R.string.this_is_the_beginning_of_room_no_name) - } - else -> { - holder.roomDescriptionText.text = holder.view.resources.getString(R.string.this_is_the_beginning_of_room, roomDisplayName) - } - } - - val topic = roomSummary?.topic - if (topic.isNullOrBlank()) { - // do not show hint for DMs or group DMs - val canSetTopic = attributes.canChangeTopic && !isDirect - if (canSetTopic) { - val addTopicLink = holder.view.resources.getString(R.string.add_a_topic_link_text) - val styledText = SpannableString(holder.view.resources.getString(R.string.room_created_summary_no_topic_creation_text, addTopicLink)) - holder.roomTopicText.setTextOrHide(styledText.tappableMatchingText(addTopicLink, object : ClickableSpan() { - override fun onClick(widget: View) { - attributes.callback?.onTimelineItemAction(RoomDetailAction.QuickActionSetTopic) - } - })) - } - } else { - holder.roomTopicText.setTextOrHide( - span { - span(holder.view.resources.getString(R.string.topic_prefix)) { - textStyle = "bold" - } - +topic.linkify(attributes.callback) - } - ) - } - holder.roomTopicText.movementMethod = movementMethod + holder.roomNameText.setTextOrHide(roomDisplayName) + renderRoomDescription(holder) + renderRoomTopic(holder) val roomItem = roomSummary?.toMatrixItem() val shouldSetAvatar = attributes.canChangeAvatar && - (roomSummary?.isDirect == false || (isDirect && membersCount >= 2)) && + (roomSummary?.isDirect == false || (isDirectRoom && membersCount >= 2)) && roomItem?.avatarUrl.isNullOrBlank() holder.roomAvatarImageView.isVisible = roomItem != null @@ -224,7 +190,7 @@ abstract class MergedRoomCreationItem : BasedMergedItem { + if (attributes.isLocalRoom) { + holder.roomDescriptionText.text = holder.view.resources.getString( + R.string.send_your_first_msg_to_invite, + roomSummary?.displayName.orEmpty() + ) + } else { + holder.roomDescriptionText.text = holder.view.resources.getString( + R.string.this_is_the_beginning_of_dm, + roomSummary?.displayName.orEmpty() + ) + } + } + roomDisplayName.isNullOrBlank() || roomSummary?.name.isNullOrBlank() -> { + holder.roomDescriptionText.text = holder.view.resources.getString(R.string.this_is_the_beginning_of_room_no_name) + } + else -> { + holder.roomDescriptionText.text = holder.view.resources.getString(R.string.this_is_the_beginning_of_room, roomDisplayName) + } + } + } + + private fun renderRoomTopic(holder: Holder) { + val topic = roomSummary?.topic + if (topic.isNullOrBlank()) { + // do not show hint for DMs or group DMs + val canSetTopic = attributes.canChangeTopic && !isDirectRoom + if (canSetTopic) { + val addTopicLink = holder.view.resources.getString(R.string.add_a_topic_link_text) + val styledText = SpannableString(holder.view.resources.getString(R.string.room_created_summary_no_topic_creation_text, addTopicLink)) + holder.roomTopicText.setTextOrHide(styledText.tappableMatchingText(addTopicLink, object : ClickableSpan() { + override fun onClick(widget: View) { + attributes.callback?.onTimelineItemAction(RoomDetailAction.QuickActionSetTopic) + } + })) + } + } else { + holder.roomTopicText.setTextOrHide( + span { + span(holder.view.resources.getString(R.string.topic_prefix)) { + textStyle = "bold" + } + +topic.linkify(attributes.callback) + } + ) + } + holder.roomTopicText.movementMethod = movementMethod + } + class Holder : BasedMergedItem.Holder(STUB_ID) { val mergedView by bind(R.id.mergedSumContainer) val summaryView by bind(R.id.itemNoticeTextView) From 7415623c2fae0fce46e4f6c6c9616dadc5ae7513 Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Fri, 1 Jul 2022 00:19:41 +0200 Subject: [PATCH 015/131] Update room description style --- .../timeline/item/MergedRoomCreationItem.kt | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt index b5c24a4480..47401c34e7 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt @@ -27,6 +27,7 @@ import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.ContextCompat import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams +import androidx.core.widget.TextViewCompat import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R @@ -37,6 +38,7 @@ import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.detail.RoomDetailAction import im.vector.app.features.home.room.detail.timeline.TimelineEventController import im.vector.app.features.home.room.detail.timeline.tools.linkify +import im.vector.app.features.themes.ThemeUtils import me.gujun.android.span.span import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho @@ -201,27 +203,27 @@ abstract class MergedRoomCreationItem : BasedMergedItem { if (attributes.isLocalRoom) { - holder.roomDescriptionText.text = holder.view.resources.getString( - R.string.send_your_first_msg_to_invite, - roomSummary?.displayName.orEmpty() - ) + resources.getString(R.string.send_your_first_msg_to_invite, roomSummary?.displayName.orEmpty()) } else { - holder.roomDescriptionText.text = holder.view.resources.getString( - R.string.this_is_the_beginning_of_dm, - roomSummary?.displayName.orEmpty() - ) + resources.getString(R.string.this_is_the_beginning_of_dm, roomSummary?.displayName.orEmpty()) } } roomDisplayName.isNullOrBlank() || roomSummary?.name.isNullOrBlank() -> { - holder.roomDescriptionText.text = holder.view.resources.getString(R.string.this_is_the_beginning_of_room_no_name) + holder.view.resources.getString(R.string.this_is_the_beginning_of_room_no_name) } else -> { - holder.roomDescriptionText.text = holder.view.resources.getString(R.string.this_is_the_beginning_of_room, roomDisplayName) + holder.view.resources.getString(R.string.this_is_the_beginning_of_room, roomDisplayName) } } + holder.roomDescriptionText.text = description + if (isDirectRoom && attributes.isLocalRoom) { + TextViewCompat.setTextAppearance(holder.roomDescriptionText, R.style.TextAppearance_Vector_Subtitle) + holder.roomDescriptionText.setTextColor(ThemeUtils.getColor(holder.roomDescriptionText.context, R.attr.vctr_content_primary)) + } } private fun renderRoomTopic(holder: Holder) { From 0dad4cb02a111de71f9970b9103f00fd80b73394 Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Fri, 1 Jul 2022 09:57:45 +0200 Subject: [PATCH 016/131] Set current ts for local events age --- .../sdk/internal/session/room/create/CreateLocalRoomTask.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt index 1fa2cfe35b..811d7ef5b6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt @@ -156,7 +156,8 @@ internal class DefaultCreateLocalRoomTask @Inject constructor( continue } - val eventEntity = event.toEntity(roomId, SendState.SYNCED, null).copyToRealmOrIgnore(realm, EventInsertType.INCREMENTAL_SYNC) + val now = clock.epochMillis() + val eventEntity = event.toEntity(roomId, SendState.SYNCED, now).copyToRealmOrIgnore(realm, EventInsertType.INCREMENTAL_SYNC) if (event.stateKey != null) { CurrentStateEventEntity.getOrCreate(realm, roomId, event.stateKey, event.type).apply { eventId = event.eventId From c25edfada40ec2f7ae8358a2437f158497df7739 Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Fri, 1 Jul 2022 10:09:26 +0200 Subject: [PATCH 017/131] Remove unused imports --- .../home/room/detail/timeline/TimelineEventController.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt index 5b81b327aa..18c626bda8 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt @@ -69,7 +69,6 @@ import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.ReadReceipt import org.matrix.android.sdk.api.session.room.model.RoomMemberContent import org.matrix.android.sdk.api.session.room.model.RoomSummary -import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent import org.matrix.android.sdk.api.session.room.model.message.MessageImageInfoContent import org.matrix.android.sdk.api.session.room.model.message.MessageVideoContent @@ -605,8 +604,8 @@ class TimelineEventController @Inject constructor( private fun wantsDateSeparator(event: TimelineEvent, nextEvent: TimelineEvent?): Boolean { return when { - hasReachedInvite && hasUTD -> true - else -> { + hasReachedInvite && hasUTD -> true + else -> { val date = event.root.localDateTime() val nextDate = nextEvent?.root?.localDateTime() date.toLocalDate() != nextDate?.toLocalDate() From 6c2574c99e4a59466a41806ba93711d96dce5eca Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Thu, 30 Jun 2022 17:20:46 +0000 Subject: [PATCH 018/131] Translated using Weblate (Czech) Currently translated at 100.0% (2260 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/cs/ --- vector/src/main/res/values-cs/strings.xml | 33 ++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/vector/src/main/res/values-cs/strings.xml b/vector/src/main/res/values-cs/strings.xml index 7077c79192..e2cce2f2cc 100644 --- a/vector/src/main/res/values-cs/strings.xml +++ b/vector/src/main/res/values-cs/strings.xml @@ -2547,4 +2547,35 @@ sek min h - + Povolit sdílení polohy živě + Upozornění: jedná se o experimetnální funkci s dočasnou implementací. To znamená, že nebudete moci odstranit historii své polohy a pokročilí uživatelé budou moci vidět historii vaší polohy i poté, co přestanete sdílet svou polohu živě v této místnosti. + Sdílení polohy živě + Aktuální brána: %s + Brána + Nelze najít koncový bod. + Aktuální koncový bod: %s + Koncový bod + Aktuálně se používá %s. + + Nalezen %d způsob. + Nalezeny %d způsoby. + Nalezeno %d způsobů. + + Způsob + Nebyl nalezen jiný způsob než synchronizace na pozadí. + Žádný jiný způsob než služba Google Play nebyl nalezen. + Dostupné způsoby + Způsob oznamování + Synchronizace na pozadí + Služby Google + Výběr způsobu přijímání oznámení + Nepodařilo se zapnout biometrické ověřování. + Biometrické ověřování bylo vypnuto, protože nedávno byla přidána nová metoda biometrického ověřování. Můžete ho znovu povolit v Nastavení. + Obnovit metodu oznamování + Značka profilu: + Nepodařilo se zaregistrovat token koncového bodu na domovském serveru: +\n%1$s + Koncový bod byl úspěšně zaregistrován na domovském serveru. + Registrace koncového bodu + Další + \ No newline at end of file From 6dbdc34f0f62a9fa1665597adfc766708a3e13fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Thu, 30 Jun 2022 17:15:05 +0000 Subject: [PATCH 019/131] Translated using Weblate (Estonian) Currently translated at 99.2% (2242 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/et/ --- vector/src/main/res/values-et/strings.xml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/vector/src/main/res/values-et/strings.xml b/vector/src/main/res/values-et/strings.xml index bf2f1d62c7..fdb4506142 100644 --- a/vector/src/main/res/values-et/strings.xml +++ b/vector/src/main/res/values-et/strings.xml @@ -2500,4 +2500,12 @@ sek min t - + Luba asukohta jagada + Palun arvesta järgnevaga: see katseline funktsionaalsus kasutab ajutist lahendust. See tähendab, et sa ei saa oma asukoha jagamise ajalugu kustutada ning heade arvutioskustega kasutajad saavad näha sinu asukohta ka siis, kui sa oled oma asukoha jagamise selles jututoas lõpetanud. + Asukoha jagamine reaalajas + Biomeetrilise autentimise kasutuselevõtmine ei õnnestunud. + Kuna hiljuti lisandus uus biomeetrilise autentimise meetod, siis lülitati biomeetriline autentimine välja. Sa saad ta uuesti kasutusele võtta seadistustest. + Lähtesta teavituse meetod + Profiili silt: + Järgmine + \ No newline at end of file From 61d8af62d5833a7c400b6db5e61e3f1238ae83a5 Mon Sep 17 00:00:00 2001 From: Danial Behzadi Date: Thu, 30 Jun 2022 17:15:45 +0000 Subject: [PATCH 020/131] Translated using Weblate (Persian) Currently translated at 99.6% (2253 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/fa/ --- vector/src/main/res/values-fa/strings.xml | 24 ++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/vector/src/main/res/values-fa/strings.xml b/vector/src/main/res/values-fa/strings.xml index 55b870df65..3d7e86ac5e 100644 --- a/vector/src/main/res/values-fa/strings.xml +++ b/vector/src/main/res/values-fa/strings.xml @@ -2500,4 +2500,26 @@ ث د س - + به کار انداختن مکان زنده + هم‌رسانی مکان زنده + دروازهٔ کنونی: %s + دروازه + در حال استفاده از %s. + روش + + ۱ روش پیدا شد. + %d روش پیدا شد. + + روشی جز همگام سازی پس‌زمینه پیدا نشد. + روشی جز خدمت پلی گوگل پیدا نشد. + روش‌های موجود + روش آگاهی + همگام سازی پس‌زمینه + خدمات گوگل + گزینش چگونگی دریافت آگاهی + نتوانست تأیید هویت زیست‌سنجی را به کار بیندازد. + تأیی هویت زیست‌سنجی به دلیل اضافه شدن روش تأیسد هویت زیست‌سنجی جدیدی به تازگی از کار افتاده. می‌توانید دوباره در تنظیمات به کارش بیندازید. + بازنشانی روش آگاهی + برچسب نمایه: + بعدی + \ No newline at end of file From 063b017f42abfa2bcd82454f9291ef1c70e07851 Mon Sep 17 00:00:00 2001 From: Glandos Date: Fri, 1 Jul 2022 10:30:55 +0000 Subject: [PATCH 021/131] Translated using Weblate (French) Currently translated at 100.0% (2260 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/fr/ --- vector/src/main/res/values-fr/strings.xml | 32 ++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/vector/src/main/res/values-fr/strings.xml b/vector/src/main/res/values-fr/strings.xml index 3e3cbeafd4..ca75fb5b0d 100644 --- a/vector/src/main/res/values-fr/strings.xml +++ b/vector/src/main/res/values-fr/strings.xml @@ -2500,4 +2500,34 @@ s min h - + Activer le partage de localisation + Attention : c\'est une fonctionnalité expérimentale qui utilise une implémentation temporaire. Cela implique que vous ne pourrez pas supprimer votre historique de positions, et les utilisateurs avancés pourront voir votre historique de positions même après avoir arrêter le partage de votre position en continu dans ce salon. + Partage de position en continu + Passerelle actuelle : %s + Passerelle + Impossible de trouver le point de connexion. + Point de connexion actuel : %s + Point de connexion + Utilise %s actuellement. + Méthode + + %d méthode trouvée. + %d méthodes trouvées. + + Aucune autre méthode que la synchronisation en arrière-plan n’a été trouvée. + Aucune autre méthode que Google Play Service n’a été trouvée. + Méthodes disponibles + Méthode de notification + Synchronisation en arrière-plan + Google Services + Choisissez comment recevoir les notifications + Impossible d’activer l’authentification biométrique. + L’authentification biométrique a été désactivée car une nouvelle méthode d’authentification biométrique a été ajoutée récemment. Vous pouvez la réactiver dans les Paramètres. + Réinitialiser la méthode de notification + Étiquette de profil : + Le jeton du point de connexion n’a pas pu être enregistré sur le serveur d’accueil : +\n%1$s + Le point de connexion a été correctement enregistré sur le serveur d’accueil. + Enregistrement du point de connexion + Suivant + \ No newline at end of file From 0241a2167453e8ddde3c82133b231c1a6815fe0b Mon Sep 17 00:00:00 2001 From: Linerly Date: Fri, 1 Jul 2022 11:34:17 +0000 Subject: [PATCH 022/131] Translated using Weblate (Indonesian) Currently translated at 100.0% (2260 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/id/ --- vector/src/main/res/values-in/strings.xml | 31 ++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/vector/src/main/res/values-in/strings.xml b/vector/src/main/res/values-in/strings.xml index a055f6bdc8..0e8e32fcb9 100644 --- a/vector/src/main/res/values-in/strings.xml +++ b/vector/src/main/res/values-in/strings.xml @@ -2455,4 +2455,33 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. dtk mnt j - + Aktifkan pembagian lokasi + Mohon dicatat: ini adalah fitur uji coba menggunakan implementasi sementara. Ini berarti Anda tidak dapat menghapus riwayat lokasi Anda, dan pengguna bertingkat lanjut dapat melihat riwayat lokasi Anda bahkan setelah Anda membagikan lokasi langsung Anda di ruangan ini. + Pembagian lokasi langsung + Gateway saat ini: %s + Gateway + Tidak dapat menemukan endpoint. + Endpoint saat ini: %s + Endpoint + Saat ini menggunakan %s. + Metode + + Ditemukan %d metode. + + Tidak ada metode lain selain sinkronisasi latar belakang yang ditemukan. + Tidak ada metode lain selain Layanan Google Play yang ditemukan. + Metode yang tersedia + Metode notifikasi + Sinkronisasi latar belakang + Layanan Google + Pilih cara untuk menerima notifikasi + Tidak dapat mengaktifkan otentikasi biometrik. + Otentikasi biometrik dinonaktifkan karena sebuah otentikasi biometrik telah ditambahkan baru-baru ini. Anda dapat mengaktifkan ulang di Pengaturan. + Atur ulang metode notifikasi + Tag profil: + Gagal mendaftarkan token endpoint ke homeserver: +\n%1$s + Endpoint berhasil terdaftar ke homeserver. + Pendaftaran Endpoint + Lanjut + \ No newline at end of file From 6f610b134e49b936a7d4ead141ed538bd1fb319e Mon Sep 17 00:00:00 2001 From: random Date: Fri, 1 Jul 2022 13:04:46 +0000 Subject: [PATCH 023/131] Translated using Weblate (Italian) Currently translated at 100.0% (2260 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/it/ --- vector/src/main/res/values-it/strings.xml | 32 ++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/vector/src/main/res/values-it/strings.xml b/vector/src/main/res/values-it/strings.xml index 96f981d23d..5dfdc9f3ec 100644 --- a/vector/src/main/res/values-it/strings.xml +++ b/vector/src/main/res/values-it/strings.xml @@ -2491,4 +2491,34 @@ o sec min - + Attiva condivisione posizione + Nota: si tratta di una funzionalità sperimentale che usa un\'implementazione temporanea. Ciò significa che non potrai eliminare la cronologia delle posizioni e gli utenti avanzati potranno vederla anche dopo l\'interruzione della tua condivisione con questa stanza. + Condivisione posizione in tempo reale + Gateway attuale: %s + Gateway + Impossibile trovare l\'endpoint. + Endpoint attuale: %s + Endpoint + Ora si sta usando %s. + Metodo + + Trovato %d metodo. + Trovati %d metodi. + + Nessun altro metodo trovato oltre alla sincronizzazione in secondo piano. + Servizi Google + Nessun altro metodo trovato oltre a Google Play Service. + Metodi disponibili + Metodo di notifica + Sincronizzazione in secondo piano + Scegli come ricevere le notifiche + Impossibile attivare l\'autenticazione biometrica. + L\'autenticazione biometrica è stata disattivata perché è stato aggiunto di recente un nuovo metodo di autenticazione biometrica. Puoi riattivarla nelle impostazioni. + Reimposta metodo di notifica + Etichetta profilo: + È fallita la registrazione del token dell\'endpoint sull\'homeserver: +\n %1$s + Endpoint registrato con successo sull\'homeserver. + Registrazione endpoint + Avanti + \ No newline at end of file From 67d595dbf1fda00e107346f7d36ae7a41034f514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Romanik?= Date: Fri, 1 Jul 2022 16:21:05 +0000 Subject: [PATCH 024/131] Translated using Weblate (Polish) Currently translated at 98.8% (2233 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/pl/ --- vector/src/main/res/values-pl/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vector/src/main/res/values-pl/strings.xml b/vector/src/main/res/values-pl/strings.xml index 0f430acf8b..de9b79cb17 100644 --- a/vector/src/main/res/values-pl/strings.xml +++ b/vector/src/main/res/values-pl/strings.xml @@ -1178,7 +1178,7 @@ Nie masz więcej nieprzeczytanych wiadomości Reakcje Zgoda - Zobacz Reakcje + Zobacz reakcje Zdarzenie usunięte przez użytkownika Zdarzenie moderowane przez administratora pokoju Ogólne @@ -2593,4 +2593,4 @@ godz min Pokoje w przestrzeni - + \ No newline at end of file From 1c03162357cb17cebbe339c7286d3faa79cc6087 Mon Sep 17 00:00:00 2001 From: Nui Harime Date: Fri, 1 Jul 2022 16:30:51 +0000 Subject: [PATCH 025/131] Translated using Weblate (Russian) Currently translated at 98.6% (2230 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ru/ --- vector/src/main/res/values-ru/strings.xml | 55 ++++++++++++----------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/vector/src/main/res/values-ru/strings.xml b/vector/src/main/res/values-ru/strings.xml index d8b36edc79..fe33c147b1 100644 --- a/vector/src/main/res/values-ru/strings.xml +++ b/vector/src/main/res/values-ru/strings.xml @@ -408,7 +408,7 @@ Аутентификация Авторизован как Домашний сервер - Сервер опознавания + Сервер обнаружения Проверьте электронную почту и перейдите по высланной ссылке. Затем нажмите продолжить. Этот адрес электронной почты уже занят. Этот номер телефона уже используется. @@ -462,7 +462,7 @@ Язык Выберите язык Запускать при загрузке - Показывать метки времени для всех сообщений + Метки времени для всех сообщений 3 дня 1 неделя 1 месяц @@ -573,16 +573,16 @@ У вас сейчас нет доступных наклеек. \n \nДобавить сейчас\? - Деактивация аккаунта - Деактивировать мой аккаунт + Деактивация учётной записи + Деактивировать мою учётную запись Отправка аналитических данных ${app_name} собирает анонимную аналитику для улучшения приложения. Обязательный параметр отсутствует. Для продолжения использования %1$s вы должны ознакомиться и согласиться с условиями и правилами использования этого домашнего сервера. Посмотреть сейчас - Деактивировать аккаунт + Деактивировать учётную запись Пожалуйста, удалите все сообщения, которые я отправил, после деактивации моего аккаунта (Предупреждение: будущие участники увидят неполную историю разговоров) - Деактивировать аккаунт + Деактивировать учётную запись Это действие сделает вашу учетную запись навсегда непригодной для дальнейшего использования. Вы не сможете войти в систему и никто другой не сможет заново зарегистрировать учетную запись с вашим идентификатором. Также, это приведет к тому, что вы покинете все комнаты, в которых участвовали и данные о вашей учетной записи будут удалены с сервера идентификации. Это действие необратимо. \n \nПо умолчанию, деактивация вашей учетной записи не удаляет отправленные вами сообщения. Если вы хотите, чтобы мы удалили все ваши сообщения - поставьте отметку в поле ниже. @@ -701,11 +701,11 @@ Игнорировать оптимизацию Предпросмотр ссылок в чате, когда ваш домашний сервер поддерживает эту функцию. Показывать другим пользователям, что вы печатаете. - Форматировать сообщения, используя markdown. Например, позволяет использовать звездочки для выделения текста курсивом. - Показывать уведомления о прочтении + Форматировать сообщения, используя markdown. Например, позволяет использовать звёздочки для выделения текста курсивом. + Уведомления о прочтении Нажмите на уведомление о прочтении для подробного списка. - Показывать события о вступлении/выходе - Показывать события аккаунта + События о вступлении/выходе + События учётной записи Включает изменения аватара и отображаемого имени. Использовать системную камеру вместо камеры Element. %1$s: %2$s @@ -868,7 +868,7 @@ Клавиша Ввод отправит сообщение вместо переноса строки Воспроизвести звук затвора неизвестный IP - ** Отправить не удалось - пожалуйста откройте комнату + ** Отправить не удалось — пожалуйста, откройте комнату К сожалению, конференц-звонки с Jitsi не поддерживаются на старых устройствах (ниже Android OS - 6.0) Новая сессия запрашивает ключи шифрования. \nИмя сессии: %1$s @@ -904,7 +904,7 @@ Здесь будут отображаться ваши комнаты. Нажмите + в правом нижнем углу, чтобы найти существующие комнаты или создать свою. Реакции Принять - Добавить реакцию + Отреагировать Просмотреть реакции Менеджер интеграции Реакции @@ -1244,7 +1244,7 @@ Шифрование не включено %1$s: %2$s %1$s: %2$s %3$s - Показывать удалённые сообщения + Удалённые сообщения Показывать заглушку на месте удалённых сообщений Мы отправили письмо для подтверждения на %s, проверьте почту и нажмите на ссылку для подтверждения Код подтверждения неверный. @@ -1724,7 +1724,7 @@ %d секунд Опрос - Отреагировал: %s + Отреагировал(а): %s Результат проверки Ссылка была искажена У вас нет разрешения на запуск звонка в этой комнате @@ -1888,7 +1888,7 @@ Добавить кнопку в редактор сообщений, чтобы открыть клавиатуру эмодзи Показать клавиатуру эмодзи Используйте команду /confetti или отправьте сообщение, содержащее ❄️ или 🎉 - Показать эффекты чата + Эффекты Изменить тему Обновить комнату Отправить событие m.room.server_acl @@ -1994,7 +1994,7 @@ Покинуть текущую конференцию и перейти к другой\? Версия комнаты Показать все комнаты в списке комнат, в том числе с откровенным содержанием. - Показать комнаты с откровенным содержанием + Комнаты с непристойным содержанием Каталог комнат Новое значение Сменить @@ -2411,7 +2411,7 @@ Правовые положения Этот сервер не предоставляет никакой политики. Сторонние библиотеки - Политика вашего сервера опознавания + Политика сервера обнаружения Политика домашнего сервера Политика ${app_name} Вы можете отключить это в любое время в настройках @@ -2437,7 +2437,7 @@ Все обсуждения Посмотреть обсуждения Посмотреть в комнате - Показывать сообщения в пузырях + Сообщения в пузырях Не удалось загрузить карту Карта Примечание: приложение будет перезапущено @@ -2518,14 +2518,14 @@ Включить отправку трансляции местоположения ${app_name} Трансляция местоположения Транслировать до %1$s - Трансляция местоположения окончена + Трансляция завершена Трансляция местоположения включена - Поделиться текущим местоположением + Текущим местоположением Загрузка трансляции местоположения… Поделиться трансляцией местоположения на - Поделиться трансляцией местоположения + Трансляцией местоположения Поделились трансляцией местоположения - Поделиться трансляцией местоположения + Трансляцией местоположения Некоторые результаты могут быть скрыты, поскольку они являются приватными и для их просмотра необходимо приглашение. мин ч @@ -2541,10 +2541,10 @@ Поделиться этим местоположением Поделиться этим местоположением Увеличить масштаб до текущего местоположения - Поделиться текущим местоположением + Текущим местоположением Закрепить выбранное место на карте Отображать последнюю информацию о профиле (аватар и отображаемое имя) для всех сообщений. - Отображать последнюю информацию о пользователе + Последняя информация о пользователе Не найдено Занят Домашний сервер не принимает имя пользователя, состоящее только из цифр. @@ -2554,8 +2554,8 @@ Всё готово! ${app_name} также отлично подходит для работы. Ему доверяют самые надёжные организации в мире. Резервная копия имеет действительную подпись для данного пользователя. - Воспроизводить анимированные изображения в ленте сообщений, как только они становятся видимыми - Автовоспроизведение анимированных изображений + Воспроизводить анимированные изображения, как только они попадают в поле зрения + Анимированные изображения сек Обсуждения — это незавершенная работа с новыми интересными функциями, такими как улучшенные уведомления. Мы будем рады услышать ваши отзывы! Ваш домашний сервер в настоящее время не поддерживает обсуждения, поэтому эта функция может быть ненадёжной. Некоторые сообщения из обсуждений могут быть недоступны. %sВы хотите включить обсуждения в любом случае\? @@ -2576,4 +2576,5 @@ Присутствие ${app_name} Демонстрация экрана Идёт демонстрация экрана - + Посмотреть трансляцию местоположения + \ No newline at end of file From 5108b5dccb2a67e7131c7a057b1af89d1647d552 Mon Sep 17 00:00:00 2001 From: Jozef Gaal Date: Thu, 30 Jun 2022 23:11:24 +0000 Subject: [PATCH 026/131] Translated using Weblate (Slovak) Currently translated at 100.0% (2260 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sk/ --- vector/src/main/res/values-sk/strings.xml | 33 ++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/vector/src/main/res/values-sk/strings.xml b/vector/src/main/res/values-sk/strings.xml index d93838b2d4..5581d48393 100644 --- a/vector/src/main/res/values-sk/strings.xml +++ b/vector/src/main/res/values-sk/strings.xml @@ -2547,4 +2547,35 @@ sek min h - + Povoliť zdieľanie polohy + Upozornenie: ide o laboratórnu funkciu, ktorá je dočasne implementovaná. To znamená, že nebudete môcť vymazať históriu svojej polohy a pokročilí používatelia budú môcť vidieť históriu vašej polohy aj po tom, ako prestanete zdieľať svoju reálnu polohu s touto miestnosťou. + Zdieľanie polohy v reálnom čase + Aktuálna brána: %s + Brána + Nie je možné nájsť koncový bod. + Aktuálny koncový bod: %s + Koncový bod + V súčasnosti používa %s. + Spôsob + + Nájdený %d spôsob. + Nájdené %d spôsoby. + Nájdených %d spôsobov. + + Nenašiel sa iný spôsob ako synchronizácia na pozadí. + Žiadny iný spôsob ako služba Google Play nebol nájdený. + Dostupné spôsoby + Spôsob oznamovania + Synchronizácia na pozadí + Služby Google + Vyberte si spôsob prijímania oznámení + Nepodarilo sa zapnúť biometrické overovanie. + Biometrické overovanie bolo vypnuté, pretože nedávno bola pridaná nová metóda biometrického overovania. Môžete ho opäť povoliť v Nastaveniach. + Obnoviť spôsob oznamovania + Značka profilu: + Nepodarilo sa zaregistrovať token koncového bodu na domovskom serveri: +\n%1$s + Koncové zariadenie sa úspešne zaregistrovalo na domovský server. + Registrácia koncového bodu + Ďalej + \ No newline at end of file From ca565ea3d9593658802194d01bf59caa72fba68e Mon Sep 17 00:00:00 2001 From: LinAGKar Date: Fri, 1 Jul 2022 20:05:54 +0000 Subject: [PATCH 027/131] Translated using Weblate (Swedish) Currently translated at 98.8% (2235 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sv/ --- vector/src/main/res/values-sv/strings.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vector/src/main/res/values-sv/strings.xml b/vector/src/main/res/values-sv/strings.xml index fe5458466e..845515def1 100644 --- a/vector/src/main/res/values-sv/strings.xml +++ b/vector/src/main/res/values-sv/strings.xml @@ -2500,4 +2500,5 @@ sek min t - + Nästa + \ No newline at end of file From b1a459b6deee463a2e31b0d47343f72fefadac9a Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Thu, 30 Jun 2022 18:09:34 +0000 Subject: [PATCH 028/131] Translated using Weblate (Ukrainian) Currently translated at 100.0% (2260 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/uk/ --- vector/src/main/res/values-uk/strings.xml | 34 ++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/vector/src/main/res/values-uk/strings.xml b/vector/src/main/res/values-uk/strings.xml index 39254ac535..635594f505 100644 --- a/vector/src/main/res/values-uk/strings.xml +++ b/vector/src/main/res/values-uk/strings.xml @@ -2592,4 +2592,36 @@ с хв г - + Увімкнути надсилання місцеперебування + Зверніть увагу: це експериментальна функція, яка використовує тимчасову імплементацію. Це означає, що ви не зможете видалити свою історію місцеперебування, а досвідчені користувачі зможуть переглядати вашу історію місцеперебування, навіть якщо ви припините ділитися ним із цією кімнатою. + Надсилання місцеперебування наживо + Поточний шлюз: %s + Шлюз + Не вдалося знайти кінцеву точку. + Поточна кінцева точка: %s + Кінцева точка + Зараз використовується %s. + Метод + + Знайдений %d метод. + Знайдені %d методи. + Знайдені %d методів. + Знайдені %d методів. + + Не знайдено іншого методу, крім фонової синхронізації. + Іншого методу, крім служби Google Play, не знайдено. + Доступні методи + Метод сповіщення + Фонова синхронізація + Служби Google + Виберіть, як отримувати сповіщення + Не вдалось увімкнути біометричне розпізнавання. + Біометричне розпізнавання було вимкнено, оскільки нещодавно було додано новий метод біометричного розпізнавання. Ви можете знову ввімкнути його в налаштуваннях. + Скинути метод сповіщень + Мітка профілю: + Не вдалося зареєструвати токен кінцевої точки на домашньому сервері: +\n%1$s + Кінцеву точку успішно зареєстровано на домашньому сервері. + Реєстрація кінцевої точки + Далі + \ No newline at end of file From 227f6ffa58559ecf73abac0d765d300bd9175966 Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Fri, 1 Jul 2022 02:48:44 +0000 Subject: [PATCH 029/131] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (2260 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/zh_Hant/ --- vector/src/main/res/values-zh-rTW/strings.xml | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/vector/src/main/res/values-zh-rTW/strings.xml b/vector/src/main/res/values-zh-rTW/strings.xml index 55c3a4ca10..cac37b9b64 100644 --- a/vector/src/main/res/values-zh-rTW/strings.xml +++ b/vector/src/main/res/values-zh-rTW/strings.xml @@ -886,7 +886,7 @@ 格式: 音訊與視訊 說明與關於 - 註冊代符 + 註冊權杖 建議 請在下面編寫您的建議。 在此描述您的建議 @@ -2453,4 +2453,33 @@ 分鐘 小時 - + 啟用位置分享 + 請注意:這是使用暫時實作的實驗室功能。這代表了您將無法刪除您的位置歷史紀錄,即使您停止與此聊天室分享您的即時位置,進階使用者也還是能看到您的位置歷史紀錄。 + 即時位置分享 + 目前閘道:%s + 閘道 + 找不到端點。 + 目前端點:%s + 端點 + 目前正在使用 %s。 + 方式 + + 找到 %d 種方式。 + + 找不到除了背景同步以外的方式。 + 找不到除了 Google Play 服務以外的方式。 + 可用方式 + 通知方式 + 背景同步 + Google 服務 + 選擇如何接收通知 + 無法啟用生物特徵驗證。 + 生物特徵驗證方式被停用,因為最新新增了新的生物特徵驗證方式。您可以在「設定」中再次啟用它。 + 重設通知方式 + 個人檔案標籤: + 註冊端點權杖至家伺服器失敗: +\n%1$s + 端點成功註冊至家伺服器。 + 端點註冊 + 下一步 + \ No newline at end of file From 9d89ab1b6088f93f2fa65a2c4e489a6b53156e04 Mon Sep 17 00:00:00 2001 From: Glandos Date: Fri, 1 Jul 2022 10:19:09 +0000 Subject: [PATCH 030/131] Translated using Weblate (French) Currently translated at 100.0% (68 of 68 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/fr/ --- fastlane/metadata/android/fr-FR/changelogs/40104220.txt | 2 ++ fastlane/metadata/android/fr-FR/changelogs/40104230.txt | 2 ++ fastlane/metadata/android/fr-FR/changelogs/40104240.txt | 2 ++ fastlane/metadata/android/fr-FR/changelogs/40104250.txt | 2 ++ 4 files changed, 8 insertions(+) create mode 100644 fastlane/metadata/android/fr-FR/changelogs/40104220.txt create mode 100644 fastlane/metadata/android/fr-FR/changelogs/40104230.txt create mode 100644 fastlane/metadata/android/fr-FR/changelogs/40104240.txt create mode 100644 fastlane/metadata/android/fr-FR/changelogs/40104250.txt diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104220.txt b/fastlane/metadata/android/fr-FR/changelogs/40104220.txt new file mode 100644 index 0000000000..fe61fd021c --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/40104220.txt @@ -0,0 +1,2 @@ +Principaux changements pour cette version : Plusieurs corrections de bogues et d’améliorations de stabilité. +Intégralité des changements : https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104230.txt b/fastlane/metadata/android/fr-FR/changelogs/40104230.txt new file mode 100644 index 0000000000..fe61fd021c --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/40104230.txt @@ -0,0 +1,2 @@ +Principaux changements pour cette version : Plusieurs corrections de bogues et d’améliorations de stabilité. +Intégralité des changements : https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104240.txt b/fastlane/metadata/android/fr-FR/changelogs/40104240.txt new file mode 100644 index 0000000000..fe61fd021c --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/40104240.txt @@ -0,0 +1,2 @@ +Principaux changements pour cette version : Plusieurs corrections de bogues et d’améliorations de stabilité. +Intégralité des changements : https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104250.txt b/fastlane/metadata/android/fr-FR/changelogs/40104250.txt new file mode 100644 index 0000000000..fe61fd021c --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/40104250.txt @@ -0,0 +1,2 @@ +Principaux changements pour cette version : Plusieurs corrections de bogues et d’améliorations de stabilité. +Intégralité des changements : https://github.com/vector-im/element-android/releases From c07ea743c54dc536fd2fc688d5bed3aead389482 Mon Sep 17 00:00:00 2001 From: Jozef Gaal Date: Thu, 30 Jun 2022 23:01:00 +0000 Subject: [PATCH 031/131] Translated using Weblate (Slovak) Currently translated at 100.0% (68 of 68 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/sk/ --- fastlane/metadata/android/sk/changelogs/40104220.txt | 2 ++ fastlane/metadata/android/sk/changelogs/40104230.txt | 2 ++ fastlane/metadata/android/sk/changelogs/40104240.txt | 2 ++ fastlane/metadata/android/sk/changelogs/40104250.txt | 2 ++ 4 files changed, 8 insertions(+) create mode 100644 fastlane/metadata/android/sk/changelogs/40104220.txt create mode 100644 fastlane/metadata/android/sk/changelogs/40104230.txt create mode 100644 fastlane/metadata/android/sk/changelogs/40104240.txt create mode 100644 fastlane/metadata/android/sk/changelogs/40104250.txt diff --git a/fastlane/metadata/android/sk/changelogs/40104220.txt b/fastlane/metadata/android/sk/changelogs/40104220.txt new file mode 100644 index 0000000000..50670f18c2 --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/40104220.txt @@ -0,0 +1,2 @@ +Hlavné zmeny v tejto verzii: Rôzne opravy chýb a vylepšenia stability. +Úplný zoznam zmien: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/sk/changelogs/40104230.txt b/fastlane/metadata/android/sk/changelogs/40104230.txt new file mode 100644 index 0000000000..50670f18c2 --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/40104230.txt @@ -0,0 +1,2 @@ +Hlavné zmeny v tejto verzii: Rôzne opravy chýb a vylepšenia stability. +Úplný zoznam zmien: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/sk/changelogs/40104240.txt b/fastlane/metadata/android/sk/changelogs/40104240.txt new file mode 100644 index 0000000000..50670f18c2 --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/40104240.txt @@ -0,0 +1,2 @@ +Hlavné zmeny v tejto verzii: Rôzne opravy chýb a vylepšenia stability. +Úplný zoznam zmien: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/sk/changelogs/40104250.txt b/fastlane/metadata/android/sk/changelogs/40104250.txt new file mode 100644 index 0000000000..50670f18c2 --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/40104250.txt @@ -0,0 +1,2 @@ +Hlavné zmeny v tejto verzii: Rôzne opravy chýb a vylepšenia stability. +Úplný zoznam zmien: https://github.com/vector-im/element-android/releases From d08b4b953ff4fd47e81ce6ee19ca10b0ec68b7d3 Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Thu, 30 Jun 2022 18:11:28 +0000 Subject: [PATCH 032/131] Translated using Weblate (Ukrainian) Currently translated at 100.0% (68 of 68 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/uk/ --- fastlane/metadata/android/uk/changelogs/40104220.txt | 2 ++ fastlane/metadata/android/uk/changelogs/40104230.txt | 2 ++ fastlane/metadata/android/uk/changelogs/40104240.txt | 2 ++ fastlane/metadata/android/uk/changelogs/40104250.txt | 2 ++ 4 files changed, 8 insertions(+) create mode 100644 fastlane/metadata/android/uk/changelogs/40104220.txt create mode 100644 fastlane/metadata/android/uk/changelogs/40104230.txt create mode 100644 fastlane/metadata/android/uk/changelogs/40104240.txt create mode 100644 fastlane/metadata/android/uk/changelogs/40104250.txt diff --git a/fastlane/metadata/android/uk/changelogs/40104220.txt b/fastlane/metadata/android/uk/changelogs/40104220.txt new file mode 100644 index 0000000000..252a57c9d9 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/40104220.txt @@ -0,0 +1,2 @@ +Основні зміни в цій версії: Усунуто різні вади й поліпшено стабільність. +Вичерпний перелік змін: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/uk/changelogs/40104230.txt b/fastlane/metadata/android/uk/changelogs/40104230.txt new file mode 100644 index 0000000000..252a57c9d9 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/40104230.txt @@ -0,0 +1,2 @@ +Основні зміни в цій версії: Усунуто різні вади й поліпшено стабільність. +Вичерпний перелік змін: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/uk/changelogs/40104240.txt b/fastlane/metadata/android/uk/changelogs/40104240.txt new file mode 100644 index 0000000000..252a57c9d9 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/40104240.txt @@ -0,0 +1,2 @@ +Основні зміни в цій версії: Усунуто різні вади й поліпшено стабільність. +Вичерпний перелік змін: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/uk/changelogs/40104250.txt b/fastlane/metadata/android/uk/changelogs/40104250.txt new file mode 100644 index 0000000000..252a57c9d9 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/40104250.txt @@ -0,0 +1,2 @@ +Основні зміни в цій версії: Усунуто різні вади й поліпшено стабільність. +Вичерпний перелік змін: https://github.com/vector-im/element-android/releases From 26d42a198d6219549919580d664e91198febb857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Thu, 30 Jun 2022 17:15:41 +0000 Subject: [PATCH 033/131] Translated using Weblate (Estonian) Currently translated at 100.0% (68 of 68 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/et/ --- fastlane/metadata/android/et/changelogs/40104220.txt | 2 ++ fastlane/metadata/android/et/changelogs/40104230.txt | 2 ++ fastlane/metadata/android/et/changelogs/40104240.txt | 2 ++ fastlane/metadata/android/et/changelogs/40104250.txt | 2 ++ 4 files changed, 8 insertions(+) create mode 100644 fastlane/metadata/android/et/changelogs/40104220.txt create mode 100644 fastlane/metadata/android/et/changelogs/40104230.txt create mode 100644 fastlane/metadata/android/et/changelogs/40104240.txt create mode 100644 fastlane/metadata/android/et/changelogs/40104250.txt diff --git a/fastlane/metadata/android/et/changelogs/40104220.txt b/fastlane/metadata/android/et/changelogs/40104220.txt new file mode 100644 index 0000000000..1df5ac4176 --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/40104220.txt @@ -0,0 +1,2 @@ +Põhilised muutused selles versioonis: erinevate vigade parandused ja stabiilsust edendavad kohendused. +Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/et/changelogs/40104230.txt b/fastlane/metadata/android/et/changelogs/40104230.txt new file mode 100644 index 0000000000..1df5ac4176 --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/40104230.txt @@ -0,0 +1,2 @@ +Põhilised muutused selles versioonis: erinevate vigade parandused ja stabiilsust edendavad kohendused. +Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/et/changelogs/40104240.txt b/fastlane/metadata/android/et/changelogs/40104240.txt new file mode 100644 index 0000000000..1df5ac4176 --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/40104240.txt @@ -0,0 +1,2 @@ +Põhilised muutused selles versioonis: erinevate vigade parandused ja stabiilsust edendavad kohendused. +Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/et/changelogs/40104250.txt b/fastlane/metadata/android/et/changelogs/40104250.txt new file mode 100644 index 0000000000..1df5ac4176 --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/40104250.txt @@ -0,0 +1,2 @@ +Põhilised muutused selles versioonis: erinevate vigade parandused ja stabiilsust edendavad kohendused. +Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases From de2aac0ecddffa8d9d0d94745f5dd5843ccef861 Mon Sep 17 00:00:00 2001 From: random Date: Fri, 1 Jul 2022 13:05:13 +0000 Subject: [PATCH 034/131] Translated using Weblate (Italian) Currently translated at 100.0% (68 of 68 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/it/ --- fastlane/metadata/android/it-IT/changelogs/40104220.txt | 2 ++ fastlane/metadata/android/it-IT/changelogs/40104230.txt | 2 ++ fastlane/metadata/android/it-IT/changelogs/40104240.txt | 2 ++ fastlane/metadata/android/it-IT/changelogs/40104250.txt | 2 ++ 4 files changed, 8 insertions(+) create mode 100644 fastlane/metadata/android/it-IT/changelogs/40104220.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/40104230.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/40104240.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/40104250.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/40104220.txt b/fastlane/metadata/android/it-IT/changelogs/40104220.txt new file mode 100644 index 0000000000..556a6fc7ea --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/40104220.txt @@ -0,0 +1,2 @@ +Modifiche principali in questa versione: varie correzioni di errori e miglioramenti della stabilità. +Cronologia completa: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/it-IT/changelogs/40104230.txt b/fastlane/metadata/android/it-IT/changelogs/40104230.txt new file mode 100644 index 0000000000..556a6fc7ea --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/40104230.txt @@ -0,0 +1,2 @@ +Modifiche principali in questa versione: varie correzioni di errori e miglioramenti della stabilità. +Cronologia completa: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/it-IT/changelogs/40104240.txt b/fastlane/metadata/android/it-IT/changelogs/40104240.txt new file mode 100644 index 0000000000..556a6fc7ea --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/40104240.txt @@ -0,0 +1,2 @@ +Modifiche principali in questa versione: varie correzioni di errori e miglioramenti della stabilità. +Cronologia completa: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/it-IT/changelogs/40104250.txt b/fastlane/metadata/android/it-IT/changelogs/40104250.txt new file mode 100644 index 0000000000..556a6fc7ea --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/40104250.txt @@ -0,0 +1,2 @@ +Modifiche principali in questa versione: varie correzioni di errori e miglioramenti della stabilità. +Cronologia completa: https://github.com/vector-im/element-android/releases From 080759b1547b013e597b85b7ad98b2cc040a772d Mon Sep 17 00:00:00 2001 From: Danial Behzadi Date: Thu, 30 Jun 2022 17:08:55 +0000 Subject: [PATCH 035/131] Translated using Weblate (Persian) Currently translated at 100.0% (68 of 68 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/fa/ --- fastlane/metadata/android/fa/changelogs/40104220.txt | 2 ++ fastlane/metadata/android/fa/changelogs/40104230.txt | 2 ++ fastlane/metadata/android/fa/changelogs/40104240.txt | 2 ++ fastlane/metadata/android/fa/changelogs/40104250.txt | 2 ++ 4 files changed, 8 insertions(+) create mode 100644 fastlane/metadata/android/fa/changelogs/40104220.txt create mode 100644 fastlane/metadata/android/fa/changelogs/40104230.txt create mode 100644 fastlane/metadata/android/fa/changelogs/40104240.txt create mode 100644 fastlane/metadata/android/fa/changelogs/40104250.txt diff --git a/fastlane/metadata/android/fa/changelogs/40104220.txt b/fastlane/metadata/android/fa/changelogs/40104220.txt new file mode 100644 index 0000000000..29efb95925 --- /dev/null +++ b/fastlane/metadata/android/fa/changelogs/40104220.txt @@ -0,0 +1,2 @@ +تغییرات عمده در این نگارش: رفع اشکال‌های مختلف و بهبودهای پایداری. +گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/fa/changelogs/40104230.txt b/fastlane/metadata/android/fa/changelogs/40104230.txt new file mode 100644 index 0000000000..29efb95925 --- /dev/null +++ b/fastlane/metadata/android/fa/changelogs/40104230.txt @@ -0,0 +1,2 @@ +تغییرات عمده در این نگارش: رفع اشکال‌های مختلف و بهبودهای پایداری. +گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/fa/changelogs/40104240.txt b/fastlane/metadata/android/fa/changelogs/40104240.txt new file mode 100644 index 0000000000..29efb95925 --- /dev/null +++ b/fastlane/metadata/android/fa/changelogs/40104240.txt @@ -0,0 +1,2 @@ +تغییرات عمده در این نگارش: رفع اشکال‌های مختلف و بهبودهای پایداری. +گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/fa/changelogs/40104250.txt b/fastlane/metadata/android/fa/changelogs/40104250.txt new file mode 100644 index 0000000000..29efb95925 --- /dev/null +++ b/fastlane/metadata/android/fa/changelogs/40104250.txt @@ -0,0 +1,2 @@ +تغییرات عمده در این نگارش: رفع اشکال‌های مختلف و بهبودهای پایداری. +گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases From 96eaa62d7b7b740b2959dd68f1bca5be467b69ea Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Fri, 1 Jul 2022 02:38:23 +0000 Subject: [PATCH 036/131] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (68 of 68 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/zh_Hant/ --- fastlane/metadata/android/zh-TW/changelogs/40104220.txt | 2 ++ fastlane/metadata/android/zh-TW/changelogs/40104230.txt | 2 ++ fastlane/metadata/android/zh-TW/changelogs/40104240.txt | 2 ++ fastlane/metadata/android/zh-TW/changelogs/40104250.txt | 2 ++ 4 files changed, 8 insertions(+) create mode 100644 fastlane/metadata/android/zh-TW/changelogs/40104220.txt create mode 100644 fastlane/metadata/android/zh-TW/changelogs/40104230.txt create mode 100644 fastlane/metadata/android/zh-TW/changelogs/40104240.txt create mode 100644 fastlane/metadata/android/zh-TW/changelogs/40104250.txt diff --git a/fastlane/metadata/android/zh-TW/changelogs/40104220.txt b/fastlane/metadata/android/zh-TW/changelogs/40104220.txt new file mode 100644 index 0000000000..4bcca9a0b8 --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/40104220.txt @@ -0,0 +1,2 @@ +此版本中的主要變動:多個臭蟲修復與穩定性改善。 +完整的變更紀錄:https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/zh-TW/changelogs/40104230.txt b/fastlane/metadata/android/zh-TW/changelogs/40104230.txt new file mode 100644 index 0000000000..4bcca9a0b8 --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/40104230.txt @@ -0,0 +1,2 @@ +此版本中的主要變動:多個臭蟲修復與穩定性改善。 +完整的變更紀錄:https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/zh-TW/changelogs/40104240.txt b/fastlane/metadata/android/zh-TW/changelogs/40104240.txt new file mode 100644 index 0000000000..4bcca9a0b8 --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/40104240.txt @@ -0,0 +1,2 @@ +此版本中的主要變動:多個臭蟲修復與穩定性改善。 +完整的變更紀錄:https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/zh-TW/changelogs/40104250.txt b/fastlane/metadata/android/zh-TW/changelogs/40104250.txt new file mode 100644 index 0000000000..4bcca9a0b8 --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/40104250.txt @@ -0,0 +1,2 @@ +此版本中的主要變動:多個臭蟲修復與穩定性改善。 +完整的變更紀錄:https://github.com/vector-im/element-android/releases From 0b5f991434ff8a1b8fafa9e3ad4640424ada8733 Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Thu, 30 Jun 2022 17:21:24 +0000 Subject: [PATCH 037/131] Translated using Weblate (Czech) Currently translated at 100.0% (68 of 68 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/cs/ --- fastlane/metadata/android/cs-CZ/changelogs/40104220.txt | 2 ++ fastlane/metadata/android/cs-CZ/changelogs/40104230.txt | 2 ++ fastlane/metadata/android/cs-CZ/changelogs/40104240.txt | 2 ++ fastlane/metadata/android/cs-CZ/changelogs/40104250.txt | 2 ++ 4 files changed, 8 insertions(+) create mode 100644 fastlane/metadata/android/cs-CZ/changelogs/40104220.txt create mode 100644 fastlane/metadata/android/cs-CZ/changelogs/40104230.txt create mode 100644 fastlane/metadata/android/cs-CZ/changelogs/40104240.txt create mode 100644 fastlane/metadata/android/cs-CZ/changelogs/40104250.txt diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40104220.txt b/fastlane/metadata/android/cs-CZ/changelogs/40104220.txt new file mode 100644 index 0000000000..578549ce6c --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/40104220.txt @@ -0,0 +1,2 @@ +Hlavní změny v této verzi: Opravy různých chyb a vylepšení stability. +Úplný seznam změn: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40104230.txt b/fastlane/metadata/android/cs-CZ/changelogs/40104230.txt new file mode 100644 index 0000000000..578549ce6c --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/40104230.txt @@ -0,0 +1,2 @@ +Hlavní změny v této verzi: Opravy různých chyb a vylepšení stability. +Úplný seznam změn: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40104240.txt b/fastlane/metadata/android/cs-CZ/changelogs/40104240.txt new file mode 100644 index 0000000000..578549ce6c --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/40104240.txt @@ -0,0 +1,2 @@ +Hlavní změny v této verzi: Opravy různých chyb a vylepšení stability. +Úplný seznam změn: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40104250.txt b/fastlane/metadata/android/cs-CZ/changelogs/40104250.txt new file mode 100644 index 0000000000..578549ce6c --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/40104250.txt @@ -0,0 +1,2 @@ +Hlavní změny v této verzi: Opravy různých chyb a vylepšení stability. +Úplný seznam změn: https://github.com/vector-im/element-android/releases From 6cd05c899e3bfee5eb680dc1bd0c6904944c2408 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Mon, 4 Jul 2022 12:01:22 +0100 Subject: [PATCH 038/131] fixing homeserver edits not updating the selected server UI --- .../im/vector/app/features/onboarding/OnboardingViewModel.kt | 4 +++- .../vector/app/features/onboarding/OnboardingViewModelTest.kt | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index 56f95db2be..27c501176e 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -302,7 +302,9 @@ class OnboardingViewModel @AssistedInject constructor( authenticationDescription = awaitState().selectedAuthenticationState.description ?: AuthenticationDescription.Register(AuthenticationDescription.AuthenticationType.Other) ) - RegistrationActionHandler.Result.StartRegistration -> _viewEvents.post(OnboardingViewEvents.DisplayStartRegistration) + RegistrationActionHandler.Result.StartRegistration -> { + overrideNextStage?.invoke() ?: _viewEvents.post(OnboardingViewEvents.DisplayStartRegistration) + } RegistrationActionHandler.Result.UnsupportedStage -> _viewEvents.post(OnboardingViewEvents.DisplayRegistrationFallback) is RegistrationActionHandler.Result.SendEmailSuccess -> _viewEvents.post(OnboardingViewEvents.OnSendEmailSuccess(it.email)) is RegistrationActionHandler.Result.SendMsisdnSuccess -> _viewEvents.post(OnboardingViewEvents.OnSendMsisdnSuccess(it.msisdn.msisdn)) diff --git a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt index 16a3257b72..a56e2e07ac 100644 --- a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt +++ b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt @@ -630,7 +630,7 @@ class OnboardingViewModelTest { private fun givenCanSuccessfullyUpdateHomeserver(homeserverUrl: String, resultingState: SelectedHomeserverState) { fakeHomeServerConnectionConfigFactory.givenConfigFor(homeserverUrl, A_HOMESERVER_CONFIG) fakeStartAuthenticationFlowUseCase.givenResult(A_HOMESERVER_CONFIG, StartAuthenticationResult(isHomeserverOutdated = false, resultingState)) - givenRegistrationResultFor(RegisterAction.StartRegistration, ANY_CONTINUING_REGISTRATION_RESULT) + givenRegistrationResultFor(RegisterAction.StartRegistration, RegistrationActionHandler.Result.StartRegistration) fakeHomeServerHistoryService.expectUrlToBeAdded(A_HOMESERVER_CONFIG.homeServerUri.toString()) } From 8a5a47c6a57863b87f62ca2e123fe619d1d9b612 Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Mon, 4 Jul 2022 17:38:32 +0200 Subject: [PATCH 039/131] Ensure that Realm is up to date before returning the roomId --- .../room/create/CreateLocalRoomTask.kt | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt index 811d7ef5b6..7f0d3a63e3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt @@ -18,16 +18,13 @@ package org.matrix.android.sdk.internal.session.room.create import com.zhuinden.monarchy.Monarchy import io.realm.Realm -import io.realm.RealmConfiguration import io.realm.kotlin.createObject -import kotlinx.coroutines.TimeoutCancellationException import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.events.model.Content 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.events.model.toContent -import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure import org.matrix.android.sdk.api.session.room.model.GuestAccess import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility @@ -40,7 +37,6 @@ import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.sync.model.RoomSyncSummary import org.matrix.android.sdk.api.session.user.UserService import org.matrix.android.sdk.api.session.user.model.User -import org.matrix.android.sdk.internal.database.awaitNotEmptyResult import org.matrix.android.sdk.internal.database.helper.addTimelineEvent import org.matrix.android.sdk.internal.database.mapper.asDomain import org.matrix.android.sdk.internal.database.mapper.toEntity @@ -49,7 +45,6 @@ import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity import org.matrix.android.sdk.internal.database.model.EventInsertType import org.matrix.android.sdk.internal.database.model.RoomEntity import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity -import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields import org.matrix.android.sdk.internal.database.query.copyToRealmOrIgnore import org.matrix.android.sdk.internal.database.query.getOrCreate import org.matrix.android.sdk.internal.database.query.getOrNull @@ -63,7 +58,6 @@ import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction import org.matrix.android.sdk.internal.util.time.Clock import java.util.UUID -import java.util.concurrent.TimeUnit import javax.inject.Inject internal interface CreateLocalRoomTask : Task @@ -73,7 +67,6 @@ internal class DefaultCreateLocalRoomTask @Inject constructor( @SessionDatabase private val monarchy: Monarchy, private val roomMemberEventHandler: RoomMemberEventHandler, private val roomSummaryUpdater: RoomSummaryUpdater, - @SessionDatabase private val realmConfiguration: RealmConfiguration, private val createRoomBodyBuilder: CreateRoomBodyBuilder, private val userService: UserService, private val clock: Clock, @@ -87,16 +80,8 @@ internal class DefaultCreateLocalRoomTask @Inject constructor( createLocalRoomSummaryEntity(realm, roomId, createRoomBody) } - // Wait for room to be created in DB - try { - awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm -> - realm.where(RoomSummaryEntity::class.java) - .equalTo(RoomSummaryEntityFields.ROOM_ID, roomId) - .equalTo(RoomSummaryEntityFields.MEMBERSHIP_STR, Membership.JOIN.name) - } - } catch (exception: TimeoutCancellationException) { - throw CreateRoomFailure.CreatedWithTimeout(roomId) - } + // Ensure that Realm is up to date before returning the roomId. + monarchy.doWithRealm { it.refresh() } return roomId } From f4b50f1e0f7823550d708cba70ddf3b868ae1ad8 Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Mon, 4 Jul 2022 17:41:00 +0200 Subject: [PATCH 040/131] Fix logs when deleting local room --- .../sdk/internal/session/room/delete/DeleteLocalRoomTask.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/delete/DeleteLocalRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/delete/DeleteLocalRoomTask.kt index 689fd24a97..a15cb4393c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/delete/DeleteLocalRoomTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/delete/DeleteLocalRoomTask.kt @@ -61,7 +61,7 @@ internal class DefaultDeleteLocalRoomTask @Inject constructor( ?.also { Timber.i("## DeleteLocalRoomTask - TimelineEventEntity - delete ${it.size} entries") } ?.deleteAllFromRealm() ChunkEntity.where(realm, roomId = roomId).findAll() - ?.also { Timber.i("## DeleteLocalRoomTask - RoomMemberSummaryEntity - delete ${it.size} entries") } + ?.also { Timber.i("## DeleteLocalRoomTask - ChunkEntity - delete ${it.size} entries") } ?.deleteAllFromRealm() RoomSummaryEntity.where(realm, roomId = roomId).findAll() ?.also { Timber.i("## DeleteLocalRoomTask - RoomSummaryEntity - delete ${it.size} entries") } @@ -71,7 +71,7 @@ internal class DefaultDeleteLocalRoomTask @Inject constructor( ?.deleteAllFromRealm() } } else { - Timber.i("## DeleteLocalRoomTask - Failed to remove room id $roomId: not a local room") + Timber.i("## DeleteLocalRoomTask - Failed to remove room with id $roomId: not a local room") } } } From 0d9cd2b3a3bbf4e2b49fc3ff01102a548bd16e81 Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Mon, 4 Jul 2022 17:47:48 +0200 Subject: [PATCH 041/131] Delete local room related entities with cascade --- .../sdk/internal/session/room/delete/DeleteLocalRoomTask.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/delete/DeleteLocalRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/delete/DeleteLocalRoomTask.kt index a15cb4393c..936c94e520 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/delete/DeleteLocalRoomTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/delete/DeleteLocalRoomTask.kt @@ -25,6 +25,7 @@ import org.matrix.android.sdk.internal.database.model.RoomEntity import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntity import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity import org.matrix.android.sdk.internal.database.model.TimelineEventEntity +import org.matrix.android.sdk.internal.database.model.deleteOnCascade import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.database.query.whereRoomId import org.matrix.android.sdk.internal.di.SessionDatabase @@ -59,10 +60,10 @@ internal class DefaultDeleteLocalRoomTask @Inject constructor( ?.deleteAllFromRealm() TimelineEventEntity.whereRoomId(realm, roomId = roomId).findAll() ?.also { Timber.i("## DeleteLocalRoomTask - TimelineEventEntity - delete ${it.size} entries") } - ?.deleteAllFromRealm() + ?.forEach { it.deleteOnCascade(true) } ChunkEntity.where(realm, roomId = roomId).findAll() ?.also { Timber.i("## DeleteLocalRoomTask - ChunkEntity - delete ${it.size} entries") } - ?.deleteAllFromRealm() + ?.forEach { it.deleteOnCascade(deleteStateEvents = true, canDeleteRoot = true) } RoomSummaryEntity.where(realm, roomId = roomId).findAll() ?.also { Timber.i("## DeleteLocalRoomTask - RoomSummaryEntity - delete ${it.size} entries") } ?.deleteAllFromRealm() From e89bb0eea7c3c41828147fecc89384b7a32e1821 Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Mon, 4 Jul 2022 17:53:21 +0200 Subject: [PATCH 042/131] Set local room members as loaded --- .../sdk/internal/session/room/create/CreateLocalRoomTask.kt | 2 ++ .../sdk/internal/session/room/timeline/DefaultTimeline.kt | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt index 7f0d3a63e3..eb35dd2387 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt @@ -44,6 +44,7 @@ import org.matrix.android.sdk.internal.database.model.ChunkEntity import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity import org.matrix.android.sdk.internal.database.model.EventInsertType import org.matrix.android.sdk.internal.database.model.RoomEntity +import org.matrix.android.sdk.internal.database.model.RoomMembersLoadStatusType import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity import org.matrix.android.sdk.internal.database.query.copyToRealmOrIgnore import org.matrix.android.sdk.internal.database.query.getOrCreate @@ -94,6 +95,7 @@ internal class DefaultCreateLocalRoomTask @Inject constructor( RoomEntity.getOrCreate(realm, roomId).apply { membership = Membership.JOIN chunks.add(createLocalRoomChunk(realm, roomId, createRoomBody)) + membersLoadStatus = RoomMembersLoadStatusType.LOADED } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt index 6e72cbdb8f..d1eb8794bf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt @@ -34,7 +34,6 @@ import okhttp3.internal.closeQuietly import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.room.model.Membership -import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho 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 @@ -390,7 +389,6 @@ internal class DefaultTimeline( } private suspend fun loadRoomMembersIfNeeded() { - if (RoomLocalEcho.isLocalEchoId(roomId)) return val loadRoomMembersParam = LoadRoomMembersTask.Params(roomId, excludeMembership = Membership.LEAVE) try { loadRoomMembersTask.execute(loadRoomMembersParam) From 2b6bfc1ebc8a3ae89d68d23fde5c5cba7ff847bf Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Mon, 4 Jul 2022 18:00:30 +0200 Subject: [PATCH 043/131] Create local events using local echo --- .../session/room/create/CreateLocalRoomTask.kt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt index eb35dd2387..94c300c3c3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt @@ -24,6 +24,7 @@ import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.events.model.Content 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.events.model.LocalEcho import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.room.model.GuestAccess import org.matrix.android.sdk.api.session.room.model.Membership @@ -58,7 +59,6 @@ import org.matrix.android.sdk.internal.session.room.timeline.PaginationDirection import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction import org.matrix.android.sdk.internal.util.time.Clock -import java.util.UUID import javax.inject.Inject internal interface CreateLocalRoomTask : Task @@ -185,13 +185,13 @@ internal class DefaultCreateLocalRoomTask @Inject constructor( val invitedUsers = createRoomBody.invitedUserIds.orEmpty() .mapNotNull { tryOrNull { userService.resolveUser(it) } } - val createRoomEvent = createFakeEvent( + val createRoomEvent = createLocalEvent( type = EventType.STATE_ROOM_CREATE, content = RoomCreateContent( creator = userId ).toContent() ) - val myRoomMemberEvent = createFakeEvent( + val myRoomMemberEvent = createLocalEvent( type = EventType.STATE_ROOM_MEMBER, content = RoomMemberContent( membership = Membership.JOIN, @@ -201,7 +201,7 @@ internal class DefaultCreateLocalRoomTask @Inject constructor( stateKey = userId ) val roomMemberEvents = invitedUsers.map { - createFakeEvent( + createLocalEvent( type = EventType.STATE_ROOM_MEMBER, content = RoomMemberContent( isDirect = createRoomBody.isDirect.orFalse(), @@ -216,7 +216,7 @@ internal class DefaultCreateLocalRoomTask @Inject constructor( return buildList { add(createRoomEvent) add(myRoomMemberEvent) - addAll(createRoomBody.initialStates.orEmpty().map { createFakeEvent(it.type, it.content, it.stateKey) }) + addAll(createRoomBody.initialStates.orEmpty().map { createLocalEvent(it.type, it.content, it.stateKey) }) addAll(roomMemberEvents) } } @@ -230,14 +230,14 @@ internal class DefaultCreateLocalRoomTask @Inject constructor( * * @return a fake event */ - private fun createFakeEvent(type: String?, content: Content?, stateKey: String? = ""): Event { + private fun createLocalEvent(type: String?, content: Content?, stateKey: String? = ""): Event { return Event( type = type, senderId = userId, stateKey = stateKey, content = content, originServerTs = clock.epochMillis(), - eventId = UUID.randomUUID().toString() + eventId = LocalEcho.createLocalEchoId() ) } From 414dc52f7d56aee57dc4a380a8590a2229e01ae4 Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Mon, 4 Jul 2022 18:03:43 +0200 Subject: [PATCH 044/131] Fix copyright date --- .../sdk/api/session/room/model/localecho/RoomLocalEcho.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/localecho/RoomLocalEcho.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/localecho/RoomLocalEcho.kt index a9804c6dac..e48baff5a2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/localecho/RoomLocalEcho.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/localecho/RoomLocalEcho.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * 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. From bf95ece5c8b9d284c2756d6fcdfc0b16a727a51e Mon Sep 17 00:00:00 2001 From: "Auri B. P" Date: Mon, 4 Jul 2022 19:40:00 +0000 Subject: [PATCH 045/131] Translated using Weblate (Catalan) Currently translated at 100.0% (2260 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ca/ --- vector/src/main/res/values-ca/strings.xml | 32 ++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/vector/src/main/res/values-ca/strings.xml b/vector/src/main/res/values-ca/strings.xml index 540a9f288c..ee0aa016d4 100644 --- a/vector/src/main/res/values-ca/strings.xml +++ b/vector/src/main/res/values-ca/strings.xml @@ -2500,4 +2500,34 @@ s min h - + Nota: aquesta és una funció en proves que utilitza una implementació temporal. Això vol dir que no podràs suprimir el teu historial d\'ubicacions i que els usuaris avançats el podran veure fins i tot després de deixar de compartir la teva ubicació en directe en aquesta sala. + L\'autenticació biomètrica s\'ha desactivat perquè s\'ha afegit un nou mètode d\'autenticació biomètrica. Pots tornar-la a activar a Configuració. + Activa la compartició d\'ubicació + Compartició d\'ubicació en directe + \'Gateway\' actual: %s + Passarel·la (\'gateway\') + No s\'ha trobat l\'endpoint. + \'Endpoint\' actual: %s + Punt final (\'endpoint\') + Actualment utilitzant %s. + Mètode + + S\'ha trobat %d mètode. + S\'han trobat %d mètodes. + + No s\'ha trobat cap altre mètode a part de la sincronització en segon pla. + No s\'ha trobat cap altre mètode a part de Serveis de Google. + Mètodes disponibles + Mètode de notificacions + Sincronització en segon pla + Serveis de Google + Tria com rebre les notificacions + No s\'ha pogut activar l\'autenticació biomètrica. + Restableix el mètode de notificacions + Etiqueta de perfil: + No s\'ha pogut registrar l\'endpoint al servidor: +\n%1$s + \'Endpoint\' registrat correctament al servidor. + Registre d\'endpoint + Següent + \ No newline at end of file From d055d5e5df76981357c21316e1b13364e4d1b8e2 Mon Sep 17 00:00:00 2001 From: Jeanne Lavoie Date: Sat, 2 Jul 2022 21:34:39 +0000 Subject: [PATCH 046/131] Translated using Weblate (French (Canada)) Currently translated at 79.7% (1802 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/fr_CA/ --- vector/src/main/res/values-fr-rCA/strings.xml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/vector/src/main/res/values-fr-rCA/strings.xml b/vector/src/main/res/values-fr-rCA/strings.xml index d8e90a75e2..3567b8e1c0 100644 --- a/vector/src/main/res/values-fr-rCA/strings.xml +++ b/vector/src/main/res/values-fr-rCA/strings.xml @@ -2071,4 +2071,9 @@ Permissions manquantes Pour envoyer des messages vocaux, veuillez accorder la permission Microphone. Pour effectuer cette action, veuillez autoriser la permission Caméra depuis les réglages système. - + ${app_name} a besoin d’effacer le cache pour la mise-à-jour, pour la raison suivante : +\n%s +\n +\nCette action va redémarrer l’application et pourra prendre du temps. + Requête de synchronisation initiale + \ No newline at end of file From 61f19d5bde31176ab0c15b45057c776beaeeec3b Mon Sep 17 00:00:00 2001 From: Didek Date: Mon, 4 Jul 2022 18:52:31 +0000 Subject: [PATCH 047/131] Translated using Weblate (Polish) Currently translated at 99.1% (2241 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/pl/ --- vector/src/main/res/values-pl/strings.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/vector/src/main/res/values-pl/strings.xml b/vector/src/main/res/values-pl/strings.xml index de9b79cb17..f081475e9c 100644 --- a/vector/src/main/res/values-pl/strings.xml +++ b/vector/src/main/res/values-pl/strings.xml @@ -2593,4 +2593,17 @@ godz min Pokoje w przestrzeni + Dalej + Dostawca + + Znaleziono %d dostawcę. + Znaleziono %d dostawców. + Znaleziono %d dostawdów. + Znaleziono %d dostawdów. + + Nie znaleziono innej metody poza ciągłą synchronizacją w tle. + Nie znaleziono innych dostawców poza usługami Google Play. + Dostępni dostawcy + Dostawca powiadomień + Wybierz, którego dostawcy powiadomień push chcesz używać \ No newline at end of file From c9e93d695b21873278b899d21db0019bd23c1e5f Mon Sep 17 00:00:00 2001 From: Daniil Omelchenko Date: Mon, 4 Jul 2022 10:26:42 +0000 Subject: [PATCH 048/131] Translated using Weblate (Russian) Currently translated at 99.5% (2250 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ru/ --- vector/src/main/res/values-ru/strings.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vector/src/main/res/values-ru/strings.xml b/vector/src/main/res/values-ru/strings.xml index fe33c147b1..09f0ae7b9c 100644 --- a/vector/src/main/res/values-ru/strings.xml +++ b/vector/src/main/res/values-ru/strings.xml @@ -2577,4 +2577,10 @@ ${app_name} Демонстрация экрана Идёт демонстрация экрана Посмотреть трансляцию местоположения + Текущий шлюз: %s + Шлюз + Сервисы Google + Не удалось включить вход по биометрии. + Вход по биометрии был отключён, так как недавно был добавлен новый метод входа по биометрии. Вы можете снова включить его в настройках. + Метка профиля: \ No newline at end of file From 568052c4cebecc133c0e6327b5988d69cfe0fe6c Mon Sep 17 00:00:00 2001 From: Nui Harime Date: Sun, 3 Jul 2022 19:47:08 +0000 Subject: [PATCH 049/131] Translated using Weblate (Russian) Currently translated at 99.5% (2250 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ru/ --- vector/src/main/res/values-ru/strings.xml | 35 +++++++++++++++++------ 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/vector/src/main/res/values-ru/strings.xml b/vector/src/main/res/values-ru/strings.xml index 09f0ae7b9c..6ac29a100f 100644 --- a/vector/src/main/res/values-ru/strings.xml +++ b/vector/src/main/res/values-ru/strings.xml @@ -40,7 +40,7 @@ %1$s и %2$s Пустая комната Начальная синхронизация: -\nИмпорт учетной записи… +\nИмпорт учётной записи… Начальная синхронизация: \nИмпорт криптографии Начальная синхронизация: @@ -99,9 +99,9 @@ Вы забанили %1$s Вы отозвали приглашение %1$s Вы сменили свой аватар - Вы сменили своё отображаемое имя на %1$s - Вы сменили своё отображаемое имя с %1$s на %2$s - Вы удалили своё отображаемое имя (%1$s) + Вы сменили отображаемое имя на %1$s + Вы сменили отображаемое имя с %1$s на %2$s + Вы удалили отображаемое имя (%1$s) Вы сменили тему на: %1$s Вы сменили название комнаты на: %1$s Вы начали видеозвонок. @@ -1361,7 +1361,7 @@ Введенный код неверен. Пожалуйста, проверьте. Войти с Matrix ID Войти с Matrix ID - Если вы создаете учетную запись на домашнем сервере, используйте свой матричный идентификатор (например, @user:domain.com) и пароль ниже. + Если вы создаёте учётную запись на домашнем сервере, используйте свой матричный идентификатор (например, @user:domain.com) и пароль ниже. Matrix ID Если вы не знаете свой пароль, вернитесь, чтобы сбросить его. Это недопустимый идентификатор пользователя. Ожидаемый формат: \'@user:homeserver.org\' @@ -2305,7 +2305,7 @@ Отображает информацию о пользователе Изменяет ваш аватар только в этой текущей комнате Меняет аватар текущей комнаты - Изменяет ваш отображаемое имя только в текущей комнате + Изменяет ваше отображаемое имя только в текущей комнате Устанавливает имя комнаты Прекращение игнорирования пользователя, показывает его сообщения в дальнейшем Игнорирует пользователя, скрывая его сообщения от вас @@ -2389,8 +2389,8 @@ Обратитесь к администратору, чтобы восстановить шифрование до рабочего состояния. Шифрование настроено неправильно. Поделились своим местоположением - У меня уже есть учетная запись - Создать учетную запись + У меня уже есть учётная запись + Создать учётную запись Обмен сообщениями для вашей команды. Сквозное шифрование не требующее номера телефона. Нет рекламы или сбора данных. Решайте самостоятельно и независимо, где хранить беседы. Благодаря Matrix. @@ -2583,4 +2583,23 @@ Не удалось включить вход по биометрии. Вход по биометрии был отключён, так как недавно был добавлен новый метод входа по биометрии. Вы можете снова включить его в настройках. Метка профиля: + Разрешить отправку местоположения + Трансляция местоположения + Обратите внимание: это временная реализация функции. Это означает, что вы не сможете удалить свою историю местоположений, а опытные пользователи смогут просмотреть вашу историю местоположений даже после того, как вы перестанете делиться своим местоположением в этой комнате. + Сейчас используется %s. + Способ + + Найден %d способ. + Найдено %d способа. + Найдено %d способов. + Найдено %d способов. + + Другого способа, кроме фоновой синхронизации, не найдено. + Другого способа, кроме Google Play Service, не найдено. + Доступные способы + Способ оповещения + Выберите способ получения уведомлений + Сбросить способ оповещения + Фоновая синхронизация + Далее \ No newline at end of file From 48119604b94ce6a053a6f5b369aa21e25bac0aba Mon Sep 17 00:00:00 2001 From: Daniil Omelchenko Date: Mon, 4 Jul 2022 10:18:32 +0000 Subject: [PATCH 050/131] Translated using Weblate (Russian) Currently translated at 77.9% (53 of 68 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/ru/ --- fastlane/metadata/android/ru-RU/changelogs/40104040.txt | 2 ++ fastlane/metadata/android/ru-RU/changelogs/40104250.txt | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 fastlane/metadata/android/ru-RU/changelogs/40104040.txt create mode 100644 fastlane/metadata/android/ru-RU/changelogs/40104250.txt diff --git a/fastlane/metadata/android/ru-RU/changelogs/40104040.txt b/fastlane/metadata/android/ru-RU/changelogs/40104040.txt new file mode 100644 index 0000000000..00904bc548 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40104040.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: обновлён индикатор набора сообщения. Исправлены известные ошибки и улучшена стабильность. +Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.4.4 diff --git a/fastlane/metadata/android/ru-RU/changelogs/40104250.txt b/fastlane/metadata/android/ru-RU/changelogs/40104250.txt new file mode 100644 index 0000000000..57c0128d34 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40104250.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: исправлены известные проблемы и улучшена стабильность. +Полный список изменений: https://github.com/vector-im/element-android/releases From f469450ca4d2c58d7bd34ba3f8f635070de60c45 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 Jul 2022 16:07:12 +0200 Subject: [PATCH 051/131] Setup `nightly` buildType --- gradle.properties | 5 +++++ vector/build.gradle | 14 ++++++++++++++ vector/signature/nightly.keystore | Bin 0 -> 2217 bytes 3 files changed, 19 insertions(+) create mode 100644 vector/signature/nightly.keystore diff --git a/gradle.properties b/gradle.properties index 6de52be607..2af9214ed5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -32,3 +32,8 @@ signing.element.storePath=pathTo.keystore signing.element.storePassword=Secret signing.element.keyId=Secret signing.element.keyPassword=Secret + +# Dummy values for signing secrets / nightly +signing.element.nightly.storePassword=Secret +signing.element.nightly.keyId=Secret +signing.element.nightly.keyPassword=Secret diff --git a/vector/build.gradle b/vector/build.gradle index dd160f9574..45f1178c44 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -228,6 +228,12 @@ android { storeFile file('./signature/debug.keystore') storePassword 'android' } + nightly { + keyAlias project.property("signing.element.nightly.keyId") + keyPassword project.property("signing.element.nightly.keyPassword") + storeFile file('./signature/nightly.keystore') + storePassword project.property("signing.element.nightly.storePassword") + } release { keyAlias project.property("signing.element.keyId") keyPassword project.property("signing.element.keyPassword") @@ -268,6 +274,14 @@ android { } // signingConfig signingConfigs.release } + + nightly { + initWith release + applicationIdSuffix ".nightly" + resValue "string", "app_name", "Element nightly" + + signingConfig signingConfigs.nightly + } } flavorDimensions "store" diff --git a/vector/signature/nightly.keystore b/vector/signature/nightly.keystore new file mode 100644 index 0000000000000000000000000000000000000000..a0e9ba413be5ac9bb0b30a3088882a17c5aaa3bd GIT binary patch literal 2217 zcmchYX*3iH8^>oem@$~Lz9mLsm@s3@5;As@{hG*bFbK(#vSbu8L%gh&woO@0m-p}uc=fm@Ro)6FYpXdDlhpUIH0001VT)@8z=1+_a zB>DJ;21FjCxZ$b?G5`Pv0856jvAj?i1`31#UvkOKfAL%zCfsf@3k=4}x5b~?zt zS>4={6p7gyxhG_MH3I1zfN#teA(S*?B|lTZoZwGcKpAO{|6-@9w&bn|X7I6X9UW zGgo>k|S7|o`+xSx=*lAdWp;Q=Ux zA15drh_my;U4+SN9d9q4lp33dhOd*Z2-MkY1(9tRT}NpRtom%KN$z0kq@Qx(Qx3jOKDu&89wDBwS>C>K zS}=#~WW1Q_Ua44H(YPiwqf0TU;Nkz2{~b7L{7e91 zDnhYF?ifpSL=LCu7~go8I~nC4>SyT4=ExsBYBF!B5-)stlTsD6Vj4`65+38(wJVmL z5FUZVNEkcR2k7;Spb8PKQ-R&l6{@;9oXMSt0UusGY0oQ}uE}+M#)|pXMMnjd8$kRG zUz2sw_H_aK$51fLx1}JEtjzS5x)IjqO!|34JxKp4)wll0EICK(_LY>TFjd(#FIm|Q zhr#WvD${`dCl1*=%8Wy!6Zi|K|BdGEEl=cw8#)%!(vr*$OKG+qDcr_v zK1@cgFC=1vvH#XNRWx7TR{<1K%5w^!FnuP(Wb@_K0xS7yJc(k?~D86QxgZyXHs zP__BqigJ!iCDVP=fP6;qM&H%+XvXK6VT*QH9`8!?1NfUg*3L>a0@t}%F7LkB=B5Ua zNt-w~w!LLLmCJugKkmK$Gk*&vyG+Aqo8@?yS{M)V`$hAY2h1O z4DKQ&LA36JPa;Ahr;$Mf_ggiziYEzC`cDtfw>FiK52$hxJm2|WJ*Q|k7H{pZKxuQ$ z=!ELXK=<$ZyBn5QgEJ9dq;Ci+l5W3~p_OJLz(r0@^%<43J?e#E$30=rjcgjuGA+wG%m39=L zE*cLdVro=R}*3L|u$9X;XEMI^9w>NSS6jZSq007tp zO9ne)$sl|I7z6}?ARbHu0u}+~mP;^6*g*h+@MFUa#KE!LP_R7&dJ<%0gX24%A2(b) zP@@p{Ku_X7fRhJmLktWg-o%~6BLBMq%q zs^V0zN?5F;2%i#G^;htJzlaQ!{8g0W!~m0le8*7&gn`IFAfV!9WH+`4Z!T?In;Z#G z62JC(0rh*4Mo=sA9p~L^3!Gy*GLO^@LPNtoNXhFx8*6DOH8Ib^Cu{F|ZRTGuQu)^; zYv6KT)8&Q4lQY+8%RK?rA+cxsJ%co&<0tcDMzHj%Cgvs@9@^kSNEVl#Qv-d?CKSt@ zY<7{DYmbTq_LHY)pT4G_yT33Ntk7f^qCviL5!N5JUu-X54*D}qD^5`3eIq}IuXw57 z`cAP2(SwBy;P<25qJ=2)(@$|d+HpHP*y{@Q9k+%}lwZWVW=uFo7rrHqhX!9Qr3$5k zA@?>1`I5c&Rv|_RZ#Zwg6ryurN&g0YdzV}kF$8v+q#!|fF6h)Vz)lUEIv|)hv!(< zHU^_&BM);E!{t|J+j-x3!aKBF_p9iv?d-%|D{ac_9sF&gbX!p(Pk7OK_qTK3ZMbz< zcX(;uW9{M7+e0dKYGW2P=>q Date: Tue, 5 Jul 2022 16:09:18 +0200 Subject: [PATCH 052/131] Add google-services.json for nightly builds --- vector/src/gplay/nightly/google-services.json | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 vector/src/gplay/nightly/google-services.json diff --git a/vector/src/gplay/nightly/google-services.json b/vector/src/gplay/nightly/google-services.json new file mode 100644 index 0000000000..4cfa4dc036 --- /dev/null +++ b/vector/src/gplay/nightly/google-services.json @@ -0,0 +1,40 @@ +{ + "project_info": { + "project_number": "912726360885", + "firebase_url": "https://vector-alpha.firebaseio.com", + "project_id": "vector-alpha", + "storage_bucket": "vector-alpha.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:912726360885:android:4ef8f3a0021e774d", + "android_client_info": { + "package_name": "im.vector.app.nightly" + } + }, + "oauth_client": [ + { + "client_id": "912726360885-e87n3jva9uoj4vbidvijq78ebg02asv2.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyAFZX8IhIfgzdOZvxDP_ISO5WYoU7jmQ5c" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "912726360885-rsae0i66rgqt6ivnudu1pv4tksg9i8b2.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + } + ], + "configuration_version": "1" +} From 8434fb9a6476feb22252df8244768f353ce2caf1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 Jul 2022 16:11:44 +0200 Subject: [PATCH 053/131] Add fallback for submodules --- vector/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/build.gradle b/vector/build.gradle index 45f1178c44..5a34196893 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -279,7 +279,7 @@ android { initWith release applicationIdSuffix ".nightly" resValue "string", "app_name", "Element nightly" - + matchingFallbacks = ['release'] signingConfig signingConfigs.nightly } } From 0776d394bc5dca838d27e20f760081f49f41d89e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 Jul 2022 11:51:30 +0200 Subject: [PATCH 054/131] Add GitHub action to check for a towncrier file --- .github/workflows/quality.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index d7f5ce8b57..9f3825f715 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -203,3 +203,26 @@ jobs: name: detekt-report path: | */build/reports/detekt/detekt.html + + towncrier: + name: Check that there is at least one file for the changelog + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Python 3.8 + uses: actions/setup-python@v4 + with: + python-version: 3.8 + - name: Install towncrier + run: | + python3 -m pip install towncrier + - name: Run towncrier + run: | + # Fetch the pull request' base branch so towncrier will be able to + # compare the current branch with the base branch. + # Source: https://github.com/actions/checkout/#fetch-all-branches. + git fetch --no-tags origin +refs/heads/${BASE_BRANCH}:refs/remotes/origin/${BASE_BRANCH} + towncrier check --compare-with origin/${BASE_BRANCH} + env: + BASE_BRANCH: ${{ github.base_ref }} + if: github.event_name == 'pull_request' From 1e0799d5b005358d695d017ca561068902a8e133 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 Jul 2022 11:53:13 +0200 Subject: [PATCH 055/131] shorter name --- .github/workflows/quality.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 9f3825f715..e4b06a6348 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -205,7 +205,7 @@ jobs: */build/reports/detekt/detekt.html towncrier: - name: Check that there is at least one file for the changelog + name: Towncrier check runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 From ad76cbbc405a6c611f5e3e1486c64f9dfd9475a6 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 5 Jul 2022 13:22:52 +0100 Subject: [PATCH 056/131] adding tests around share intent handling --- .../attachments/MultiPickerIncomingFiles.kt | 37 ++++ .../attachments/ShareIntentHandler.kt | 40 +---- .../attachments/ShareIntentHandlerTest.kt | 166 ++++++++++++++++++ .../im/vector/app/test/fakes/FakeFunction1.kt | 36 ++++ .../im/vector/app/test/fakes/FakeIntent.kt | 35 ++++ .../fakes/FakeMultiPickerIncomingFiles.kt | 44 +++++ .../fixtures/ContentAttachmentDataFixture.kt | 29 +++ 7 files changed, 354 insertions(+), 33 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/attachments/MultiPickerIncomingFiles.kt create mode 100644 vector/src/test/java/im/vector/app/features/attachments/ShareIntentHandlerTest.kt create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeFunction1.kt create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeIntent.kt create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeMultiPickerIncomingFiles.kt create mode 100644 vector/src/test/java/im/vector/app/test/fixtures/ContentAttachmentDataFixture.kt diff --git a/vector/src/main/java/im/vector/app/features/attachments/MultiPickerIncomingFiles.kt b/vector/src/main/java/im/vector/app/features/attachments/MultiPickerIncomingFiles.kt new file mode 100644 index 0000000000..82da3a795f --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/attachments/MultiPickerIncomingFiles.kt @@ -0,0 +1,37 @@ +/* + * 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.attachments + +import android.content.Context +import android.content.Intent +import im.vector.lib.multipicker.MultiPicker +import javax.inject.Inject + +class MultiPickerIncomingFiles @Inject constructor( + private val context: Context, +) { + + fun image(intent: Intent) = MultiPicker.get(MultiPicker.IMAGE).getIncomingFiles(context, intent).map { it.toContentAttachmentData() } + + fun video(intent: Intent) = MultiPicker.get(MultiPicker.VIDEO).getIncomingFiles(context, intent).map { it.toContentAttachmentData() } + + fun media(intent: Intent) = MultiPicker.get(MultiPicker.MEDIA).getIncomingFiles(context, intent).map { it.toContentAttachmentData() } + + fun file(intent: Intent) = MultiPicker.get(MultiPicker.FILE).getIncomingFiles(context, intent).map { it.toContentAttachmentData() } + + fun audio(intent: Intent) = MultiPicker.get(MultiPicker.AUDIO).getIncomingFiles(context, intent).map { it.toContentAttachmentData() } +} diff --git a/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt b/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt index 06ca949025..8cd20d36c1 100644 --- a/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt +++ b/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt @@ -18,11 +18,12 @@ package im.vector.app.features.attachments import android.content.Context import android.content.Intent -import im.vector.lib.multipicker.MultiPicker import org.matrix.android.sdk.api.session.content.ContentAttachmentData import javax.inject.Inject -class ShareIntentHandler @Inject constructor() { +class ShareIntentHandler @Inject constructor( + private val multiPickerIncomingFiles: MultiPickerIncomingFiles, +) { /** * This methods aims to handle incoming share intents. @@ -33,38 +34,11 @@ class ShareIntentHandler @Inject constructor() { val type = intent.resolveType(context) ?: return false return when { type == "text/plain" -> handlePlainText(intent, onPlainText) - type.startsWith("image") -> { - onFile( - MultiPicker.get(MultiPicker.IMAGE).getIncomingFiles(context, intent).map { - it.toContentAttachmentData() - } - ) - true - } - type.startsWith("video") -> { - onFile( - MultiPicker.get(MultiPicker.VIDEO).getIncomingFiles(context, intent).map { - it.toContentAttachmentData() - } - ) - true - } - type.startsWith("audio") -> { - onFile( - MultiPicker.get(MultiPicker.AUDIO).getIncomingFiles(context, intent).map { - it.toContentAttachmentData() - } - ) - true - } - + type.startsWith("image") -> onFile(multiPickerIncomingFiles.image(intent)).let { true } + type.startsWith("video") -> onFile(multiPickerIncomingFiles.video(intent)).let { true } + type.startsWith("audio") -> onFile(multiPickerIncomingFiles.audio(intent)).let { true } type.startsWith("application") || type.startsWith("file") || type.startsWith("text") || type.startsWith("*") -> { - onFile( - MultiPicker.get(MultiPicker.FILE).getIncomingFiles(context, intent).map { - it.toContentAttachmentData() - } - ) - true + onFile(multiPickerIncomingFiles.file(intent)).let { true } } else -> false } diff --git a/vector/src/test/java/im/vector/app/features/attachments/ShareIntentHandlerTest.kt b/vector/src/test/java/im/vector/app/features/attachments/ShareIntentHandlerTest.kt new file mode 100644 index 0000000000..bb3aabf67f --- /dev/null +++ b/vector/src/test/java/im/vector/app/features/attachments/ShareIntentHandlerTest.kt @@ -0,0 +1,166 @@ +/* + * 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.attachments + +import android.content.Intent +import im.vector.app.test.fakes.FakeContext +import im.vector.app.test.fakes.FakeFunction1 +import im.vector.app.test.fakes.FakeIntent +import im.vector.app.test.fakes.FakeMultiPickerIncomingFiles +import im.vector.app.test.fixtures.ContentAttachmentDataFixture.aContentAttachmentData +import org.amshove.kluent.shouldBeEqualTo +import org.junit.Test +import org.matrix.android.sdk.api.session.content.ContentAttachmentData + +private val A_CONTEXT = FakeContext().instance +private const val A_PLAIN_TEXT_EXTRA = "plain text for sharing" +private val A_CONTENT_ATTACHMENT_LIST = listOf(aContentAttachmentData()) + +class ShareIntentHandlerTest { + + private val fakeMultiPickerIncomingFiles = FakeMultiPickerIncomingFiles() + private val onFile = FakeFunction1>() + private val onPlainText = FakeFunction1() + + private val shareIntentHandler = ShareIntentHandler(fakeMultiPickerIncomingFiles.instance) + + @Test + fun `given an unhandled sharing intent type, when handling intent, then is not handled`() { + val unknownShareIntent = FakeIntent().also { it.givenResolvesType(A_CONTEXT, "unknown/type") } + + val handled = handleIncomingShareIntent(unknownShareIntent) + + onFile.verifyNoInteractions() + onPlainText.verifyNoInteractions() + handled shouldBeEqualTo false + } + + @Test + fun `given a plain text sharing intent, when handling intent, then is handled and parses plain text content`() { + val plainTextShareIntent = FakeIntent().also { + it.givenResolvesType(A_CONTEXT, "text/plain") + it.givenCharSequenceExtra(key = Intent.EXTRA_TEXT, value = A_PLAIN_TEXT_EXTRA) + } + + val handled = handleIncomingShareIntent(plainTextShareIntent) + + onFile.verifyNoInteractions() + onPlainText.assertValue(A_PLAIN_TEXT_EXTRA) + handled shouldBeEqualTo true + } + + @Test + fun `given an empty plain text sharing intent, when handling intent, then is not handled`() { + val plainTextShareIntent = FakeIntent().also { + it.givenResolvesType(A_CONTEXT, "text/plain") + it.givenCharSequenceExtra(key = Intent.EXTRA_TEXT, value = "") + } + + val handled = handleIncomingShareIntent(plainTextShareIntent) + + onFile.verifyNoInteractions() + onPlainText.verifyNoInteractions() + handled shouldBeEqualTo false + } + + @Test + fun `given an image sharing intent, when handling intent, then is handled and parses image files`() { + val imageShareIntent = FakeIntent().also { it.givenResolvesType(A_CONTEXT, "image/png") } + fakeMultiPickerIncomingFiles.givenImageReturns(imageShareIntent.instance, A_CONTENT_ATTACHMENT_LIST) + + val handled = handleIncomingShareIntent(imageShareIntent) + + onFile.assertValue(A_CONTENT_ATTACHMENT_LIST) + onPlainText.verifyNoInteractions() + handled shouldBeEqualTo true + } + + @Test + fun `given an audio sharing intent, when handling intent, then is handled and parses audio files`() { + val audioShareIntent = FakeIntent().also { it.givenResolvesType(A_CONTEXT, "audio/mp3") } + fakeMultiPickerIncomingFiles.givenAudioReturns(audioShareIntent.instance, A_CONTENT_ATTACHMENT_LIST) + + val handled = handleIncomingShareIntent(audioShareIntent) + + onFile.assertValue(A_CONTENT_ATTACHMENT_LIST) + onPlainText.verifyNoInteractions() + handled shouldBeEqualTo true + } + + @Test + fun `given an video sharing intent, when handling intent, then is handled and parses video files`() { + val videoShareIntent = FakeIntent().also { it.givenResolvesType(A_CONTEXT, "video/mp4") } + fakeMultiPickerIncomingFiles.givenVideoReturns(videoShareIntent.instance, A_CONTENT_ATTACHMENT_LIST) + + val handled = handleIncomingShareIntent(videoShareIntent) + + onFile.assertValue(A_CONTENT_ATTACHMENT_LIST) + onPlainText.verifyNoInteractions() + handled shouldBeEqualTo true + } + + @Test + fun `given a file sharing intent, when handling intent, then is handled and parses files`() { + val fileShareIntent = FakeIntent().also { it.givenResolvesType(A_CONTEXT, "file/*") } + fakeMultiPickerIncomingFiles.givenFileReturns(fileShareIntent.instance, A_CONTENT_ATTACHMENT_LIST) + + val handled = handleIncomingShareIntent(fileShareIntent) + + onFile.assertValue(A_CONTENT_ATTACHMENT_LIST) + onPlainText.verifyNoInteractions() + handled shouldBeEqualTo true + } + + @Test + fun `given a application sharing intent, when handling intent, then is handled and parses files`() { + val fileShareIntent = FakeIntent().also { it.givenResolvesType(A_CONTEXT, "application/apk") } + fakeMultiPickerIncomingFiles.givenFileReturns(fileShareIntent.instance, A_CONTENT_ATTACHMENT_LIST) + + handleIncomingShareIntent(fileShareIntent) + + onFile.assertValue(A_CONTENT_ATTACHMENT_LIST) + onPlainText.verifyNoInteractions() + } + + @Test + fun `given a text sharing intent, when handling intent, then is handled and parses text files`() { + val fileShareIntent = FakeIntent().also { it.givenResolvesType(A_CONTEXT, "text/ics") } + fakeMultiPickerIncomingFiles.givenFileReturns(fileShareIntent.instance, A_CONTENT_ATTACHMENT_LIST) + + val handled = handleIncomingShareIntent(fileShareIntent) + + onFile.assertValue(A_CONTENT_ATTACHMENT_LIST) + onPlainText.verifyNoInteractions() + handled shouldBeEqualTo true + } + + @Test + fun `given a wildcard sharing intent, when handling intent, then is handled and parses files`() { + val fileShareIntent = FakeIntent().also { it.givenResolvesType(A_CONTEXT, "*/*") } + fakeMultiPickerIncomingFiles.givenFileReturns(fileShareIntent.instance, A_CONTENT_ATTACHMENT_LIST) + + val handled = handleIncomingShareIntent(fileShareIntent) + + onFile.assertValue(A_CONTENT_ATTACHMENT_LIST) + onPlainText.verifyNoInteractions() + handled shouldBeEqualTo true + } + + private fun handleIncomingShareIntent(intent: FakeIntent): Boolean { + return shareIntentHandler.handleIncomingShareIntent(A_CONTEXT, intent.instance, onFile.capture, onPlainText.capture) + } +} diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeFunction1.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeFunction1.kt new file mode 100644 index 0000000000..434a661e5f --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeFunction1.kt @@ -0,0 +1,36 @@ +/* + * 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 org.amshove.kluent.shouldBeEqualTo + +class FakeFunction1 { + + private lateinit var capturedValue: T + + val capture: (T) -> Unit = { + capturedValue = it + } + + fun verifyNoInteractions() { + this::capturedValue.isInitialized shouldBeEqualTo false + } + + fun assertValue(value: T) { + capturedValue shouldBeEqualTo value + } +} diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeIntent.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeIntent.kt new file mode 100644 index 0000000000..1b3ce3538e --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeIntent.kt @@ -0,0 +1,35 @@ +/* + * 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 android.content.Context +import android.content.Intent +import io.mockk.every +import io.mockk.mockk + +class FakeIntent { + + val instance = mockk() + + fun givenResolvesType(context: Context, type: String?) { + every { instance.resolveType(context) } returns type + } + + fun givenCharSequenceExtra(key: String, value: CharSequence) { + every { instance.getCharSequenceExtra(key) } returns value + } +} diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeMultiPickerIncomingFiles.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeMultiPickerIncomingFiles.kt new file mode 100644 index 0000000000..00adc83e5c --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeMultiPickerIncomingFiles.kt @@ -0,0 +1,44 @@ +/* + * 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 android.content.Intent +import im.vector.app.features.attachments.MultiPickerIncomingFiles +import io.mockk.every +import io.mockk.mockk +import org.matrix.android.sdk.api.session.content.ContentAttachmentData + +class FakeMultiPickerIncomingFiles { + + val instance = mockk() + + fun givenFileReturns(intent: Intent, result: List) { + every { instance.file(intent) } returns result + } + + fun givenAudioReturns(intent: Intent, result: List) { + every { instance.audio(intent) } returns result + } + + fun givenVideoReturns(intent: Intent, result: List) { + every { instance.video(intent) } returns result + } + + fun givenImageReturns(intent: Intent, result: List) { + every { instance.image(intent) } returns result + } +} diff --git a/vector/src/test/java/im/vector/app/test/fixtures/ContentAttachmentDataFixture.kt b/vector/src/test/java/im/vector/app/test/fixtures/ContentAttachmentDataFixture.kt new file mode 100644 index 0000000000..731d6b32d0 --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fixtures/ContentAttachmentDataFixture.kt @@ -0,0 +1,29 @@ +/* + * 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.fixtures + +import im.vector.app.test.fakes.FakeUri +import org.matrix.android.sdk.api.session.content.ContentAttachmentData + +object ContentAttachmentDataFixture { + + fun aContentAttachmentData() = ContentAttachmentData( + type = ContentAttachmentData.Type.AUDIO, + queryUri = FakeUri().instance, + mimeType = null, + ) +} From d19346b9c65ac45a0e5fd4cc728b576374f1a031 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 5 Jul 2022 13:46:24 +0100 Subject: [PATCH 057/131] fixing formatting --- .../vector/app/features/attachments/MultiPickerIncomingFiles.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/attachments/MultiPickerIncomingFiles.kt b/vector/src/main/java/im/vector/app/features/attachments/MultiPickerIncomingFiles.kt index 82da3a795f..0f2dad541c 100644 --- a/vector/src/main/java/im/vector/app/features/attachments/MultiPickerIncomingFiles.kt +++ b/vector/src/main/java/im/vector/app/features/attachments/MultiPickerIncomingFiles.kt @@ -32,6 +32,6 @@ class MultiPickerIncomingFiles @Inject constructor( fun media(intent: Intent) = MultiPicker.get(MultiPicker.MEDIA).getIncomingFiles(context, intent).map { it.toContentAttachmentData() } fun file(intent: Intent) = MultiPicker.get(MultiPicker.FILE).getIncomingFiles(context, intent).map { it.toContentAttachmentData() } - + fun audio(intent: Intent) = MultiPicker.get(MultiPicker.AUDIO).getIncomingFiles(context, intent).map { it.toContentAttachmentData() } } From 59ef8e10c8e649a8a2b9226cead1291e68416358 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 6 Jul 2022 12:02:45 +0100 Subject: [PATCH 058/131] injecting the context directly to the handler --- .../im/vector/app/features/attachments/ShareIntentHandler.kt | 3 ++- .../vector/app/features/home/room/detail/TimelineFragment.kt | 2 +- .../im/vector/app/features/share/IncomingShareFragment.kt | 1 - .../vector/app/features/attachments/ShareIntentHandlerTest.kt | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt b/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt index 8cd20d36c1..1d722c2341 100644 --- a/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt +++ b/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt @@ -23,6 +23,7 @@ import javax.inject.Inject class ShareIntentHandler @Inject constructor( private val multiPickerIncomingFiles: MultiPickerIncomingFiles, + private val context: Context, ) { /** @@ -30,7 +31,7 @@ class ShareIntentHandler @Inject constructor( * * @return true if it can handle the intent data, false otherwise */ - fun handleIncomingShareIntent(context: Context, intent: Intent, onFile: (List) -> Unit, onPlainText: (String) -> Unit): Boolean { + fun handleIncomingShareIntent(intent: Intent, onFile: (List) -> Unit, onPlainText: (String) -> Unit): Boolean { val type = intent.resolveType(context) ?: return false return when { type == "text/plain" -> handlePlainText(intent, onPlainText) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt index 9468af7726..a3eff137c8 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt @@ -1619,7 +1619,7 @@ class TimelineFragment @Inject constructor( private fun sendUri(uri: Uri): Boolean { val shareIntent = Intent(Intent.ACTION_SEND, uri) - val isHandled = shareIntentHandler.handleIncomingShareIntent(requireContext(), shareIntent, ::onContentAttachmentsReady, onPlainText = { + val isHandled = shareIntentHandler.handleIncomingShareIntent(shareIntent, ::onContentAttachmentsReady, onPlainText = { fatalError("Should not happen as we're generating a File based share Intent", vectorPreferences.failFast()) }) if (!isHandled) { diff --git a/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt b/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt index a113c8105d..3f8923dd68 100644 --- a/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt +++ b/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt @@ -116,7 +116,6 @@ class IncomingShareFragment @Inject constructor( } private fun handleIncomingShareIntent(intent: Intent) = shareIntentHandler.handleIncomingShareIntent( - requireContext(), intent, onFile = { val sharedData = SharedData.Attachments(it) diff --git a/vector/src/test/java/im/vector/app/features/attachments/ShareIntentHandlerTest.kt b/vector/src/test/java/im/vector/app/features/attachments/ShareIntentHandlerTest.kt index bb3aabf67f..d2fba95eee 100644 --- a/vector/src/test/java/im/vector/app/features/attachments/ShareIntentHandlerTest.kt +++ b/vector/src/test/java/im/vector/app/features/attachments/ShareIntentHandlerTest.kt @@ -36,7 +36,7 @@ class ShareIntentHandlerTest { private val onFile = FakeFunction1>() private val onPlainText = FakeFunction1() - private val shareIntentHandler = ShareIntentHandler(fakeMultiPickerIncomingFiles.instance) + private val shareIntentHandler = ShareIntentHandler(fakeMultiPickerIncomingFiles.instance, A_CONTEXT) @Test fun `given an unhandled sharing intent type, when handling intent, then is not handled`() { @@ -161,6 +161,6 @@ class ShareIntentHandlerTest { } private fun handleIncomingShareIntent(intent: FakeIntent): Boolean { - return shareIntentHandler.handleIncomingShareIntent(A_CONTEXT, intent.instance, onFile.capture, onPlainText.capture) + return shareIntentHandler.handleIncomingShareIntent(intent.instance, onFile.capture, onPlainText.capture) } } From 169ac9d0a08da3ad0acddaf74c013eb2733279f8 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 6 Jul 2022 12:06:17 +0100 Subject: [PATCH 059/131] updating the known SDK mimetypes and making use of them for the intent switches --- .../matrix/android/sdk/api/util/MimeTypes.kt | 6 ++++++ .../features/attachments/ShareIntentHandler.kt | 18 +++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MimeTypes.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MimeTypes.kt index ef47775f1b..5ec0dedadf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MimeTypes.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MimeTypes.kt @@ -33,9 +33,15 @@ object MimeTypes { const val Ogg = "audio/ogg" + const val PlainText = "text/plain" + fun String?.normalizeMimeType() = if (this == BadJpg) Jpeg else this fun String?.isMimeTypeImage() = this?.startsWith("image/").orFalse() fun String?.isMimeTypeVideo() = this?.startsWith("video/").orFalse() fun String?.isMimeTypeAudio() = this?.startsWith("audio/").orFalse() + fun String?.isMimeTypeApplication() = this?.startsWith("application/").orFalse() + fun String?.isMimeTypeFile() = this?.startsWith("file/").orFalse() + fun String?.isMimeTypeText() = this?.startsWith("text/").orFalse() + fun String?.isMimeTypeAny() = this?.startsWith("*/").orFalse() } diff --git a/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt b/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt index 1d722c2341..18caba10d9 100644 --- a/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt +++ b/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt @@ -19,6 +19,14 @@ package im.vector.app.features.attachments import android.content.Context import android.content.Intent import org.matrix.android.sdk.api.session.content.ContentAttachmentData +import org.matrix.android.sdk.api.util.MimeTypes +import org.matrix.android.sdk.api.util.MimeTypes.isMimeTypeAny +import org.matrix.android.sdk.api.util.MimeTypes.isMimeTypeApplication +import org.matrix.android.sdk.api.util.MimeTypes.isMimeTypeAudio +import org.matrix.android.sdk.api.util.MimeTypes.isMimeTypeFile +import org.matrix.android.sdk.api.util.MimeTypes.isMimeTypeImage +import org.matrix.android.sdk.api.util.MimeTypes.isMimeTypeText +import org.matrix.android.sdk.api.util.MimeTypes.isMimeTypeVideo import javax.inject.Inject class ShareIntentHandler @Inject constructor( @@ -34,11 +42,11 @@ class ShareIntentHandler @Inject constructor( fun handleIncomingShareIntent(intent: Intent, onFile: (List) -> Unit, onPlainText: (String) -> Unit): Boolean { val type = intent.resolveType(context) ?: return false return when { - type == "text/plain" -> handlePlainText(intent, onPlainText) - type.startsWith("image") -> onFile(multiPickerIncomingFiles.image(intent)).let { true } - type.startsWith("video") -> onFile(multiPickerIncomingFiles.video(intent)).let { true } - type.startsWith("audio") -> onFile(multiPickerIncomingFiles.audio(intent)).let { true } - type.startsWith("application") || type.startsWith("file") || type.startsWith("text") || type.startsWith("*") -> { + type == MimeTypes.PlainText -> handlePlainText(intent, onPlainText) + type.isMimeTypeImage() -> onFile(multiPickerIncomingFiles.image(intent)).let { true } + type.isMimeTypeVideo() -> onFile(multiPickerIncomingFiles.video(intent)).let { true } + type.isMimeTypeAudio() -> onFile(multiPickerIncomingFiles.audio(intent)).let { true } + type.isMimeTypeApplication() || type.isMimeTypeFile() || type.isMimeTypeText() || type.isMimeTypeAny() -> { onFile(multiPickerIncomingFiles.file(intent)).let { true } } else -> false From ea5b2b34339428b800735beddb31015ffe039734 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 Jul 2022 15:36:01 +0200 Subject: [PATCH 060/131] Add sources for nightly. Use release version, change AnalyticsConfig.kt and shortcuts.xml. --- vector/build.gradle | 4 ++++ vector/src/nightly/res/xml/shortcuts.xml | 7 +++++++ .../release/java/im/vector/app/config/AnalyticsConfig.kt | 7 ++++++- 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 vector/src/nightly/res/xml/shortcuts.xml diff --git a/vector/build.gradle b/vector/build.gradle index 5a34196893..7bdc496c91 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -348,6 +348,10 @@ android { test { java.srcDirs += "src/sharedTest/java" } + // Add sourceSets for `release` version when building `nightly` + nightly { + java.srcDirs += "src/release/java" + } } buildFeatures { diff --git a/vector/src/nightly/res/xml/shortcuts.xml b/vector/src/nightly/res/xml/shortcuts.xml new file mode 100644 index 0000000000..f3056d0f8c --- /dev/null +++ b/vector/src/nightly/res/xml/shortcuts.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/vector/src/release/java/im/vector/app/config/AnalyticsConfig.kt b/vector/src/release/java/im/vector/app/config/AnalyticsConfig.kt index 7f7ef1a54e..e1427338b2 100644 --- a/vector/src/release/java/im/vector/app/config/AnalyticsConfig.kt +++ b/vector/src/release/java/im/vector/app/config/AnalyticsConfig.kt @@ -19,8 +19,13 @@ package im.vector.app.config import im.vector.app.BuildConfig import im.vector.app.features.analytics.AnalyticsConfig +private val allowedPackageList = listOf( + "im.vector.app", + "im.vector.app.nightly", +) + val analyticsConfig: AnalyticsConfig = object : AnalyticsConfig { - override val isEnabled = BuildConfig.APPLICATION_ID == "im.vector.app" + override val isEnabled = BuildConfig.APPLICATION_ID in allowedPackageList override val postHogHost = "https://posthog.hss.element.io" override val postHogApiKey = "phc_Jzsm6DTm6V2705zeU5dcNvQDlonOR68XvX2sh1sEOHO" override val policyLink = "https://element.io/cookie-policy" From a030769aeabeaff32dac3d9a12cfd24b6a49b7a8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 Jul 2022 16:29:47 +0200 Subject: [PATCH 061/131] Change icon background color for nightly build --- vector/build.gradle | 3 +++ vector/src/main/res/drawable/ic_launcher_background.xml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/vector/build.gradle b/vector/build.gradle index 7bdc496c91..a64d64b377 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -246,6 +246,7 @@ android { debug { applicationIdSuffix ".debug" resValue "string", "app_name", "Element dbg" + resValue "color", "launcher_background", "#0DBD8B" buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false" // Set to true if you want to enable strict mode in debug @@ -260,6 +261,7 @@ android { release { resValue "string", "app_name", "Element" + resValue "color", "launcher_background", "#0DBD8B" buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false" buildConfigField "boolean", "ENABLE_STRICT_MODE_LOGS", "false" @@ -279,6 +281,7 @@ android { initWith release applicationIdSuffix ".nightly" resValue "string", "app_name", "Element nightly" + resValue "color", "launcher_background", "#07007E" matchingFallbacks = ['release'] signingConfig signingConfigs.nightly } diff --git a/vector/src/main/res/drawable/ic_launcher_background.xml b/vector/src/main/res/drawable/ic_launcher_background.xml index f58c9aeb53..0792f1686b 100644 --- a/vector/src/main/res/drawable/ic_launcher_background.xml +++ b/vector/src/main/res/drawable/ic_launcher_background.xml @@ -5,6 +5,6 @@ android:viewportHeight="108"> From 5793a38774101a14d50d53680c39bcd9830a6673 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 Jul 2022 17:11:52 +0200 Subject: [PATCH 062/131] Add label for rageshake to know the build type, in particular to know if it's a nightly build. --- .../main/java/im/vector/app/features/rageshake/BugReporter.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt index 09453e5b02..e2e5ee2c6e 100755 --- a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt +++ b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt @@ -346,6 +346,9 @@ class BugReporter @Inject constructor( // Special for Element builder.addFormDataPart("label", "[Element]") + // Possible values for BuildConfig.BUILD_TYPE: "debug", "nightly", "release". + builder.addFormDataPart("label", BuildConfig.BUILD_TYPE) + when (reportType) { ReportType.BUG_REPORT -> { /* nop */ From 388a38010141e4b6aa0a8957e11b6a4fde331eb7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 Jul 2022 17:50:01 +0200 Subject: [PATCH 063/131] Add "-nightly" suffix to version name --- vector/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/vector/build.gradle b/vector/build.gradle index a64d64b377..652f90ab88 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -280,6 +280,7 @@ android { nightly { initWith release applicationIdSuffix ".nightly" + versionNameSuffix "-nightly" resValue "string", "app_name", "Element nightly" resValue "color", "launcher_background", "#07007E" matchingFallbacks = ['release'] From 11b2cd3dc0985398a02f8bf6780a590dfc3b2504 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 Jul 2022 00:15:32 +0200 Subject: [PATCH 064/131] Configure Firebase appdistribution plugin --- build.gradle | 1 + vector/build.gradle | 20 +++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 61027a0bff..e8472097d5 100644 --- a/build.gradle +++ b/build.gradle @@ -24,6 +24,7 @@ buildscript { classpath libs.gradle.gradlePlugin classpath libs.gradle.kotlinPlugin classpath libs.gradle.hiltPlugin + classpath 'com.google.firebase:firebase-appdistribution-gradle:3.0.2' classpath 'com.google.gms:google-services:4.3.13' classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.4.0.2513' classpath 'com.google.android.gms:oss-licenses-plugin:0.10.5' diff --git a/vector/build.gradle b/vector/build.gradle index 652f90ab88..a4a08c4522 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -1,6 +1,7 @@ import com.android.build.OutputFile apply plugin: 'com.android.application' +apply plugin: 'com.google.firebase.appdistribution' apply plugin: 'com.google.android.gms.oss-licenses-plugin' apply plugin: 'kotlin-android' apply plugin: 'kotlin-parcelize' @@ -229,10 +230,10 @@ android { storePassword 'android' } nightly { - keyAlias project.property("signing.element.nightly.keyId") - keyPassword project.property("signing.element.nightly.keyPassword") + keyAlias System.env.ELEMENT_ANDROID_NIGHTLY_KEYID ?: project.property("signing.element.nightly.keyId") + keyPassword System.env.ELEMENT_ANDROID_NIGHTLY_KEYPASSWORD ?: project.property("signing.element.nightly.keyPassword") storeFile file('./signature/nightly.keystore') - storePassword project.property("signing.element.nightly.storePassword") + storePassword System.env.ELEMENT_ANDROID_NIGHTLY_STOREPASSWORD ?: project.property("signing.element.nightly.storePassword") } release { keyAlias project.property("signing.element.keyId") @@ -285,6 +286,19 @@ android { resValue "color", "launcher_background", "#07007E" matchingFallbacks = ['release'] signingConfig signingConfigs.nightly + firebaseAppDistribution { + artifactType = "APK" + // We upload the universal APK to fix this error: + // "App Distribution found more than 1 output file for this variant. + // Please contact firebase-support@google.com for help using APK splits with App Distribution." + artifactPath = "$rootDir/vector/build/outputs/apk/gplay/nightly/vector-gplay-universal-nightly.apk" + // This file will be generated by the GitHub action + releaseNotesFile = "CHANGES_NIGHTLY.md" + groups = "external-testers" + // This should not be required, but if I do not add the appId, I get this error: + // "App Distribution halted because it had a problem uploading the APK: [404] Requested entity was not found." + appId = "1:912726360885:android:efd8545af52a9f9300427c" + } } } From cdaec0e293dbf2b324151b51406f993d61a869a0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 Jul 2022 11:17:03 +0200 Subject: [PATCH 065/131] Add GitHub action to build and publish the nightly build. --- .github/workflows/nightly.yml | 48 +++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 .github/workflows/nightly.yml diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml new file mode 100644 index 0000000000..483291de1f --- /dev/null +++ b/.github/workflows/nightly.yml @@ -0,0 +1,48 @@ +name: Build and release nightly APK + +on: + schedule: + # Every nights at 4 + - cron: "0 4 * * *" + +env: + CI_GRADLE_ARG_PROPERTIES: > + -Porg.gradle.jvmargs=-Xmx4g + -Porg.gradle.parallel=false + --no-daemon + +jobs: + nightly: + name: Build and publish nightly Gplay APK to Firebase + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Python 3.8 + uses: actions/setup-python@v4 + with: + python-version: 3.8 + - uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Install towncrier + run: | + python3 -m pip install towncrier + - name: Prepare changelog file + run: | + mv towncrier.toml towncrier.toml.bak + sed 's/CHANGES\.md/CHANGES_NIGHTLY\.md/' towncrier.toml.bak > towncrier.toml + rm towncrier.toml.bak + yes n | towncrier --version nightly + - name: Build and upload Gplay Nightly APK + run: | + ./gradlew assembleGplayNightly appDistributionUploadGplayNightly $CI_GRADLE_ARG_PROPERTIES --stacktrace + env: + ELEMENT_ANDROID_NIGHTLY_KEYID: ${{ secrets.ELEMENT_ANDROID_NIGHTLY_KEYID }} + ELEMENT_ANDROID_NIGHTLY_KEYPASSWORD: ${{ secrets.ELEMENT_ANDROID_NIGHTLY_KEYPASSWORD }} + ELEMENT_ANDROID_NIGHTLY_STOREPASSWORD: ${{ secrets.ELEMENT_ANDROID_NIGHTLY_STOREPASSWORD }} + FIREBASE_TOKEN: ${{ secrets.ELEMENT_ANDROID_NIGHTLY_FIREBASE_TOKEN }} From 253480fd2b8ea4453966482ea26badca7dd65a95 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 Jul 2022 11:08:19 +0200 Subject: [PATCH 066/131] Changelog --- changelog.d/6478.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6478.misc diff --git a/changelog.d/6478.misc b/changelog.d/6478.misc new file mode 100644 index 0000000000..52bc4a011d --- /dev/null +++ b/changelog.d/6478.misc @@ -0,0 +1 @@ +Nightly build publication on Firebase From b3e86129e90465a4726275eb6b6da2203f74a358 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 Jul 2022 17:00:09 +0200 Subject: [PATCH 067/131] `initWith release` does not take care of `postprocessing` block, so rather do some copy paste, to avoid a warning about values being replaced --- vector/build.gradle | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/vector/build.gradle b/vector/build.gradle index a4a08c4522..4de97199b4 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -279,11 +279,22 @@ android { } nightly { - initWith release applicationIdSuffix ".nightly" versionNameSuffix "-nightly" resValue "string", "app_name", "Element nightly" resValue "color", "launcher_background", "#07007E" + + buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false" + buildConfigField "boolean", "ENABLE_STRICT_MODE_LOGS", "false" + + postprocessing { + removeUnusedCode true + removeUnusedResources true + // We do not activate obfuscation as it makes it hard then to read crash reports, and it's a bit useless on an open source project :) + obfuscate false + optimizeCode true + proguardFiles 'proguard-rules.pro' + } matchingFallbacks = ['release'] signingConfig signingConfigs.nightly firebaseAppDistribution { From de0c4f3f67d00fde379b0035b454e7eb8fe999ac Mon Sep 17 00:00:00 2001 From: John Doe Date: Wed, 6 Jul 2022 08:14:34 +0000 Subject: [PATCH 068/131] Translated using Weblate (Spanish) Currently translated at 98.8% (2233 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/es/ --- vector/src/main/res/values-es/strings.xml | 38 ++++++++++++++++++++--- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/vector/src/main/res/values-es/strings.xml b/vector/src/main/res/values-es/strings.xml index 51ddac7093..f4ed0d570b 100644 --- a/vector/src/main/res/values-es/strings.xml +++ b/vector/src/main/res/values-es/strings.xml @@ -742,7 +742,7 @@ Silencioso Por favor introduzca un nombre de usuario. %1$s: %2$s - %d+ + +%d No se ha encontrado ningún APK válido de Servicios de Google Play. Las notificaciones podrían no funcionar correctamente. Por favor introduzca una contraseña La contraseña que has introducido es muy débil @@ -855,9 +855,9 @@ Invitado por %s No tienes más mensajes sin leer Conversaciones - Tus conversaciones se mostrarán aquí. Toque + en la derecha para comenzar. + Tus conversaciones se mostrarán aquí. Toque el + en la esquina inferior derecha para comenzar. Salas - Tus salas se mostrarán aquí. Pulsa el botón + abajo a la derecha para buscar o crear salas propias. + Tus salas se mostrarán aquí. Pulsa el botón + abajo en la esquina inferior derecha para buscar o crear salas propias. Reacciones De acuerdo Añadir reacción @@ -2496,4 +2496,34 @@ sec min h - + Activar compartir ubicación + Nota: esta funcionalidad es experimental, y su funcionamiento es todavía provisional. Esto significa que no podrás eliminar el historial de tu ubicación, y usuarios con conocimientos avanzados podrán verlo en esta sala incluso cuando dejes de compartir en tiempo real. + Compartir ubicación en tiempo real + Puerta de enlace actual: %s + Puerta de enlace + No se pudo encontrar el punto final. + Punto final actual: %s + Punto final + Actualmente usando %s. + Método + + Se encontró %d método. + Se encontraron %d métodos. + + No se ha encontrado otro método aparte de la sincronización en segundo plano. + No se ha encontrado otro método aparte de los servicios de Google Play. + Métodos disponibles + Método de notificación + Sincronización en segundo plano + Servicios de Google + Elija como recibir notificaciones + No se pudo habilitar la identificación biométrica. + La identificación biométrica fue desactivada debido a que un método de identificación biométrica fue añadido recientemente. Puede activarlo de nuevo en Preferencias. + Reestablecer método de notificación + Etiqueta de perfil: + Ha ocurrido un error al registrar el token del punto final al servidor doméstico: +\n%1$s + El destino se ha registrado de forma satisfactoria al servidor doméstico. + Registración de punto final + Siguiente + \ No newline at end of file From d8533b0abfb64a4f1a7c16fff2e3d8fc59e83d3d Mon Sep 17 00:00:00 2001 From: Mateus Rodrigues Costa Date: Tue, 5 Jul 2022 16:19:13 +0000 Subject: [PATCH 069/131] Translated using Weblate (Portuguese (Brazil)) Currently translated at 99.8% (2257 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/pt_BR/ --- vector/src/main/res/values-pt-rBR/strings.xml | 120 +++++++++++------- 1 file changed, 75 insertions(+), 45 deletions(-) diff --git a/vector/src/main/res/values-pt-rBR/strings.xml b/vector/src/main/res/values-pt-rBR/strings.xml index e577a8bfb7..ee73b43824 100644 --- a/vector/src/main/res/values-pt-rBR/strings.xml +++ b/vector/src/main/res/values-pt-rBR/strings.xml @@ -3,32 +3,32 @@ convite de %s %1$s convidou %2$s %1$s convidou você - %1$s juntou-se à sala + %1$s entrou na sala %1$s saiu da sala - %1$s rejeitou o convite + %1$s recusou o convite %1$s expulsou %2$s %1$s desbaniu %2$s %1$s baniu %2$s - %1$s retirou o convite de %2$s - %1$s mudou o avatar dela(e) - %1$s definiu o nome de exibição dela(e) para %2$s - %1$s mudou o nome de exibição dela(e) de %2$s para %3$s - %1$s removeu o nome de exibição dela(e) (era %2$s) + %1$s desfez o convite de %2$s + %1$s mudou seu avatar + %1$s definiu seu nome de exibição para %2$s + %1$s mudou seu nome de exibição de %2$s para %3$s + %1$s removeu seu nome de exibição (era %2$s) %1$s mudou o tópico para: %2$s %1$s mudou o nome da sala para: %2$s %s começou uma chamada de vídeo. %s começou uma chamada de voz. %s atendeu a chamada. - %s terminou a chamada. - %1$s fez histórico da sala futuro visível para %2$s - todos os membros da sala, do ponto que foram convidados. - todos os mebros da sala, do ponto que se juntaram. + %s encerrou a chamada. + %1$s deixou o histórico futuro da sala visível para %2$s + todos os membros da sala, desde quando foram convidadas/os. + todos os membros da sala, a partir de quando entraram. todos os membros da sala. qualquer pessoa. (avatar mudou também) %1$s removeu o nome da sala %1$s removeu o tópico da sala - %1$s enviou um convite para %2$s para se juntar à sala + %1$s enviou um convite para %2$s para entrar na sala %1$s aceitou o convite para %2$s ** Incapaz de decriptar: %s ** O dispositivo do/da enviador(a) não nos enviou as chaves para esta mensagem. @@ -43,13 +43,13 @@ %1$s criou a sala Você criou a sala Você convidou %1$s - Você juntou-se à sala + Você entrou na sala Você saiu da sala - Você rejeitou o convite + Você recusou o convite Você expulsou %1$s Você desbaniu %1$s Você baniu %1$s - Você retirou o convite de %1$s + Você desfez o convite de %1$s Você mudou seu avatar Você definiu seu nome de exibição para %1$s Você mudou seu nome de exibição de %1$s para %2$s @@ -63,15 +63,15 @@ %s enviou dados para configurar a chamada. Você enviou dados para configurar a chamada. Você atendeu a chamada. - Você terminou a chamada. - Você fez histórico da sala futuro visível para %1$s + Você encerrou a chamada. + Você deixou o histórico futuro da sala visível para %1$s %s fez o upgrade desta sala. Você fez o upgrade desta sala. Você removeu o nome da sala Você removeu o tópico da sala %1$s removeu o avatar da sala Você removeu o avatar da sala - Você enviou um convite para %1$s para se juntar à sala + Você enviou um convite para %1$s para entrar na sala %1$s revogou o convite para %2$s para entrar na sala Você revogou o convite para %1$s para entrar na sala Você aceitou o convite para %1$s @@ -92,12 +92,12 @@ Sinc inicial: \nImportando conta… Sinc inicial: -\nImportando crypto +\nImportando criptografia Sinc inicial: \nImportando Salas Sinc inicial: \nCarregando suas conversas -\nSe você tem se juntado a um monte de salas, isto poderia levar um momento +\nSe você entrou em muitas salas, isso pode demorar Sinc inicial: \nImportando salas convidadas Sinc inicial: @@ -112,8 +112,8 @@ %1$s convidou %2$s. Razão: %3$s Você convidou %1$s. Razão: %2$s %1$s convidou você. Razão: %2$s - %1$s juntou-se à sala. Razão: %2$s - Você juntou-se à sala. Razão: %1$s + %1$s entrou na sala. Razão: %2$s + Você entrou na sala. Razão: %1$s %1$s saiu da sala. Razão: %2$s Você saiu da sala. Razão: %1$s %1$s rejeitou o convite. Razão: %2$s @@ -164,20 +164,20 @@ %1$s tem permitido visitantes se juntarem aqui. Você saiu. Razão: %1$s %1$s saiu. Razão: %2$s - Você juntou-se. Razão: %1$s - %1$s juntou-se. Razão: %2$s + Você entrou. Razão: %1$s + %1$s entrou. Razão: %2$s Você revogou o convite para %1$s %1$s revogou o convite para %2$s Você convidou %1$s %1$s convidou %2$s Você fez o upgrade aqui. %s fez o upgrade aqui. - Você deixou mensagens futuras vísiveis para %1$s - %1$s fez mensagens futuras visíveis para %2$s + Você deixou as mensagens futuras visíveis para %1$s + %1$s deixou as mensagens futuras visíveis para %2$s Você saiu da sala %1$s saiu da sala - Você juntou-se - %1$s juntou-se + Você entrou + %1$s entrou Você criou a discussão %1$s criou a discussão Sala vazia (era %s) @@ -411,7 +411,7 @@ Qualquer pessoa Membros somente (desde o ponto no tempo de seleção desta opção) Membros somente (desde que eles foram convidados) - Membros somente (desde que eles se juntaram) + Somente membros (desde que eles entraram) Usuárias(os) banidas(os) Avançadas ID interno desta sala @@ -999,7 +999,7 @@ CRIAR Nome Pública - Qualquer pessoa vai ser capaz de se juntar a esta sala + Qualquer pessoa poderá se juntar a esta sala Um erro ocorreu ao obter info de confiança Um erro ocorreu ao obter dados de backup de chaves Importar as chaves e2e de arquivo \"%1$s\". @@ -1012,7 +1012,7 @@ Regras de Push Nenhuma regra de push definida Nenhum gateway de push registrado - app_id: + push_key: app_display_name: session_name: @@ -1644,7 +1644,7 @@ Gerenciar Integrações Nenhum widget ativo - A sala tem sido criada, mas alguns convites não têm sido enviados pela seguinte razão: + A sala foi criada, mas alguns convites não foram enviados pelo seguinte motivo: \n \n%s @@ -1704,7 +1704,7 @@ Somente faça isto se você não tem nenhum outro dispositivo com o qual você pode verificar este dispositivo. Resettar tudo Esqueceu ou perdeu todas as opções de recuperação\? Resette tudo - Você juntou-se. + Você entrou. Mensagens nesta sala são encriptadas ponta-a-ponta. Sair Configurações @@ -1728,7 +1728,7 @@ Resettar %1$s fez isto somente convite. Você fez isto somente convite. - %s juntou-se. + %s entrou. Filtrar usuárias(os) banidas(os) Testar Push @@ -1907,7 +1907,7 @@ Sinc inicial: \nFazendo download de dados… Sinc inicial: -\nEsperando por resposta de servidor… +\nEsperando pela resposta do servidor… Nível de confiança confiado Nível de confiança alerta Você tem certeza que você quer deletar todas as mensagens não-enviadas nesta sala\? @@ -2015,8 +2015,8 @@ Adicionar salas Explorar salas - %d pessoa que você conhece já tem se juntado - %d pessoas que você conhece já têm se juntado + %d pessoa que você conhece já entrou + %d pessoas que você conhece já entraram Juntar-Se a Espaço Criar espaço @@ -2113,7 +2113,7 @@ Não dá para gravar uma mensagem de voz Não dá para tocar esta mensagem de voz Toque em sua gravação para parar ou escutar - %1$ds restando + %1$ds restantes Segure para gravar, solte para enviar Deletar gravação Gravando mensagem de voz @@ -2267,7 +2267,7 @@ Enviar emails e números de telefone para %s Seus contatos são privados. Para descobrir usuárias(os) de seus contatos, você precisa de permissão para enviar info de contato a seu servidor de identidade. O signout desta sessão tem sido feito! - Esta sala tem sido saída! + Saiu da sala! Você concorda em enviar esta info\? Para descobrir contatos existentes, você precisa enviar info de contato (emails e números de telefone) para seu servidor de identidade. Nós hashamos seus dados antes de enviar por privacidade. Não agora @@ -2318,7 +2318,7 @@ Habilitar Recomece o aplicativo para a mudançar tomar efeito. Habilitar matemática LaTeX - Você não é permitida(o) a juntar-se a esta sala + Você não tem permissão pra entrar nesta sala Criar sondagem Abrir contatos Enviar sticker @@ -2472,11 +2472,11 @@ ${app_name} Compartilhamento de Tela Parar compartilhamento de tela Compartilhar tela - - Algumas(ns) usuárias(os) têm sido designoradas(os) - ${app_name} precisa performar um cache limpo para estar atualizado, pela seguinte razão: + - Alguns usuários foram designorados + ${app_name} precisa limpar o cache para estar atualizado, pelo seguinte motivo: \n%s \n -\nNote que esta ação vai recomeçar o app e pode levar algum tempo. +\nNote que esta ação vai reiniciar o app e pode levar algum tempo. Requisição de sinc inicial Mostrar a info de perfil mais recente (avatar e nome de exibição) para todas as mensagens. Mostrar info de usuária(o) mais recente @@ -2486,7 +2486,7 @@ Parar de compartilhar Implementação tempoária: locais persistem em histórico de sala Habilitar Compartilhament de Localização Ao Vivo - %1$s saiu + %1$s restantes Ao vivo até %1$s Ver localização ao vivo Localização ao vivo terminou @@ -2500,4 +2500,34 @@ seg min h - + Observação: esta é uma funcionalidade experimental usando uma implementação temporária. Isso significa que você não poderá deletar seu histórico de localização, e usuários avançados poderão ver seu histórico de localização mesmo depois que você parar de compartilhar sua localização em tempo real com esta sala. + Tag do perfil: + Falhou ao registrar o token do endpoint ao servidorcasa: +\n%1$s + + + Ativar compartilhamento de localização + Compartilhamento de localização em tempo real + Gateway atual: %s + Não foi possível encontrar o endpoint. + Endpoint atual: %s + Usando %s atualmente. + Método + + %d método encontrado. + %d métodos encontrados. + + Nenhum outro método além da sincronização em plano de fundo encontrado. + Nenhum outro método além do Google Play Services encontrado. + Métodos disponíveis + Método de notificação + Sincronização em plano de fundo + Serviços do Google + Escolha como receber notificações + A verificação biométrica foi desativada porque um novo método de verificação biométrica foi adicionado recentemente. Você pode reativá-la nas Configurações. + Não foi possível ativar a verificação biométrica. + Redefinir método de notificação + Endpoint registrado com sucesso ao servidor casa. + Registro de Endpoint + Próximo + \ No newline at end of file From c7a7a4db16e87ec68bf62ab42b36355d6f399d0a Mon Sep 17 00:00:00 2001 From: Daimar Stein Date: Tue, 5 Jul 2022 14:46:50 +0000 Subject: [PATCH 070/131] Translated using Weblate (Portuguese (Brazil)) Currently translated at 99.8% (2257 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/pt_BR/ --- vector/src/main/res/values-pt-rBR/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/res/values-pt-rBR/strings.xml b/vector/src/main/res/values-pt-rBR/strings.xml index ee73b43824..caa06db7f4 100644 --- a/vector/src/main/res/values-pt-rBR/strings.xml +++ b/vector/src/main/res/values-pt-rBR/strings.xml @@ -2304,7 +2304,7 @@ A política de seu servidor de identidade A política de seu servidorcasa Política de ${app_name} - Nós não gravamos ou perfilamos quaisquer dados de conta + Nós não gravaremos nem criaremos um perfil dos dados de sua conta Ajude-nos a identificar problemas e melhorar ${app_name} ao compartilhar dados de uso anônimos. Para entender como pessoas usam seus múltiplos dispositivos, nós vamos gerar um identificador aleatório, compartilhado por seus dispositivos. \n \nVocê pode ler todos os nossos termos %s. From 7d800dd8e0485e56016bde20027ec5242828e6f4 Mon Sep 17 00:00:00 2001 From: Nui Harime Date: Wed, 6 Jul 2022 14:25:13 +0000 Subject: [PATCH 071/131] Translated using Weblate (Russian) Currently translated at 99.5% (2250 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ru/ --- vector/src/main/res/values-ru/strings.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vector/src/main/res/values-ru/strings.xml b/vector/src/main/res/values-ru/strings.xml index 6ac29a100f..17d48c59f2 100644 --- a/vector/src/main/res/values-ru/strings.xml +++ b/vector/src/main/res/values-ru/strings.xml @@ -2125,7 +2125,7 @@ Поиск по имени Сжатие видео %d%% Сжатие изображения… - Дать отзыв + Оставить отзыв Не удалось отправить отзыв (%s) Спасибо, ваш отзыв успешно отправлен Вы можете связаться со мной, если у вас есть дополнительные вопросы @@ -2495,8 +2495,8 @@ Домой Персонализировать БЕТА - Обратная связь на бета-версию Обсуждений - Обратная связь + Отзыв на бета-версию Обсуждений + Оставить отзыв БЕТА Если включено, для других вы всегда будете выглядеть, как в офлайне, даже при использовании приложения. Офлайн-режим @@ -2515,7 +2515,7 @@ Осталось %1$s Обновлено %1$s назад Остановить трансляцию - Включить отправку трансляции местоположения + Включить функцию \"Поделиться трансляцией местоположения\" ${app_name} Трансляция местоположения Транслировать до %1$s Трансляция завершена From db84d02cd232fe586bcfe2c2936cf00002383ad4 Mon Sep 17 00:00:00 2001 From: Mateus Rodrigues Costa Date: Tue, 5 Jul 2022 15:23:16 +0000 Subject: [PATCH 072/131] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (68 of 68 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/pt_BR/ --- fastlane/metadata/android/pt-BR/changelogs/40104220.txt | 2 ++ fastlane/metadata/android/pt-BR/changelogs/40104230.txt | 2 ++ fastlane/metadata/android/pt-BR/changelogs/40104240.txt | 2 ++ fastlane/metadata/android/pt-BR/changelogs/40104250.txt | 2 ++ 4 files changed, 8 insertions(+) create mode 100644 fastlane/metadata/android/pt-BR/changelogs/40104220.txt create mode 100644 fastlane/metadata/android/pt-BR/changelogs/40104230.txt create mode 100644 fastlane/metadata/android/pt-BR/changelogs/40104240.txt create mode 100644 fastlane/metadata/android/pt-BR/changelogs/40104250.txt diff --git a/fastlane/metadata/android/pt-BR/changelogs/40104220.txt b/fastlane/metadata/android/pt-BR/changelogs/40104220.txt new file mode 100644 index 0000000000..5c0d610ddd --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40104220.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Várias correções de bugs e melhorias de estabilidade. +Registro de mudanças completo: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pt-BR/changelogs/40104230.txt b/fastlane/metadata/android/pt-BR/changelogs/40104230.txt new file mode 100644 index 0000000000..5c0d610ddd --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40104230.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Várias correções de bugs e melhorias de estabilidade. +Registro de mudanças completo: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pt-BR/changelogs/40104240.txt b/fastlane/metadata/android/pt-BR/changelogs/40104240.txt new file mode 100644 index 0000000000..5c0d610ddd --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40104240.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Várias correções de bugs e melhorias de estabilidade. +Registro de mudanças completo: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pt-BR/changelogs/40104250.txt b/fastlane/metadata/android/pt-BR/changelogs/40104250.txt new file mode 100644 index 0000000000..5c0d610ddd --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40104250.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Várias correções de bugs e melhorias de estabilidade. +Registro de mudanças completo: https://github.com/vector-im/element-android/releases From e3b3617b1a312d69140d6f88fa7e0d5c0c66b8a5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 Jul 2022 17:54:29 +0200 Subject: [PATCH 073/131] Add dependency to opusencoder and remove module from this project --- dependencies.gradle | 3 + dependencies_groups.gradle | 1 + library/opusencoder/.gitignore | 10 - library/opusencoder/build.gradle | 40 - .../opusencoder/src/main/AndroidManifest.xml | 2 - .../opusencoder/src/main/cpp/CMakeLists.txt | 61 -- .../src/main/cpp/codec/CodecOggOpus.cpp | 63 -- .../src/main/cpp/codec/CodecOggOpus.h | 52 - .../src/main/cpp/opus/include/opus.h | 981 ------------------ .../src/main/cpp/opus/include/opus_custom.h | 342 ------ .../src/main/cpp/opus/include/opus_defines.h | 788 -------------- .../main/cpp/opus/include/opus_multistream.h | 660 ------------ .../main/cpp/opus/include/opus_projection.h | 568 ---------- .../src/main/cpp/opus/include/opus_types.h | 166 --- .../src/main/cpp/opus/include/opusenc.h | 358 ------- .../main/cpp/opus/libs/arm64-v8a/libopus.so | Bin 318136 -> 0 bytes .../cpp/opus/libs/arm64-v8a/libopusenc.so | Bin 49448 -> 0 bytes .../main/cpp/opus/libs/armeabi-v7a/libopus.so | Bin 253712 -> 0 bytes .../cpp/opus/libs/armeabi-v7a/libopusenc.so | Bin 39836 -> 0 bytes .../src/main/cpp/opus/libs/x86/libopus.so | Bin 329156 -> 0 bytes .../src/main/cpp/opus/libs/x86/libopusenc.so | Bin 56796 -> 0 bytes .../src/main/cpp/opus/libs/x86_64/libopus.so | Bin 346688 -> 0 bytes .../main/cpp/opus/libs/x86_64/libopusenc.so | Bin 60864 -> 0 bytes .../opusencoder/src/main/cpp/opuscodec.cpp | 42 - .../opusencoder/src/main/cpp/utils/Logger.h | 11 - .../im/vector/opusencoder/OggOpusEncoder.kt | 57 - .../opusencoder/configuration/SampleRate.kt | 28 - settings.gradle | 1 - vector/build.gradle | 4 +- .../app/features/voice/VoiceRecorderL.kt | 4 +- 30 files changed, 8 insertions(+), 4234 deletions(-) delete mode 100644 library/opusencoder/.gitignore delete mode 100644 library/opusencoder/build.gradle delete mode 100644 library/opusencoder/src/main/AndroidManifest.xml delete mode 100644 library/opusencoder/src/main/cpp/CMakeLists.txt delete mode 100644 library/opusencoder/src/main/cpp/codec/CodecOggOpus.cpp delete mode 100644 library/opusencoder/src/main/cpp/codec/CodecOggOpus.h delete mode 100644 library/opusencoder/src/main/cpp/opus/include/opus.h delete mode 100644 library/opusencoder/src/main/cpp/opus/include/opus_custom.h delete mode 100644 library/opusencoder/src/main/cpp/opus/include/opus_defines.h delete mode 100644 library/opusencoder/src/main/cpp/opus/include/opus_multistream.h delete mode 100644 library/opusencoder/src/main/cpp/opus/include/opus_projection.h delete mode 100644 library/opusencoder/src/main/cpp/opus/include/opus_types.h delete mode 100644 library/opusencoder/src/main/cpp/opus/include/opusenc.h delete mode 100755 library/opusencoder/src/main/cpp/opus/libs/arm64-v8a/libopus.so delete mode 100755 library/opusencoder/src/main/cpp/opus/libs/arm64-v8a/libopusenc.so delete mode 100755 library/opusencoder/src/main/cpp/opus/libs/armeabi-v7a/libopus.so delete mode 100755 library/opusencoder/src/main/cpp/opus/libs/armeabi-v7a/libopusenc.so delete mode 100755 library/opusencoder/src/main/cpp/opus/libs/x86/libopus.so delete mode 100755 library/opusencoder/src/main/cpp/opus/libs/x86/libopusenc.so delete mode 100755 library/opusencoder/src/main/cpp/opus/libs/x86_64/libopus.so delete mode 100755 library/opusencoder/src/main/cpp/opus/libs/x86_64/libopusenc.so delete mode 100644 library/opusencoder/src/main/cpp/opuscodec.cpp delete mode 100644 library/opusencoder/src/main/cpp/utils/Logger.h delete mode 100644 library/opusencoder/src/main/java/im/vector/opusencoder/OggOpusEncoder.kt delete mode 100644 library/opusencoder/src/main/java/im/vector/opusencoder/configuration/SampleRate.kt diff --git a/dependencies.gradle b/dependencies.gradle index bd03a1c48b..7c6d6c3e08 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -96,6 +96,9 @@ ext.libs = [ 'flipper' : "com.facebook.flipper:flipper:$flipper", 'flipperNetworkPlugin' : "com.facebook.flipper:flipper-network-plugin:$flipper", ], + element : [ + 'opusencoder' : "io.element.android:opusencoder:1.0.0", + ], squareup : [ 'moshi' : "com.squareup.moshi:moshi:$moshi", 'moshiKt' : "com.squareup.moshi:moshi-kotlin:$moshi", diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index b785c7f50b..e89c69a594 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -124,6 +124,7 @@ ext.groups = [ 'commons-logging', 'info.picocli', 'io.arrow-kt', + 'io.element.android', 'io.github.detekt.sarif4k', 'io.github.microutils', 'io.github.reactivecircus.flowbinding', diff --git a/library/opusencoder/.gitignore b/library/opusencoder/.gitignore deleted file mode 100644 index ff535c85f5..0000000000 --- a/library/opusencoder/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -*.iml -.gradle -/local.properties -/.idea -.DS_Store -/build -/captures -*.cxx -app/.cxx/* -.externalNativeBuild \ No newline at end of file diff --git a/library/opusencoder/build.gradle b/library/opusencoder/build.gradle deleted file mode 100644 index a825bb98bc..0000000000 --- a/library/opusencoder/build.gradle +++ /dev/null @@ -1,40 +0,0 @@ -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' - -android { - ndkVersion "21.3.6528147" - - compileSdkVersion 31 - - buildToolsVersion "31.0.0" - - defaultConfig { - minSdkVersion 18 - targetSdkVersion 31 - versionCode 1 - versionName "1.0" - - externalNativeBuild { - ndk { - abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' - } - } - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - - externalNativeBuild { - cmake { - path "src/main/cpp/CMakeLists.txt" - } - } -} - -dependencies { - implementation libs.androidx.annotation -} diff --git a/library/opusencoder/src/main/AndroidManifest.xml b/library/opusencoder/src/main/AndroidManifest.xml deleted file mode 100644 index 4dd3413820..0000000000 --- a/library/opusencoder/src/main/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/library/opusencoder/src/main/cpp/CMakeLists.txt b/library/opusencoder/src/main/cpp/CMakeLists.txt deleted file mode 100644 index c261af8b90..0000000000 --- a/library/opusencoder/src/main/cpp/CMakeLists.txt +++ /dev/null @@ -1,61 +0,0 @@ -# For more information about using CMake with Android Studio, read the -# documentation: https://d.android.com/studio/projects/add-native-code.html - -# Sets the minimum version of CMake required to build the native library. - -cmake_minimum_required(VERSION 3.4.1) -set(CMAKE_CXX_STANDARD 14) - -# Creates and names a library, sets it as either STATIC -# or SHARED, and provides the relative paths to its source code. -# You can define multiple libraries, and CMake builds them for you. -# Gradle automatically packages shared libraries with your APK. - -set(distribution_OPUS_DIR ${CMAKE_SOURCE_DIR}/opus) - -add_library(lib_opus SHARED IMPORTED) -set_target_properties(lib_opus PROPERTIES IMPORTED_LOCATION - ${distribution_OPUS_DIR}/libs/${ANDROID_ABI}/libopus.so) - -add_library(lib_opusenc SHARED IMPORTED) -set_target_properties(lib_opusenc PROPERTIES IMPORTED_LOCATION - ${distribution_OPUS_DIR}/libs/${ANDROID_ABI}/libopusenc.so) - -add_library( # Sets the name of the library. - opuscodec - - # Sets the library as a shared library. - SHARED - - # Provides a relative path to your source file(s). - codec/CodecOggOpus.cpp - opuscodec.cpp) - -target_include_directories(opuscodec PRIVATE - ${distribution_OPUS_DIR}/include) - -# Searches for a specified prebuilt library and stores the path as a -# variable. Because CMake includes system libraries in the search path by -# default, you only need to specify the name of the public NDK library -# you want to add. CMake verifies that the library exists before -# completing its build. - -find_library( # Sets the name of the path variable. - log-lib - - # Specifies the name of the NDK library that - # you want CMake to locate. - log ) - -# Specifies libraries CMake should link to your target library. You -# can link multiple libraries, such as libraries you define in this -# build script, prebuilt third-party libraries, or system libraries. - -target_link_libraries( # Specifies the target library. - opuscodec - android - lib_opusenc - lib_opus - # Links the target library to the log library - # included in the NDK. - ${log-lib} ) diff --git a/library/opusencoder/src/main/cpp/codec/CodecOggOpus.cpp b/library/opusencoder/src/main/cpp/codec/CodecOggOpus.cpp deleted file mode 100644 index d167c69cbf..0000000000 --- a/library/opusencoder/src/main/cpp/codec/CodecOggOpus.cpp +++ /dev/null @@ -1,63 +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. - */ - -#include "CodecOggOpus.h" -#include "../utils/Logger.h" - -int ret; - -int CodecOggOpus::encoderInit(char* filePath, int sampleRate) { - // Create default, empty comment header - comments = ope_comments_create(); - // Mono audio - int numChannels = 1; - // Channel Mapping Family 0, used for mono/stereo streams - int family = 0; - // Create encoder to encode PCM chunks and write the result to a file with the OggOpus framing - encoder = ope_encoder_create_file(filePath, comments, sampleRate, numChannels, family, &ret); - if (ret != OPE_OK) { - LOGE(TAG, "Creation of OggOpusEnc failed."); - return ret; - } - return OPE_OK; -} - -int CodecOggOpus::setBitrate(int bitrate) { - ret = ope_encoder_ctl(encoder, OPUS_SET_BITRATE_REQUEST, bitrate); - if (ret != OPE_OK) { - LOGE(TAG, "Could not set bitrate."); - return ret; - } - return OPE_OK; -} - -int CodecOggOpus::writeFrame(short* frame, int samplesPerChannel) { - // Encode the raw PCM-16 buffer to Opus and write it to the ogg file - return ope_encoder_write(encoder, frame, samplesPerChannel); -} - -void CodecOggOpus::encoderRelease() { - // Finish any pending encode/write operations - ope_encoder_drain(encoder); - // De-init the encoder instance - ope_encoder_destroy(encoder); - // De-init the comment header struct - ope_comments_destroy(comments); -} - -CodecOggOpus::~CodecOggOpus() { - encoderRelease(); -} diff --git a/library/opusencoder/src/main/cpp/codec/CodecOggOpus.h b/library/opusencoder/src/main/cpp/codec/CodecOggOpus.h deleted file mode 100644 index f1035434c5..0000000000 --- a/library/opusencoder/src/main/cpp/codec/CodecOggOpus.h +++ /dev/null @@ -1,52 +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. - */ - -#ifndef ELEMENT_ANDROID_CODECOGGOPUS_H -#define ELEMENT_ANDROID_CODECOGGOPUS_H - -#include -/** - * This class is a wrapper around libopusenc, used to encode and write Opus frames into an Ogg file. - * - * The usual flow would be: - * - * 1. Use encoderInit to initialize the internal encoder with the sample rate and the path to write the encoded frames to. - * 2. (Optional) set the bitrate to use. - * 3. While recording, read PCM-16 chunks from the recorder, feed them to the encoder using writeFrame. - * 4. When finished, call encoderRelease to free some resources. - */ -class CodecOggOpus { - -private: - const char *TAG = "CodecOggOpus"; - - OggOpusEnc* encoder; - OggOpusComments* comments; - -public: - int encoderInit(char* filePath, int sampleRate); - - int setBitrate(int bitrate); - - int writeFrame(short *frame, int samplesPerChannel); - - void encoderRelease(); - - ~CodecOggOpus(); -}; - - -#endif //ELEMENT_ANDROID_CODECOGGOPUS_H diff --git a/library/opusencoder/src/main/cpp/opus/include/opus.h b/library/opusencoder/src/main/cpp/opus/include/opus.h deleted file mode 100644 index d282f21d25..0000000000 --- a/library/opusencoder/src/main/cpp/opus/include/opus.h +++ /dev/null @@ -1,981 +0,0 @@ -/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited - Written by Jean-Marc Valin and Koen Vos */ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/** - * @file opus.h - * @brief Opus reference implementation API - */ - -#ifndef OPUS_H -#define OPUS_H - -#include "opus_types.h" -#include "opus_defines.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @mainpage Opus - * - * The Opus codec is designed for interactive speech and audio transmission over the Internet. - * It is designed by the IETF Codec Working Group and incorporates technology from - * Skype's SILK codec and Xiph.Org's CELT codec. - * - * The Opus codec is designed to handle a wide range of interactive audio applications, - * including Voice over IP, videoconferencing, in-game chat, and even remote live music - * performances. It can scale from low bit-rate narrowband speech to very high quality - * stereo music. Its main features are: - - * @li Sampling rates from 8 to 48 kHz - * @li Bit-rates from 6 kb/s to 510 kb/s - * @li Support for both constant bit-rate (CBR) and variable bit-rate (VBR) - * @li Audio bandwidth from narrowband to full-band - * @li Support for speech and music - * @li Support for mono and stereo - * @li Support for multichannel (up to 255 channels) - * @li Frame sizes from 2.5 ms to 60 ms - * @li Good loss robustness and packet loss concealment (PLC) - * @li Floating point and fixed-point implementation - * - * Documentation sections: - * @li @ref opus_encoder - * @li @ref opus_decoder - * @li @ref opus_repacketizer - * @li @ref opus_multistream - * @li @ref opus_libinfo - * @li @ref opus_custom - */ - -/** @defgroup opus_encoder Opus Encoder - * @{ - * - * @brief This page describes the process and functions used to encode Opus. - * - * Since Opus is a stateful codec, the encoding process starts with creating an encoder - * state. This can be done with: - * - * @code - * int error; - * OpusEncoder *enc; - * enc = opus_encoder_create(Fs, channels, application, &error); - * @endcode - * - * From this point, @c enc can be used for encoding an audio stream. An encoder state - * @b must @b not be used for more than one stream at the same time. Similarly, the encoder - * state @b must @b not be re-initialized for each frame. - * - * While opus_encoder_create() allocates memory for the state, it's also possible - * to initialize pre-allocated memory: - * - * @code - * int size; - * int error; - * OpusEncoder *enc; - * size = opus_encoder_get_size(channels); - * enc = malloc(size); - * error = opus_encoder_init(enc, Fs, channels, application); - * @endcode - * - * where opus_encoder_get_size() returns the required size for the encoder state. Note that - * future versions of this code may change the size, so no assuptions should be made about it. - * - * The encoder state is always continuous in memory and only a shallow copy is sufficient - * to copy it (e.g. memcpy()) - * - * It is possible to change some of the encoder's settings using the opus_encoder_ctl() - * interface. All these settings already default to the recommended value, so they should - * only be changed when necessary. The most common settings one may want to change are: - * - * @code - * opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate)); - * opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity)); - * opus_encoder_ctl(enc, OPUS_SET_SIGNAL(signal_type)); - * @endcode - * - * where - * - * @arg bitrate is in bits per second (b/s) - * @arg complexity is a value from 1 to 10, where 1 is the lowest complexity and 10 is the highest - * @arg signal_type is either OPUS_AUTO (default), OPUS_SIGNAL_VOICE, or OPUS_SIGNAL_MUSIC - * - * See @ref opus_encoderctls and @ref opus_genericctls for a complete list of parameters that can be set or queried. Most parameters can be set or changed at any time during a stream. - * - * To encode a frame, opus_encode() or opus_encode_float() must be called with exactly one frame (2.5, 5, 10, 20, 40 or 60 ms) of audio data: - * @code - * len = opus_encode(enc, audio_frame, frame_size, packet, max_packet); - * @endcode - * - * where - *
    - *
  • audio_frame is the audio data in opus_int16 (or float for opus_encode_float())
  • - *
  • frame_size is the duration of the frame in samples (per channel)
  • - *
  • packet is the byte array to which the compressed data is written
  • - *
  • max_packet is the maximum number of bytes that can be written in the packet (4000 bytes is recommended). - * Do not use max_packet to control VBR target bitrate, instead use the #OPUS_SET_BITRATE CTL.
  • - *
- * - * opus_encode() and opus_encode_float() return the number of bytes actually written to the packet. - * The return value can be negative, which indicates that an error has occurred. If the return value - * is 2 bytes or less, then the packet does not need to be transmitted (DTX). - * - * Once the encoder state if no longer needed, it can be destroyed with - * - * @code - * opus_encoder_destroy(enc); - * @endcode - * - * If the encoder was created with opus_encoder_init() rather than opus_encoder_create(), - * then no action is required aside from potentially freeing the memory that was manually - * allocated for it (calling free(enc) for the example above) - * - */ - -/** Opus encoder state. - * This contains the complete state of an Opus encoder. - * It is position independent and can be freely copied. - * @see opus_encoder_create,opus_encoder_init - */ -typedef struct OpusEncoder OpusEncoder; - -/** Gets the size of an OpusEncoder structure. - * @param[in] channels int: Number of channels. - * This must be 1 or 2. - * @returns The size in bytes. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_encoder_get_size(int channels); - -/** - */ - -/** Allocates and initializes an encoder state. - * There are three coding modes: - * - * @ref OPUS_APPLICATION_VOIP gives best quality at a given bitrate for voice - * signals. It enhances the input signal by high-pass filtering and - * emphasizing formants and harmonics. Optionally it includes in-band - * forward error correction to protect against packet loss. Use this - * mode for typical VoIP applications. Because of the enhancement, - * even at high bitrates the output may sound different from the input. - * - * @ref OPUS_APPLICATION_AUDIO gives best quality at a given bitrate for most - * non-voice signals like music. Use this mode for music and mixed - * (music/voice) content, broadcast, and applications requiring less - * than 15 ms of coding delay. - * - * @ref OPUS_APPLICATION_RESTRICTED_LOWDELAY configures low-delay mode that - * disables the speech-optimized mode in exchange for slightly reduced delay. - * This mode can only be set on an newly initialized or freshly reset encoder - * because it changes the codec delay. - * - * This is useful when the caller knows that the speech-optimized modes will not be needed (use with caution). - * @param [in] Fs opus_int32: Sampling rate of input signal (Hz) - * This must be one of 8000, 12000, 16000, - * 24000, or 48000. - * @param [in] channels int: Number of channels (1 or 2) in input signal - * @param [in] application int: Coding mode (@ref OPUS_APPLICATION_VOIP/@ref OPUS_APPLICATION_AUDIO/@ref OPUS_APPLICATION_RESTRICTED_LOWDELAY) - * @param [out] error int*: @ref opus_errorcodes - * @note Regardless of the sampling rate and number channels selected, the Opus encoder - * can switch to a lower audio bandwidth or number of channels if the bitrate - * selected is too low. This also means that it is safe to always use 48 kHz stereo input - * and let the encoder optimize the encoding. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusEncoder *opus_encoder_create( - opus_int32 Fs, - int channels, - int application, - int *error -); - -/** Initializes a previously allocated encoder state - * The memory pointed to by st must be at least the size returned by opus_encoder_get_size(). - * This is intended for applications which use their own allocator instead of malloc. - * @see opus_encoder_create(),opus_encoder_get_size() - * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. - * @param [in] st OpusEncoder*: Encoder state - * @param [in] Fs opus_int32: Sampling rate of input signal (Hz) - * This must be one of 8000, 12000, 16000, - * 24000, or 48000. - * @param [in] channels int: Number of channels (1 or 2) in input signal - * @param [in] application int: Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO/OPUS_APPLICATION_RESTRICTED_LOWDELAY) - * @retval #OPUS_OK Success or @ref opus_errorcodes - */ -OPUS_EXPORT int opus_encoder_init( - OpusEncoder *st, - opus_int32 Fs, - int channels, - int application -) OPUS_ARG_NONNULL(1); - -/** Encodes an Opus frame. - * @param [in] st OpusEncoder*: Encoder state - * @param [in] pcm opus_int16*: Input signal (interleaved if 2 channels). length is frame_size*channels*sizeof(opus_int16) - * @param [in] frame_size int: Number of samples per channel in the - * input signal. - * This must be an Opus frame size for - * the encoder's sampling rate. - * For example, at 48 kHz the permitted - * values are 120, 240, 480, 960, 1920, - * and 2880. - * Passing in a duration of less than - * 10 ms (480 samples at 48 kHz) will - * prevent the encoder from using the LPC - * or hybrid modes. - * @param [out] data unsigned char*: Output payload. - * This must contain storage for at - * least \a max_data_bytes. - * @param [in] max_data_bytes opus_int32: Size of the allocated - * memory for the output - * payload. This may be - * used to impose an upper limit on - * the instant bitrate, but should - * not be used as the only bitrate - * control. Use #OPUS_SET_BITRATE to - * control the bitrate. - * @returns The length of the encoded packet (in bytes) on success or a - * negative error code (see @ref opus_errorcodes) on failure. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode( - OpusEncoder *st, - const opus_int16 *pcm, - int frame_size, - unsigned char *data, - opus_int32 max_data_bytes -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); - -/** Encodes an Opus frame from floating point input. - * @param [in] st OpusEncoder*: Encoder state - * @param [in] pcm float*: Input in float format (interleaved if 2 channels), with a normal range of +/-1.0. - * Samples with a range beyond +/-1.0 are supported but will - * be clipped by decoders using the integer API and should - * only be used if it is known that the far end supports - * extended dynamic range. - * length is frame_size*channels*sizeof(float) - * @param [in] frame_size int: Number of samples per channel in the - * input signal. - * This must be an Opus frame size for - * the encoder's sampling rate. - * For example, at 48 kHz the permitted - * values are 120, 240, 480, 960, 1920, - * and 2880. - * Passing in a duration of less than - * 10 ms (480 samples at 48 kHz) will - * prevent the encoder from using the LPC - * or hybrid modes. - * @param [out] data unsigned char*: Output payload. - * This must contain storage for at - * least \a max_data_bytes. - * @param [in] max_data_bytes opus_int32: Size of the allocated - * memory for the output - * payload. This may be - * used to impose an upper limit on - * the instant bitrate, but should - * not be used as the only bitrate - * control. Use #OPUS_SET_BITRATE to - * control the bitrate. - * @returns The length of the encoded packet (in bytes) on success or a - * negative error code (see @ref opus_errorcodes) on failure. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode_float( - OpusEncoder *st, - const float *pcm, - int frame_size, - unsigned char *data, - opus_int32 max_data_bytes -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); - -/** Frees an OpusEncoder allocated by opus_encoder_create(). - * @param[in] st OpusEncoder*: State to be freed. - */ -OPUS_EXPORT void opus_encoder_destroy(OpusEncoder *st); - -/** Perform a CTL function on an Opus encoder. - * - * Generally the request and subsequent arguments are generated - * by a convenience macro. - * @param st OpusEncoder*: Encoder state. - * @param request This and all remaining parameters should be replaced by one - * of the convenience macros in @ref opus_genericctls or - * @ref opus_encoderctls. - * @see opus_genericctls - * @see opus_encoderctls - */ -OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NONNULL(1); -/**@}*/ - -/** @defgroup opus_decoder Opus Decoder - * @{ - * - * @brief This page describes the process and functions used to decode Opus. - * - * The decoding process also starts with creating a decoder - * state. This can be done with: - * @code - * int error; - * OpusDecoder *dec; - * dec = opus_decoder_create(Fs, channels, &error); - * @endcode - * where - * @li Fs is the sampling rate and must be 8000, 12000, 16000, 24000, or 48000 - * @li channels is the number of channels (1 or 2) - * @li error will hold the error code in case of failure (or #OPUS_OK on success) - * @li the return value is a newly created decoder state to be used for decoding - * - * While opus_decoder_create() allocates memory for the state, it's also possible - * to initialize pre-allocated memory: - * @code - * int size; - * int error; - * OpusDecoder *dec; - * size = opus_decoder_get_size(channels); - * dec = malloc(size); - * error = opus_decoder_init(dec, Fs, channels); - * @endcode - * where opus_decoder_get_size() returns the required size for the decoder state. Note that - * future versions of this code may change the size, so no assuptions should be made about it. - * - * The decoder state is always continuous in memory and only a shallow copy is sufficient - * to copy it (e.g. memcpy()) - * - * To decode a frame, opus_decode() or opus_decode_float() must be called with a packet of compressed audio data: - * @code - * frame_size = opus_decode(dec, packet, len, decoded, max_size, 0); - * @endcode - * where - * - * @li packet is the byte array containing the compressed data - * @li len is the exact number of bytes contained in the packet - * @li decoded is the decoded audio data in opus_int16 (or float for opus_decode_float()) - * @li max_size is the max duration of the frame in samples (per channel) that can fit into the decoded_frame array - * - * opus_decode() and opus_decode_float() return the number of samples (per channel) decoded from the packet. - * If that value is negative, then an error has occurred. This can occur if the packet is corrupted or if the audio - * buffer is too small to hold the decoded audio. - * - * Opus is a stateful codec with overlapping blocks and as a result Opus - * packets are not coded independently of each other. Packets must be - * passed into the decoder serially and in the correct order for a correct - * decode. Lost packets can be replaced with loss concealment by calling - * the decoder with a null pointer and zero length for the missing packet. - * - * A single codec state may only be accessed from a single thread at - * a time and any required locking must be performed by the caller. Separate - * streams must be decoded with separate decoder states and can be decoded - * in parallel unless the library was compiled with NONTHREADSAFE_PSEUDOSTACK - * defined. - * - */ - -/** Opus decoder state. - * This contains the complete state of an Opus decoder. - * It is position independent and can be freely copied. - * @see opus_decoder_create,opus_decoder_init - */ -typedef struct OpusDecoder OpusDecoder; - -/** Gets the size of an OpusDecoder structure. - * @param [in] channels int: Number of channels. - * This must be 1 or 2. - * @returns The size in bytes. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_size(int channels); - -/** Allocates and initializes a decoder state. - * @param [in] Fs opus_int32: Sample rate to decode at (Hz). - * This must be one of 8000, 12000, 16000, - * 24000, or 48000. - * @param [in] channels int: Number of channels (1 or 2) to decode - * @param [out] error int*: #OPUS_OK Success or @ref opus_errorcodes - * - * Internally Opus stores data at 48000 Hz, so that should be the default - * value for Fs. However, the decoder can efficiently decode to buffers - * at 8, 12, 16, and 24 kHz so if for some reason the caller cannot use - * data at the full sample rate, or knows the compressed data doesn't - * use the full frequency range, it can request decoding at a reduced - * rate. Likewise, the decoder is capable of filling in either mono or - * interleaved stereo pcm buffers, at the caller's request. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusDecoder *opus_decoder_create( - opus_int32 Fs, - int channels, - int *error -); - -/** Initializes a previously allocated decoder state. - * The state must be at least the size returned by opus_decoder_get_size(). - * This is intended for applications which use their own allocator instead of malloc. @see opus_decoder_create,opus_decoder_get_size - * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. - * @param [in] st OpusDecoder*: Decoder state. - * @param [in] Fs opus_int32: Sampling rate to decode to (Hz). - * This must be one of 8000, 12000, 16000, - * 24000, or 48000. - * @param [in] channels int: Number of channels (1 or 2) to decode - * @retval #OPUS_OK Success or @ref opus_errorcodes - */ -OPUS_EXPORT int opus_decoder_init( - OpusDecoder *st, - opus_int32 Fs, - int channels -) OPUS_ARG_NONNULL(1); - -/** Decode an Opus packet. - * @param [in] st OpusDecoder*: Decoder state - * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss - * @param [in] len opus_int32: Number of bytes in payload* - * @param [out] pcm opus_int16*: Output signal (interleaved if 2 channels). length - * is frame_size*channels*sizeof(opus_int16) - * @param [in] frame_size Number of samples per channel of available space in \a pcm. - * If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will - * not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1), - * then frame_size needs to be exactly the duration of audio that is missing, otherwise the - * decoder will not be in the optimal state to decode the next incoming packet. For the PLC and - * FEC cases, frame_size must be a multiple of 2.5 ms. - * @param [in] decode_fec int: Flag (0 or 1) to request that any in-band forward error correction data be - * decoded. If no such data is available, the frame is decoded as if it were lost. - * @returns Number of decoded samples or @ref opus_errorcodes - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode( - OpusDecoder *st, - const unsigned char *data, - opus_int32 len, - opus_int16 *pcm, - int frame_size, - int decode_fec -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); - -/** Decode an Opus packet with floating point output. - * @param [in] st OpusDecoder*: Decoder state - * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss - * @param [in] len opus_int32: Number of bytes in payload - * @param [out] pcm float*: Output signal (interleaved if 2 channels). length - * is frame_size*channels*sizeof(float) - * @param [in] frame_size Number of samples per channel of available space in \a pcm. - * If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will - * not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1), - * then frame_size needs to be exactly the duration of audio that is missing, otherwise the - * decoder will not be in the optimal state to decode the next incoming packet. For the PLC and - * FEC cases, frame_size must be a multiple of 2.5 ms. - * @param [in] decode_fec int: Flag (0 or 1) to request that any in-band forward error correction data be - * decoded. If no such data is available the frame is decoded as if it were lost. - * @returns Number of decoded samples or @ref opus_errorcodes - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode_float( - OpusDecoder *st, - const unsigned char *data, - opus_int32 len, - float *pcm, - int frame_size, - int decode_fec -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); - -/** Perform a CTL function on an Opus decoder. - * - * Generally the request and subsequent arguments are generated - * by a convenience macro. - * @param st OpusDecoder*: Decoder state. - * @param request This and all remaining parameters should be replaced by one - * of the convenience macros in @ref opus_genericctls or - * @ref opus_decoderctls. - * @see opus_genericctls - * @see opus_decoderctls - */ -OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...) OPUS_ARG_NONNULL(1); - -/** Frees an OpusDecoder allocated by opus_decoder_create(). - * @param[in] st OpusDecoder*: State to be freed. - */ -OPUS_EXPORT void opus_decoder_destroy(OpusDecoder *st); - -/** Parse an opus packet into one or more frames. - * Opus_decode will perform this operation internally so most applications do - * not need to use this function. - * This function does not copy the frames, the returned pointers are pointers into - * the input packet. - * @param [in] data char*: Opus packet to be parsed - * @param [in] len opus_int32: size of data - * @param [out] out_toc char*: TOC pointer - * @param [out] frames char*[48] encapsulated frames - * @param [out] size opus_int16[48] sizes of the encapsulated frames - * @param [out] payload_offset int*: returns the position of the payload within the packet (in bytes) - * @returns number of frames - */ -OPUS_EXPORT int opus_packet_parse( - const unsigned char *data, - opus_int32 len, - unsigned char *out_toc, - const unsigned char *frames[48], - opus_int16 size[48], - int *payload_offset -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5); - -/** Gets the bandwidth of an Opus packet. - * @param [in] data char*: Opus packet - * @retval OPUS_BANDWIDTH_NARROWBAND Narrowband (4kHz bandpass) - * @retval OPUS_BANDWIDTH_MEDIUMBAND Mediumband (6kHz bandpass) - * @retval OPUS_BANDWIDTH_WIDEBAND Wideband (8kHz bandpass) - * @retval OPUS_BANDWIDTH_SUPERWIDEBAND Superwideband (12kHz bandpass) - * @retval OPUS_BANDWIDTH_FULLBAND Fullband (20kHz bandpass) - * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_bandwidth(const unsigned char *data) OPUS_ARG_NONNULL(1); - -/** Gets the number of samples per frame from an Opus packet. - * @param [in] data char*: Opus packet. - * This must contain at least one byte of - * data. - * @param [in] Fs opus_int32: Sampling rate in Hz. - * This must be a multiple of 400, or - * inaccurate results will be returned. - * @returns Number of samples per frame. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_samples_per_frame(const unsigned char *data, opus_int32 Fs) OPUS_ARG_NONNULL(1); - -/** Gets the number of channels from an Opus packet. - * @param [in] data char*: Opus packet - * @returns Number of channels - * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_channels(const unsigned char *data) OPUS_ARG_NONNULL(1); - -/** Gets the number of frames in an Opus packet. - * @param [in] packet char*: Opus packet - * @param [in] len opus_int32: Length of packet - * @returns Number of frames - * @retval OPUS_BAD_ARG Insufficient data was passed to the function - * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1); - -/** Gets the number of samples of an Opus packet. - * @param [in] packet char*: Opus packet - * @param [in] len opus_int32: Length of packet - * @param [in] Fs opus_int32: Sampling rate in Hz. - * This must be a multiple of 400, or - * inaccurate results will be returned. - * @returns Number of samples - * @retval OPUS_BAD_ARG Insufficient data was passed to the function - * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len, opus_int32 Fs) OPUS_ARG_NONNULL(1); - -/** Gets the number of samples of an Opus packet. - * @param [in] dec OpusDecoder*: Decoder state - * @param [in] packet char*: Opus packet - * @param [in] len opus_int32: Length of packet - * @returns Number of samples - * @retval OPUS_BAD_ARG Insufficient data was passed to the function - * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2); - -/** Applies soft-clipping to bring a float signal within the [-1,1] range. If - * the signal is already in that range, nothing is done. If there are values - * outside of [-1,1], then the signal is clipped as smoothly as possible to - * both fit in the range and avoid creating excessive distortion in the - * process. - * @param [in,out] pcm float*: Input PCM and modified PCM - * @param [in] frame_size int Number of samples per channel to process - * @param [in] channels int: Number of channels - * @param [in,out] softclip_mem float*: State memory for the soft clipping process (one float per channel, initialized to zero) - */ -OPUS_EXPORT void opus_pcm_soft_clip(float *pcm, int frame_size, int channels, float *softclip_mem); - - -/**@}*/ - -/** @defgroup opus_repacketizer Repacketizer - * @{ - * - * The repacketizer can be used to merge multiple Opus packets into a single - * packet or alternatively to split Opus packets that have previously been - * merged. Splitting valid Opus packets is always guaranteed to succeed, - * whereas merging valid packets only succeeds if all frames have the same - * mode, bandwidth, and frame size, and when the total duration of the merged - * packet is no more than 120 ms. The 120 ms limit comes from the - * specification and limits decoder memory requirements at a point where - * framing overhead becomes negligible. - * - * The repacketizer currently only operates on elementary Opus - * streams. It will not manipualte multistream packets successfully, except in - * the degenerate case where they consist of data from a single stream. - * - * The repacketizing process starts with creating a repacketizer state, either - * by calling opus_repacketizer_create() or by allocating the memory yourself, - * e.g., - * @code - * OpusRepacketizer *rp; - * rp = (OpusRepacketizer*)malloc(opus_repacketizer_get_size()); - * if (rp != NULL) - * opus_repacketizer_init(rp); - * @endcode - * - * Then the application should submit packets with opus_repacketizer_cat(), - * extract new packets with opus_repacketizer_out() or - * opus_repacketizer_out_range(), and then reset the state for the next set of - * input packets via opus_repacketizer_init(). - * - * For example, to split a sequence of packets into individual frames: - * @code - * unsigned char *data; - * int len; - * while (get_next_packet(&data, &len)) - * { - * unsigned char out[1276]; - * opus_int32 out_len; - * int nb_frames; - * int err; - * int i; - * err = opus_repacketizer_cat(rp, data, len); - * if (err != OPUS_OK) - * { - * release_packet(data); - * return err; - * } - * nb_frames = opus_repacketizer_get_nb_frames(rp); - * for (i = 0; i < nb_frames; i++) - * { - * out_len = opus_repacketizer_out_range(rp, i, i+1, out, sizeof(out)); - * if (out_len < 0) - * { - * release_packet(data); - * return (int)out_len; - * } - * output_next_packet(out, out_len); - * } - * opus_repacketizer_init(rp); - * release_packet(data); - * } - * @endcode - * - * Alternatively, to combine a sequence of frames into packets that each - * contain up to TARGET_DURATION_MS milliseconds of data: - * @code - * // The maximum number of packets with duration TARGET_DURATION_MS occurs - * // when the frame size is 2.5 ms, for a total of (TARGET_DURATION_MS*2/5) - * // packets. - * unsigned char *data[(TARGET_DURATION_MS*2/5)+1]; - * opus_int32 len[(TARGET_DURATION_MS*2/5)+1]; - * int nb_packets; - * unsigned char out[1277*(TARGET_DURATION_MS*2/2)]; - * opus_int32 out_len; - * int prev_toc; - * nb_packets = 0; - * while (get_next_packet(data+nb_packets, len+nb_packets)) - * { - * int nb_frames; - * int err; - * nb_frames = opus_packet_get_nb_frames(data[nb_packets], len[nb_packets]); - * if (nb_frames < 1) - * { - * release_packets(data, nb_packets+1); - * return nb_frames; - * } - * nb_frames += opus_repacketizer_get_nb_frames(rp); - * // If adding the next packet would exceed our target, or it has an - * // incompatible TOC sequence, output the packets we already have before - * // submitting it. - * // N.B., The nb_packets > 0 check ensures we've submitted at least one - * // packet since the last call to opus_repacketizer_init(). Otherwise a - * // single packet longer than TARGET_DURATION_MS would cause us to try to - * // output an (invalid) empty packet. It also ensures that prev_toc has - * // been set to a valid value. Additionally, len[nb_packets] > 0 is - * // guaranteed by the call to opus_packet_get_nb_frames() above, so the - * // reference to data[nb_packets][0] should be valid. - * if (nb_packets > 0 && ( - * ((prev_toc & 0xFC) != (data[nb_packets][0] & 0xFC)) || - * opus_packet_get_samples_per_frame(data[nb_packets], 48000)*nb_frames > - * TARGET_DURATION_MS*48)) - * { - * out_len = opus_repacketizer_out(rp, out, sizeof(out)); - * if (out_len < 0) - * { - * release_packets(data, nb_packets+1); - * return (int)out_len; - * } - * output_next_packet(out, out_len); - * opus_repacketizer_init(rp); - * release_packets(data, nb_packets); - * data[0] = data[nb_packets]; - * len[0] = len[nb_packets]; - * nb_packets = 0; - * } - * err = opus_repacketizer_cat(rp, data[nb_packets], len[nb_packets]); - * if (err != OPUS_OK) - * { - * release_packets(data, nb_packets+1); - * return err; - * } - * prev_toc = data[nb_packets][0]; - * nb_packets++; - * } - * // Output the final, partial packet. - * if (nb_packets > 0) - * { - * out_len = opus_repacketizer_out(rp, out, sizeof(out)); - * release_packets(data, nb_packets); - * if (out_len < 0) - * return (int)out_len; - * output_next_packet(out, out_len); - * } - * @endcode - * - * An alternate way of merging packets is to simply call opus_repacketizer_cat() - * unconditionally until it fails. At that point, the merged packet can be - * obtained with opus_repacketizer_out() and the input packet for which - * opus_repacketizer_cat() needs to be re-added to a newly reinitialized - * repacketizer state. - */ - -typedef struct OpusRepacketizer OpusRepacketizer; - -/** Gets the size of an OpusRepacketizer structure. - * @returns The size in bytes. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_size(void); - -/** (Re)initializes a previously allocated repacketizer state. - * The state must be at least the size returned by opus_repacketizer_get_size(). - * This can be used for applications which use their own allocator instead of - * malloc(). - * It must also be called to reset the queue of packets waiting to be - * repacketized, which is necessary if the maximum packet duration of 120 ms - * is reached or if you wish to submit packets with a different Opus - * configuration (coding mode, audio bandwidth, frame size, or channel count). - * Failure to do so will prevent a new packet from being added with - * opus_repacketizer_cat(). - * @see opus_repacketizer_create - * @see opus_repacketizer_get_size - * @see opus_repacketizer_cat - * @param rp OpusRepacketizer*: The repacketizer state to - * (re)initialize. - * @returns A pointer to the same repacketizer state that was passed in. - */ -OPUS_EXPORT OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1); - -/** Allocates memory and initializes the new repacketizer with - * opus_repacketizer_init(). - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusRepacketizer *opus_repacketizer_create(void); - -/** Frees an OpusRepacketizer allocated by - * opus_repacketizer_create(). - * @param[in] rp OpusRepacketizer*: State to be freed. - */ -OPUS_EXPORT void opus_repacketizer_destroy(OpusRepacketizer *rp); - -/** Add a packet to the current repacketizer state. - * This packet must match the configuration of any packets already submitted - * for repacketization since the last call to opus_repacketizer_init(). - * This means that it must have the same coding mode, audio bandwidth, frame - * size, and channel count. - * This can be checked in advance by examining the top 6 bits of the first - * byte of the packet, and ensuring they match the top 6 bits of the first - * byte of any previously submitted packet. - * The total duration of audio in the repacketizer state also must not exceed - * 120 ms, the maximum duration of a single packet, after adding this packet. - * - * The contents of the current repacketizer state can be extracted into new - * packets using opus_repacketizer_out() or opus_repacketizer_out_range(). - * - * In order to add a packet with a different configuration or to add more - * audio beyond 120 ms, you must clear the repacketizer state by calling - * opus_repacketizer_init(). - * If a packet is too large to add to the current repacketizer state, no part - * of it is added, even if it contains multiple frames, some of which might - * fit. - * If you wish to be able to add parts of such packets, you should first use - * another repacketizer to split the packet into pieces and add them - * individually. - * @see opus_repacketizer_out_range - * @see opus_repacketizer_out - * @see opus_repacketizer_init - * @param rp OpusRepacketizer*: The repacketizer state to which to - * add the packet. - * @param[in] data const unsigned char*: The packet data. - * The application must ensure - * this pointer remains valid - * until the next call to - * opus_repacketizer_init() or - * opus_repacketizer_destroy(). - * @param len opus_int32: The number of bytes in the packet data. - * @returns An error code indicating whether or not the operation succeeded. - * @retval #OPUS_OK The packet's contents have been added to the repacketizer - * state. - * @retval #OPUS_INVALID_PACKET The packet did not have a valid TOC sequence, - * the packet's TOC sequence was not compatible - * with previously submitted packets (because - * the coding mode, audio bandwidth, frame size, - * or channel count did not match), or adding - * this packet would increase the total amount of - * audio stored in the repacketizer state to more - * than 120 ms. - */ -OPUS_EXPORT int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2); - - -/** Construct a new packet from data previously submitted to the repacketizer - * state via opus_repacketizer_cat(). - * @param rp OpusRepacketizer*: The repacketizer state from which to - * construct the new packet. - * @param begin int: The index of the first frame in the current - * repacketizer state to include in the output. - * @param end int: One past the index of the last frame in the - * current repacketizer state to include in the - * output. - * @param[out] data const unsigned char*: The buffer in which to - * store the output packet. - * @param maxlen opus_int32: The maximum number of bytes to store in - * the output buffer. In order to guarantee - * success, this should be at least - * 1276 for a single frame, - * or for multiple frames, - * 1277*(end-begin). - * However, 1*(end-begin) plus - * the size of all packet data submitted to - * the repacketizer since the last call to - * opus_repacketizer_init() or - * opus_repacketizer_create() is also - * sufficient, and possibly much smaller. - * @returns The total size of the output packet on success, or an error code - * on failure. - * @retval #OPUS_BAD_ARG [begin,end) was an invalid range of - * frames (begin < 0, begin >= end, or end > - * opus_repacketizer_get_nb_frames()). - * @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the - * complete output packet. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); - -/** Return the total number of frames contained in packet data submitted to - * the repacketizer state so far via opus_repacketizer_cat() since the last - * call to opus_repacketizer_init() or opus_repacketizer_create(). - * This defines the valid range of packets that can be extracted with - * opus_repacketizer_out_range() or opus_repacketizer_out(). - * @param rp OpusRepacketizer*: The repacketizer state containing the - * frames. - * @returns The total number of frames contained in the packet data submitted - * to the repacketizer state. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1); - -/** Construct a new packet from data previously submitted to the repacketizer - * state via opus_repacketizer_cat(). - * This is a convenience routine that returns all the data submitted so far - * in a single packet. - * It is equivalent to calling - * @code - * opus_repacketizer_out_range(rp, 0, opus_repacketizer_get_nb_frames(rp), - * data, maxlen) - * @endcode - * @param rp OpusRepacketizer*: The repacketizer state from which to - * construct the new packet. - * @param[out] data const unsigned char*: The buffer in which to - * store the output packet. - * @param maxlen opus_int32: The maximum number of bytes to store in - * the output buffer. In order to guarantee - * success, this should be at least - * 1277*opus_repacketizer_get_nb_frames(rp). - * However, - * 1*opus_repacketizer_get_nb_frames(rp) - * plus the size of all packet data - * submitted to the repacketizer since the - * last call to opus_repacketizer_init() or - * opus_repacketizer_create() is also - * sufficient, and possibly much smaller. - * @returns The total size of the output packet on success, or an error code - * on failure. - * @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the - * complete output packet. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1); - -/** Pads a given Opus packet to a larger size (possibly changing the TOC sequence). - * @param[in,out] data const unsigned char*: The buffer containing the - * packet to pad. - * @param len opus_int32: The size of the packet. - * This must be at least 1. - * @param new_len opus_int32: The desired size of the packet after padding. - * This must be at least as large as len. - * @returns an error code - * @retval #OPUS_OK \a on success. - * @retval #OPUS_BAD_ARG \a len was less than 1 or new_len was less than len. - * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet. - */ -OPUS_EXPORT int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len); - -/** Remove all padding from a given Opus packet and rewrite the TOC sequence to - * minimize space usage. - * @param[in,out] data const unsigned char*: The buffer containing the - * packet to strip. - * @param len opus_int32: The size of the packet. - * This must be at least 1. - * @returns The new size of the output packet on success, or an error code - * on failure. - * @retval #OPUS_BAD_ARG \a len was less than 1. - * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_packet_unpad(unsigned char *data, opus_int32 len); - -/** Pads a given Opus multi-stream packet to a larger size (possibly changing the TOC sequence). - * @param[in,out] data const unsigned char*: The buffer containing the - * packet to pad. - * @param len opus_int32: The size of the packet. - * This must be at least 1. - * @param new_len opus_int32: The desired size of the packet after padding. - * This must be at least 1. - * @param nb_streams opus_int32: The number of streams (not channels) in the packet. - * This must be at least as large as len. - * @returns an error code - * @retval #OPUS_OK \a on success. - * @retval #OPUS_BAD_ARG \a len was less than 1. - * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet. - */ -OPUS_EXPORT int opus_multistream_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len, int nb_streams); - -/** Remove all padding from a given Opus multi-stream packet and rewrite the TOC sequence to - * minimize space usage. - * @param[in,out] data const unsigned char*: The buffer containing the - * packet to strip. - * @param len opus_int32: The size of the packet. - * This must be at least 1. - * @param nb_streams opus_int32: The number of streams (not channels) in the packet. - * This must be at least 1. - * @returns The new size of the output packet on success, or an error code - * on failure. - * @retval #OPUS_BAD_ARG \a len was less than 1 or new_len was less than len. - * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, int nb_streams); - -/**@}*/ - -#ifdef __cplusplus -} -#endif - -#endif /* OPUS_H */ diff --git a/library/opusencoder/src/main/cpp/opus/include/opus_custom.h b/library/opusencoder/src/main/cpp/opus/include/opus_custom.h deleted file mode 100644 index 41f36bf2fb..0000000000 --- a/library/opusencoder/src/main/cpp/opus/include/opus_custom.h +++ /dev/null @@ -1,342 +0,0 @@ -/* Copyright (c) 2007-2008 CSIRO - Copyright (c) 2007-2009 Xiph.Org Foundation - Copyright (c) 2008-2012 Gregory Maxwell - Written by Jean-Marc Valin and Gregory Maxwell */ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/** - @file opus_custom.h - @brief Opus-Custom reference implementation API - */ - -#ifndef OPUS_CUSTOM_H -#define OPUS_CUSTOM_H - -#include "opus_defines.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef CUSTOM_MODES -# define OPUS_CUSTOM_EXPORT OPUS_EXPORT -# define OPUS_CUSTOM_EXPORT_STATIC OPUS_EXPORT -#else -# define OPUS_CUSTOM_EXPORT -# ifdef OPUS_BUILD -# define OPUS_CUSTOM_EXPORT_STATIC static OPUS_INLINE -# else -# define OPUS_CUSTOM_EXPORT_STATIC -# endif -#endif - -/** @defgroup opus_custom Opus Custom - * @{ - * Opus Custom is an optional part of the Opus specification and - * reference implementation which uses a distinct API from the regular - * API and supports frame sizes that are not normally supported.\ Use - * of Opus Custom is discouraged for all but very special applications - * for which a frame size different from 2.5, 5, 10, or 20 ms is needed - * (for either complexity or latency reasons) and where interoperability - * is less important. - * - * In addition to the interoperability limitations the use of Opus custom - * disables a substantial chunk of the codec and generally lowers the - * quality available at a given bitrate. Normally when an application needs - * a different frame size from the codec it should buffer to match the - * sizes but this adds a small amount of delay which may be important - * in some very low latency applications. Some transports (especially - * constant rate RF transports) may also work best with frames of - * particular durations. - * - * Libopus only supports custom modes if they are enabled at compile time. - * - * The Opus Custom API is similar to the regular API but the - * @ref opus_encoder_create and @ref opus_decoder_create calls take - * an additional mode parameter which is a structure produced by - * a call to @ref opus_custom_mode_create. Both the encoder and decoder - * must create a mode using the same sample rate (fs) and frame size - * (frame size) so these parameters must either be signaled out of band - * or fixed in a particular implementation. - * - * Similar to regular Opus the custom modes support on the fly frame size - * switching, but the sizes available depend on the particular frame size in - * use. For some initial frame sizes on a single on the fly size is available. - */ - -/** Contains the state of an encoder. One encoder state is needed - for each stream. It is initialized once at the beginning of the - stream. Do *not* re-initialize the state for every frame. - @brief Encoder state - */ -typedef struct OpusCustomEncoder OpusCustomEncoder; - -/** State of the decoder. One decoder state is needed for each stream. - It is initialized once at the beginning of the stream. Do *not* - re-initialize the state for every frame. - @brief Decoder state - */ -typedef struct OpusCustomDecoder OpusCustomDecoder; - -/** The mode contains all the information necessary to create an - encoder. Both the encoder and decoder need to be initialized - with exactly the same mode, otherwise the output will be - corrupted. - @brief Mode configuration - */ -typedef struct OpusCustomMode OpusCustomMode; - -/** Creates a new mode struct. This will be passed to an encoder or - * decoder. The mode MUST NOT BE DESTROYED until the encoders and - * decoders that use it are destroyed as well. - * @param [in] Fs int: Sampling rate (8000 to 96000 Hz) - * @param [in] frame_size int: Number of samples (per channel) to encode in each - * packet (64 - 1024, prime factorization must contain zero or more 2s, 3s, or 5s and no other primes) - * @param [out] error int*: Returned error code (if NULL, no error will be returned) - * @return A newly created mode - */ -OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error); - -/** Destroys a mode struct. Only call this after all encoders and - * decoders using this mode are destroyed as well. - * @param [in] mode OpusCustomMode*: Mode to be freed. - */ -OPUS_CUSTOM_EXPORT void opus_custom_mode_destroy(OpusCustomMode *mode); - - -#if !defined(OPUS_BUILD) || defined(CELT_ENCODER_C) - -/* Encoder */ -/** Gets the size of an OpusCustomEncoder structure. - * @param [in] mode OpusCustomMode *: Mode configuration - * @param [in] channels int: Number of channels - * @returns size - */ -OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_encoder_get_size( - const OpusCustomMode *mode, - int channels -) OPUS_ARG_NONNULL(1); - -# ifdef CUSTOM_MODES -/** Initializes a previously allocated encoder state - * The memory pointed to by st must be the size returned by opus_custom_encoder_get_size. - * This is intended for applications which use their own allocator instead of malloc. - * @see opus_custom_encoder_create(),opus_custom_encoder_get_size() - * To reset a previously initialized state use the OPUS_RESET_STATE CTL. - * @param [in] st OpusCustomEncoder*: Encoder state - * @param [in] mode OpusCustomMode *: Contains all the information about the characteristics of - * the stream (must be the same characteristics as used for the - * decoder) - * @param [in] channels int: Number of channels - * @return OPUS_OK Success or @ref opus_errorcodes - */ -OPUS_CUSTOM_EXPORT int opus_custom_encoder_init( - OpusCustomEncoder *st, - const OpusCustomMode *mode, - int channels -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2); -# endif -#endif - - -/** Creates a new encoder state. Each stream needs its own encoder - * state (can't be shared across simultaneous streams). - * @param [in] mode OpusCustomMode*: Contains all the information about the characteristics of - * the stream (must be the same characteristics as used for the - * decoder) - * @param [in] channels int: Number of channels - * @param [out] error int*: Returns an error code - * @return Newly created encoder state. -*/ -OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomEncoder *opus_custom_encoder_create( - const OpusCustomMode *mode, - int channels, - int *error -) OPUS_ARG_NONNULL(1); - - -/** Destroys a an encoder state. - * @param[in] st OpusCustomEncoder*: State to be freed. - */ -OPUS_CUSTOM_EXPORT void opus_custom_encoder_destroy(OpusCustomEncoder *st); - -/** Encodes a frame of audio. - * @param [in] st OpusCustomEncoder*: Encoder state - * @param [in] pcm float*: PCM audio in float format, with a normal range of +/-1.0. - * Samples with a range beyond +/-1.0 are supported but will - * be clipped by decoders using the integer API and should - * only be used if it is known that the far end supports - * extended dynamic range. There must be exactly - * frame_size samples per channel. - * @param [in] frame_size int: Number of samples per frame of input signal - * @param [out] compressed char *: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long. - * @param [in] maxCompressedBytes int: Maximum number of bytes to use for compressing the frame - * (can change from one frame to another) - * @return Number of bytes written to "compressed". - * If negative, an error has occurred (see error codes). It is IMPORTANT that - * the length returned be somehow transmitted to the decoder. Otherwise, no - * decoding is possible. - */ -OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode_float( - OpusCustomEncoder *st, - const float *pcm, - int frame_size, - unsigned char *compressed, - int maxCompressedBytes -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); - -/** Encodes a frame of audio. - * @param [in] st OpusCustomEncoder*: Encoder state - * @param [in] pcm opus_int16*: PCM audio in signed 16-bit format (native endian). - * There must be exactly frame_size samples per channel. - * @param [in] frame_size int: Number of samples per frame of input signal - * @param [out] compressed char *: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long. - * @param [in] maxCompressedBytes int: Maximum number of bytes to use for compressing the frame - * (can change from one frame to another) - * @return Number of bytes written to "compressed". - * If negative, an error has occurred (see error codes). It is IMPORTANT that - * the length returned be somehow transmitted to the decoder. Otherwise, no - * decoding is possible. - */ -OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode( - OpusCustomEncoder *st, - const opus_int16 *pcm, - int frame_size, - unsigned char *compressed, - int maxCompressedBytes -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); - -/** Perform a CTL function on an Opus custom encoder. - * - * Generally the request and subsequent arguments are generated - * by a convenience macro. - * @see opus_encoderctls - */ -OPUS_CUSTOM_EXPORT int opus_custom_encoder_ctl(OpusCustomEncoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1); - - -#if !defined(OPUS_BUILD) || defined(CELT_DECODER_C) -/* Decoder */ - -/** Gets the size of an OpusCustomDecoder structure. - * @param [in] mode OpusCustomMode *: Mode configuration - * @param [in] channels int: Number of channels - * @returns size - */ -OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_decoder_get_size( - const OpusCustomMode *mode, - int channels -) OPUS_ARG_NONNULL(1); - -/** Initializes a previously allocated decoder state - * The memory pointed to by st must be the size returned by opus_custom_decoder_get_size. - * This is intended for applications which use their own allocator instead of malloc. - * @see opus_custom_decoder_create(),opus_custom_decoder_get_size() - * To reset a previously initialized state use the OPUS_RESET_STATE CTL. - * @param [in] st OpusCustomDecoder*: Decoder state - * @param [in] mode OpusCustomMode *: Contains all the information about the characteristics of - * the stream (must be the same characteristics as used for the - * encoder) - * @param [in] channels int: Number of channels - * @return OPUS_OK Success or @ref opus_errorcodes - */ -OPUS_CUSTOM_EXPORT_STATIC int opus_custom_decoder_init( - OpusCustomDecoder *st, - const OpusCustomMode *mode, - int channels -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2); - -#endif - - -/** Creates a new decoder state. Each stream needs its own decoder state (can't - * be shared across simultaneous streams). - * @param [in] mode OpusCustomMode: Contains all the information about the characteristics of the - * stream (must be the same characteristics as used for the encoder) - * @param [in] channels int: Number of channels - * @param [out] error int*: Returns an error code - * @return Newly created decoder state. - */ -OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomDecoder *opus_custom_decoder_create( - const OpusCustomMode *mode, - int channels, - int *error -) OPUS_ARG_NONNULL(1); - -/** Destroys a an decoder state. - * @param[in] st OpusCustomDecoder*: State to be freed. - */ -OPUS_CUSTOM_EXPORT void opus_custom_decoder_destroy(OpusCustomDecoder *st); - -/** Decode an opus custom frame with floating point output - * @param [in] st OpusCustomDecoder*: Decoder state - * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss - * @param [in] len int: Number of bytes in payload - * @param [out] pcm float*: Output signal (interleaved if 2 channels). length - * is frame_size*channels*sizeof(float) - * @param [in] frame_size Number of samples per channel of available space in *pcm. - * @returns Number of decoded samples or @ref opus_errorcodes - */ -OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode_float( - OpusCustomDecoder *st, - const unsigned char *data, - int len, - float *pcm, - int frame_size -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); - -/** Decode an opus custom frame - * @param [in] st OpusCustomDecoder*: Decoder state - * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss - * @param [in] len int: Number of bytes in payload - * @param [out] pcm opus_int16*: Output signal (interleaved if 2 channels). length - * is frame_size*channels*sizeof(opus_int16) - * @param [in] frame_size Number of samples per channel of available space in *pcm. - * @returns Number of decoded samples or @ref opus_errorcodes - */ -OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode( - OpusCustomDecoder *st, - const unsigned char *data, - int len, - opus_int16 *pcm, - int frame_size -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); - -/** Perform a CTL function on an Opus custom decoder. - * - * Generally the request and subsequent arguments are generated - * by a convenience macro. - * @see opus_genericctls - */ -OPUS_CUSTOM_EXPORT int opus_custom_decoder_ctl(OpusCustomDecoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1); - -/**@}*/ - -#ifdef __cplusplus -} -#endif - -#endif /* OPUS_CUSTOM_H */ diff --git a/library/opusencoder/src/main/cpp/opus/include/opus_defines.h b/library/opusencoder/src/main/cpp/opus/include/opus_defines.h deleted file mode 100644 index fbf5d0eb74..0000000000 --- a/library/opusencoder/src/main/cpp/opus/include/opus_defines.h +++ /dev/null @@ -1,788 +0,0 @@ -/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited - Written by Jean-Marc Valin and Koen Vos */ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/** - * @file opus_defines.h - * @brief Opus reference implementation constants - */ - -#ifndef OPUS_DEFINES_H -#define OPUS_DEFINES_H - -#include "opus_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** @defgroup opus_errorcodes Error codes - * @{ - */ -/** No error @hideinitializer*/ -#define OPUS_OK 0 -/** One or more invalid/out of range arguments @hideinitializer*/ -#define OPUS_BAD_ARG -1 -/** Not enough bytes allocated in the buffer @hideinitializer*/ -#define OPUS_BUFFER_TOO_SMALL -2 -/** An internal error was detected @hideinitializer*/ -#define OPUS_INTERNAL_ERROR -3 -/** The compressed data passed is corrupted @hideinitializer*/ -#define OPUS_INVALID_PACKET -4 -/** Invalid/unsupported request number @hideinitializer*/ -#define OPUS_UNIMPLEMENTED -5 -/** An encoder or decoder structure is invalid or already freed @hideinitializer*/ -#define OPUS_INVALID_STATE -6 -/** Memory allocation has failed @hideinitializer*/ -#define OPUS_ALLOC_FAIL -7 -/**@}*/ - -/** @cond OPUS_INTERNAL_DOC */ -/**Export control for opus functions */ - -#ifndef OPUS_EXPORT -# if defined(WIN32) -# if defined(OPUS_BUILD) && defined(DLL_EXPORT) -# define OPUS_EXPORT __declspec(dllexport) -# else -# define OPUS_EXPORT -# endif -# elif defined(__GNUC__) && defined(OPUS_BUILD) -# define OPUS_EXPORT __attribute__ ((visibility ("default"))) -# else -# define OPUS_EXPORT -# endif -#endif - -# if !defined(OPUS_GNUC_PREREQ) -# if defined(__GNUC__)&&defined(__GNUC_MINOR__) -# define OPUS_GNUC_PREREQ(_maj,_min) \ - ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) -# else -# define OPUS_GNUC_PREREQ(_maj,_min) 0 -# endif -# endif - -#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) -# if OPUS_GNUC_PREREQ(3,0) -# define OPUS_RESTRICT __restrict__ -# elif (defined(_MSC_VER) && _MSC_VER >= 1400) -# define OPUS_RESTRICT __restrict -# else -# define OPUS_RESTRICT -# endif -#else -# define OPUS_RESTRICT restrict -#endif - -#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) -# if OPUS_GNUC_PREREQ(2,7) -# define OPUS_INLINE __inline__ -# elif (defined(_MSC_VER)) -# define OPUS_INLINE __inline -# else -# define OPUS_INLINE -# endif -#else -# define OPUS_INLINE inline -#endif - -/**Warning attributes for opus functions - * NONNULL is not used in OPUS_BUILD to avoid the compiler optimizing out - * some paranoid null checks. */ -#if defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4) -# define OPUS_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__)) -#else -# define OPUS_WARN_UNUSED_RESULT -#endif -#if !defined(OPUS_BUILD) && defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4) -# define OPUS_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x))) -#else -# define OPUS_ARG_NONNULL(_x) -#endif - -/** These are the actual Encoder CTL ID numbers. - * They should not be used directly by applications. - * In general, SETs should be even and GETs should be odd.*/ -#define OPUS_SET_APPLICATION_REQUEST 4000 -#define OPUS_GET_APPLICATION_REQUEST 4001 -#define OPUS_SET_BITRATE_REQUEST 4002 -#define OPUS_GET_BITRATE_REQUEST 4003 -#define OPUS_SET_MAX_BANDWIDTH_REQUEST 4004 -#define OPUS_GET_MAX_BANDWIDTH_REQUEST 4005 -#define OPUS_SET_VBR_REQUEST 4006 -#define OPUS_GET_VBR_REQUEST 4007 -#define OPUS_SET_BANDWIDTH_REQUEST 4008 -#define OPUS_GET_BANDWIDTH_REQUEST 4009 -#define OPUS_SET_COMPLEXITY_REQUEST 4010 -#define OPUS_GET_COMPLEXITY_REQUEST 4011 -#define OPUS_SET_INBAND_FEC_REQUEST 4012 -#define OPUS_GET_INBAND_FEC_REQUEST 4013 -#define OPUS_SET_PACKET_LOSS_PERC_REQUEST 4014 -#define OPUS_GET_PACKET_LOSS_PERC_REQUEST 4015 -#define OPUS_SET_DTX_REQUEST 4016 -#define OPUS_GET_DTX_REQUEST 4017 -#define OPUS_SET_VBR_CONSTRAINT_REQUEST 4020 -#define OPUS_GET_VBR_CONSTRAINT_REQUEST 4021 -#define OPUS_SET_FORCE_CHANNELS_REQUEST 4022 -#define OPUS_GET_FORCE_CHANNELS_REQUEST 4023 -#define OPUS_SET_SIGNAL_REQUEST 4024 -#define OPUS_GET_SIGNAL_REQUEST 4025 -#define OPUS_GET_LOOKAHEAD_REQUEST 4027 -/* #define OPUS_RESET_STATE 4028 */ -#define OPUS_GET_SAMPLE_RATE_REQUEST 4029 -#define OPUS_GET_FINAL_RANGE_REQUEST 4031 -#define OPUS_GET_PITCH_REQUEST 4033 -#define OPUS_SET_GAIN_REQUEST 4034 -#define OPUS_GET_GAIN_REQUEST 4045 /* Should have been 4035 */ -#define OPUS_SET_LSB_DEPTH_REQUEST 4036 -#define OPUS_GET_LSB_DEPTH_REQUEST 4037 -#define OPUS_GET_LAST_PACKET_DURATION_REQUEST 4039 -#define OPUS_SET_EXPERT_FRAME_DURATION_REQUEST 4040 -#define OPUS_GET_EXPERT_FRAME_DURATION_REQUEST 4041 -#define OPUS_SET_PREDICTION_DISABLED_REQUEST 4042 -#define OPUS_GET_PREDICTION_DISABLED_REQUEST 4043 -/* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */ -#define OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST 4046 -#define OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST 4047 - -/** Defines for the presence of extended APIs. */ -#define OPUS_HAVE_OPUS_PROJECTION_H - -/* Macros to trigger compilation errors when the wrong types are provided to a CTL */ -#define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x)) -#define __opus_check_int_ptr(ptr) ((ptr) + ((ptr) - (opus_int32*)(ptr))) -#define __opus_check_uint_ptr(ptr) ((ptr) + ((ptr) - (opus_uint32*)(ptr))) -#define __opus_check_val16_ptr(ptr) ((ptr) + ((ptr) - (opus_val16*)(ptr))) -/** @endcond */ - -/** @defgroup opus_ctlvalues Pre-defined values for CTL interface - * @see opus_genericctls, opus_encoderctls - * @{ - */ -/* Values for the various encoder CTLs */ -#define OPUS_AUTO -1000 /**opus_int32: Allowed values: 0-10, inclusive. - * - * @hideinitializer */ -#define OPUS_SET_COMPLEXITY(x) OPUS_SET_COMPLEXITY_REQUEST, __opus_check_int(x) -/** Gets the encoder's complexity configuration. - * @see OPUS_SET_COMPLEXITY - * @param[out] x opus_int32 *: Returns a value in the range 0-10, - * inclusive. - * @hideinitializer */ -#define OPUS_GET_COMPLEXITY(x) OPUS_GET_COMPLEXITY_REQUEST, __opus_check_int_ptr(x) - -/** Configures the bitrate in the encoder. - * Rates from 500 to 512000 bits per second are meaningful, as well as the - * special values #OPUS_AUTO and #OPUS_BITRATE_MAX. - * The value #OPUS_BITRATE_MAX can be used to cause the codec to use as much - * rate as it can, which is useful for controlling the rate by adjusting the - * output buffer size. - * @see OPUS_GET_BITRATE - * @param[in] x opus_int32: Bitrate in bits per second. The default - * is determined based on the number of - * channels and the input sampling rate. - * @hideinitializer */ -#define OPUS_SET_BITRATE(x) OPUS_SET_BITRATE_REQUEST, __opus_check_int(x) -/** Gets the encoder's bitrate configuration. - * @see OPUS_SET_BITRATE - * @param[out] x opus_int32 *: Returns the bitrate in bits per second. - * The default is determined based on the - * number of channels and the input - * sampling rate. - * @hideinitializer */ -#define OPUS_GET_BITRATE(x) OPUS_GET_BITRATE_REQUEST, __opus_check_int_ptr(x) - -/** Enables or disables variable bitrate (VBR) in the encoder. - * The configured bitrate may not be met exactly because frames must - * be an integer number of bytes in length. - * @see OPUS_GET_VBR - * @see OPUS_SET_VBR_CONSTRAINT - * @param[in] x opus_int32: Allowed values: - *
- *
0
Hard CBR. For LPC/hybrid modes at very low bit-rate, this can - * cause noticeable quality degradation.
- *
1
VBR (default). The exact type of VBR is controlled by - * #OPUS_SET_VBR_CONSTRAINT.
- *
- * @hideinitializer */ -#define OPUS_SET_VBR(x) OPUS_SET_VBR_REQUEST, __opus_check_int(x) -/** Determine if variable bitrate (VBR) is enabled in the encoder. - * @see OPUS_SET_VBR - * @see OPUS_GET_VBR_CONSTRAINT - * @param[out] x opus_int32 *: Returns one of the following values: - *
- *
0
Hard CBR.
- *
1
VBR (default). The exact type of VBR may be retrieved via - * #OPUS_GET_VBR_CONSTRAINT.
- *
- * @hideinitializer */ -#define OPUS_GET_VBR(x) OPUS_GET_VBR_REQUEST, __opus_check_int_ptr(x) - -/** Enables or disables constrained VBR in the encoder. - * This setting is ignored when the encoder is in CBR mode. - * @warning Only the MDCT mode of Opus currently heeds the constraint. - * Speech mode ignores it completely, hybrid mode may fail to obey it - * if the LPC layer uses more bitrate than the constraint would have - * permitted. - * @see OPUS_GET_VBR_CONSTRAINT - * @see OPUS_SET_VBR - * @param[in] x opus_int32: Allowed values: - *
- *
0
Unconstrained VBR.
- *
1
Constrained VBR (default). This creates a maximum of one - * frame of buffering delay assuming a transport with a - * serialization speed of the nominal bitrate.
- *
- * @hideinitializer */ -#define OPUS_SET_VBR_CONSTRAINT(x) OPUS_SET_VBR_CONSTRAINT_REQUEST, __opus_check_int(x) -/** Determine if constrained VBR is enabled in the encoder. - * @see OPUS_SET_VBR_CONSTRAINT - * @see OPUS_GET_VBR - * @param[out] x opus_int32 *: Returns one of the following values: - *
- *
0
Unconstrained VBR.
- *
1
Constrained VBR (default).
- *
- * @hideinitializer */ -#define OPUS_GET_VBR_CONSTRAINT(x) OPUS_GET_VBR_CONSTRAINT_REQUEST, __opus_check_int_ptr(x) - -/** Configures mono/stereo forcing in the encoder. - * This can force the encoder to produce packets encoded as either mono or - * stereo, regardless of the format of the input audio. This is useful when - * the caller knows that the input signal is currently a mono source embedded - * in a stereo stream. - * @see OPUS_GET_FORCE_CHANNELS - * @param[in] x opus_int32: Allowed values: - *
- *
#OPUS_AUTO
Not forced (default)
- *
1
Forced mono
- *
2
Forced stereo
- *
- * @hideinitializer */ -#define OPUS_SET_FORCE_CHANNELS(x) OPUS_SET_FORCE_CHANNELS_REQUEST, __opus_check_int(x) -/** Gets the encoder's forced channel configuration. - * @see OPUS_SET_FORCE_CHANNELS - * @param[out] x opus_int32 *: - *
- *
#OPUS_AUTO
Not forced (default)
- *
1
Forced mono
- *
2
Forced stereo
- *
- * @hideinitializer */ -#define OPUS_GET_FORCE_CHANNELS(x) OPUS_GET_FORCE_CHANNELS_REQUEST, __opus_check_int_ptr(x) - -/** Configures the maximum bandpass that the encoder will select automatically. - * Applications should normally use this instead of #OPUS_SET_BANDWIDTH - * (leaving that set to the default, #OPUS_AUTO). This allows the - * application to set an upper bound based on the type of input it is - * providing, but still gives the encoder the freedom to reduce the bandpass - * when the bitrate becomes too low, for better overall quality. - * @see OPUS_GET_MAX_BANDWIDTH - * @param[in] x opus_int32: Allowed values: - *
- *
OPUS_BANDWIDTH_NARROWBAND
4 kHz passband
- *
OPUS_BANDWIDTH_MEDIUMBAND
6 kHz passband
- *
OPUS_BANDWIDTH_WIDEBAND
8 kHz passband
- *
OPUS_BANDWIDTH_SUPERWIDEBAND
12 kHz passband
- *
OPUS_BANDWIDTH_FULLBAND
20 kHz passband (default)
- *
- * @hideinitializer */ -#define OPUS_SET_MAX_BANDWIDTH(x) OPUS_SET_MAX_BANDWIDTH_REQUEST, __opus_check_int(x) - -/** Gets the encoder's configured maximum allowed bandpass. - * @see OPUS_SET_MAX_BANDWIDTH - * @param[out] x opus_int32 *: Allowed values: - *
- *
#OPUS_BANDWIDTH_NARROWBAND
4 kHz passband
- *
#OPUS_BANDWIDTH_MEDIUMBAND
6 kHz passband
- *
#OPUS_BANDWIDTH_WIDEBAND
8 kHz passband
- *
#OPUS_BANDWIDTH_SUPERWIDEBAND
12 kHz passband
- *
#OPUS_BANDWIDTH_FULLBAND
20 kHz passband (default)
- *
- * @hideinitializer */ -#define OPUS_GET_MAX_BANDWIDTH(x) OPUS_GET_MAX_BANDWIDTH_REQUEST, __opus_check_int_ptr(x) - -/** Sets the encoder's bandpass to a specific value. - * This prevents the encoder from automatically selecting the bandpass based - * on the available bitrate. If an application knows the bandpass of the input - * audio it is providing, it should normally use #OPUS_SET_MAX_BANDWIDTH - * instead, which still gives the encoder the freedom to reduce the bandpass - * when the bitrate becomes too low, for better overall quality. - * @see OPUS_GET_BANDWIDTH - * @param[in] x opus_int32: Allowed values: - *
- *
#OPUS_AUTO
(default)
- *
#OPUS_BANDWIDTH_NARROWBAND
4 kHz passband
- *
#OPUS_BANDWIDTH_MEDIUMBAND
6 kHz passband
- *
#OPUS_BANDWIDTH_WIDEBAND
8 kHz passband
- *
#OPUS_BANDWIDTH_SUPERWIDEBAND
12 kHz passband
- *
#OPUS_BANDWIDTH_FULLBAND
20 kHz passband
- *
- * @hideinitializer */ -#define OPUS_SET_BANDWIDTH(x) OPUS_SET_BANDWIDTH_REQUEST, __opus_check_int(x) - -/** Configures the type of signal being encoded. - * This is a hint which helps the encoder's mode selection. - * @see OPUS_GET_SIGNAL - * @param[in] x opus_int32: Allowed values: - *
- *
#OPUS_AUTO
(default)
- *
#OPUS_SIGNAL_VOICE
Bias thresholds towards choosing LPC or Hybrid modes.
- *
#OPUS_SIGNAL_MUSIC
Bias thresholds towards choosing MDCT modes.
- *
- * @hideinitializer */ -#define OPUS_SET_SIGNAL(x) OPUS_SET_SIGNAL_REQUEST, __opus_check_int(x) -/** Gets the encoder's configured signal type. - * @see OPUS_SET_SIGNAL - * @param[out] x opus_int32 *: Returns one of the following values: - *
- *
#OPUS_AUTO
(default)
- *
#OPUS_SIGNAL_VOICE
Bias thresholds towards choosing LPC or Hybrid modes.
- *
#OPUS_SIGNAL_MUSIC
Bias thresholds towards choosing MDCT modes.
- *
- * @hideinitializer */ -#define OPUS_GET_SIGNAL(x) OPUS_GET_SIGNAL_REQUEST, __opus_check_int_ptr(x) - - -/** Configures the encoder's intended application. - * The initial value is a mandatory argument to the encoder_create function. - * @see OPUS_GET_APPLICATION - * @param[in] x opus_int32: Returns one of the following values: - *
- *
#OPUS_APPLICATION_VOIP
- *
Process signal for improved speech intelligibility.
- *
#OPUS_APPLICATION_AUDIO
- *
Favor faithfulness to the original input.
- *
#OPUS_APPLICATION_RESTRICTED_LOWDELAY
- *
Configure the minimum possible coding delay by disabling certain modes - * of operation.
- *
- * @hideinitializer */ -#define OPUS_SET_APPLICATION(x) OPUS_SET_APPLICATION_REQUEST, __opus_check_int(x) -/** Gets the encoder's configured application. - * @see OPUS_SET_APPLICATION - * @param[out] x opus_int32 *: Returns one of the following values: - *
- *
#OPUS_APPLICATION_VOIP
- *
Process signal for improved speech intelligibility.
- *
#OPUS_APPLICATION_AUDIO
- *
Favor faithfulness to the original input.
- *
#OPUS_APPLICATION_RESTRICTED_LOWDELAY
- *
Configure the minimum possible coding delay by disabling certain modes - * of operation.
- *
- * @hideinitializer */ -#define OPUS_GET_APPLICATION(x) OPUS_GET_APPLICATION_REQUEST, __opus_check_int_ptr(x) - -/** Gets the total samples of delay added by the entire codec. - * This can be queried by the encoder and then the provided number of samples can be - * skipped on from the start of the decoder's output to provide time aligned input - * and output. From the perspective of a decoding application the real data begins this many - * samples late. - * - * The decoder contribution to this delay is identical for all decoders, but the - * encoder portion of the delay may vary from implementation to implementation, - * version to version, or even depend on the encoder's initial configuration. - * Applications needing delay compensation should call this CTL rather than - * hard-coding a value. - * @param[out] x opus_int32 *: Number of lookahead samples - * @hideinitializer */ -#define OPUS_GET_LOOKAHEAD(x) OPUS_GET_LOOKAHEAD_REQUEST, __opus_check_int_ptr(x) - -/** Configures the encoder's use of inband forward error correction (FEC). - * @note This is only applicable to the LPC layer - * @see OPUS_GET_INBAND_FEC - * @param[in] x opus_int32: Allowed values: - *
- *
0
Disable inband FEC (default).
- *
1
Enable inband FEC.
- *
- * @hideinitializer */ -#define OPUS_SET_INBAND_FEC(x) OPUS_SET_INBAND_FEC_REQUEST, __opus_check_int(x) -/** Gets encoder's configured use of inband forward error correction. - * @see OPUS_SET_INBAND_FEC - * @param[out] x opus_int32 *: Returns one of the following values: - *
- *
0
Inband FEC disabled (default).
- *
1
Inband FEC enabled.
- *
- * @hideinitializer */ -#define OPUS_GET_INBAND_FEC(x) OPUS_GET_INBAND_FEC_REQUEST, __opus_check_int_ptr(x) - -/** Configures the encoder's expected packet loss percentage. - * Higher values trigger progressively more loss resistant behavior in the encoder - * at the expense of quality at a given bitrate in the absence of packet loss, but - * greater quality under loss. - * @see OPUS_GET_PACKET_LOSS_PERC - * @param[in] x opus_int32: Loss percentage in the range 0-100, inclusive (default: 0). - * @hideinitializer */ -#define OPUS_SET_PACKET_LOSS_PERC(x) OPUS_SET_PACKET_LOSS_PERC_REQUEST, __opus_check_int(x) -/** Gets the encoder's configured packet loss percentage. - * @see OPUS_SET_PACKET_LOSS_PERC - * @param[out] x opus_int32 *: Returns the configured loss percentage - * in the range 0-100, inclusive (default: 0). - * @hideinitializer */ -#define OPUS_GET_PACKET_LOSS_PERC(x) OPUS_GET_PACKET_LOSS_PERC_REQUEST, __opus_check_int_ptr(x) - -/** Configures the encoder's use of discontinuous transmission (DTX). - * @note This is only applicable to the LPC layer - * @see OPUS_GET_DTX - * @param[in] x opus_int32: Allowed values: - *
- *
0
Disable DTX (default).
- *
1
Enabled DTX.
- *
- * @hideinitializer */ -#define OPUS_SET_DTX(x) OPUS_SET_DTX_REQUEST, __opus_check_int(x) -/** Gets encoder's configured use of discontinuous transmission. - * @see OPUS_SET_DTX - * @param[out] x opus_int32 *: Returns one of the following values: - *
- *
0
DTX disabled (default).
- *
1
DTX enabled.
- *
- * @hideinitializer */ -#define OPUS_GET_DTX(x) OPUS_GET_DTX_REQUEST, __opus_check_int_ptr(x) -/** Configures the depth of signal being encoded. - * - * This is a hint which helps the encoder identify silence and near-silence. - * It represents the number of significant bits of linear intensity below - * which the signal contains ignorable quantization or other noise. - * - * For example, OPUS_SET_LSB_DEPTH(14) would be an appropriate setting - * for G.711 u-law input. OPUS_SET_LSB_DEPTH(16) would be appropriate - * for 16-bit linear pcm input with opus_encode_float(). - * - * When using opus_encode() instead of opus_encode_float(), or when libopus - * is compiled for fixed-point, the encoder uses the minimum of the value - * set here and the value 16. - * - * @see OPUS_GET_LSB_DEPTH - * @param[in] x opus_int32: Input precision in bits, between 8 and 24 - * (default: 24). - * @hideinitializer */ -#define OPUS_SET_LSB_DEPTH(x) OPUS_SET_LSB_DEPTH_REQUEST, __opus_check_int(x) -/** Gets the encoder's configured signal depth. - * @see OPUS_SET_LSB_DEPTH - * @param[out] x opus_int32 *: Input precision in bits, between 8 and - * 24 (default: 24). - * @hideinitializer */ -#define OPUS_GET_LSB_DEPTH(x) OPUS_GET_LSB_DEPTH_REQUEST, __opus_check_int_ptr(x) - -/** Configures the encoder's use of variable duration frames. - * When variable duration is enabled, the encoder is free to use a shorter frame - * size than the one requested in the opus_encode*() call. - * It is then the user's responsibility - * to verify how much audio was encoded by checking the ToC byte of the encoded - * packet. The part of the audio that was not encoded needs to be resent to the - * encoder for the next call. Do not use this option unless you really - * know what you are doing. - * @see OPUS_GET_EXPERT_FRAME_DURATION - * @param[in] x opus_int32: Allowed values: - *
- *
OPUS_FRAMESIZE_ARG
Select frame size from the argument (default).
- *
OPUS_FRAMESIZE_2_5_MS
Use 2.5 ms frames.
- *
OPUS_FRAMESIZE_5_MS
Use 5 ms frames.
- *
OPUS_FRAMESIZE_10_MS
Use 10 ms frames.
- *
OPUS_FRAMESIZE_20_MS
Use 20 ms frames.
- *
OPUS_FRAMESIZE_40_MS
Use 40 ms frames.
- *
OPUS_FRAMESIZE_60_MS
Use 60 ms frames.
- *
OPUS_FRAMESIZE_80_MS
Use 80 ms frames.
- *
OPUS_FRAMESIZE_100_MS
Use 100 ms frames.
- *
OPUS_FRAMESIZE_120_MS
Use 120 ms frames.
- *
- * @hideinitializer */ -#define OPUS_SET_EXPERT_FRAME_DURATION(x) OPUS_SET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int(x) -/** Gets the encoder's configured use of variable duration frames. - * @see OPUS_SET_EXPERT_FRAME_DURATION - * @param[out] x opus_int32 *: Returns one of the following values: - *
- *
OPUS_FRAMESIZE_ARG
Select frame size from the argument (default).
- *
OPUS_FRAMESIZE_2_5_MS
Use 2.5 ms frames.
- *
OPUS_FRAMESIZE_5_MS
Use 5 ms frames.
- *
OPUS_FRAMESIZE_10_MS
Use 10 ms frames.
- *
OPUS_FRAMESIZE_20_MS
Use 20 ms frames.
- *
OPUS_FRAMESIZE_40_MS
Use 40 ms frames.
- *
OPUS_FRAMESIZE_60_MS
Use 60 ms frames.
- *
OPUS_FRAMESIZE_80_MS
Use 80 ms frames.
- *
OPUS_FRAMESIZE_100_MS
Use 100 ms frames.
- *
OPUS_FRAMESIZE_120_MS
Use 120 ms frames.
- *
- * @hideinitializer */ -#define OPUS_GET_EXPERT_FRAME_DURATION(x) OPUS_GET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int_ptr(x) - -/** If set to 1, disables almost all use of prediction, making frames almost - * completely independent. This reduces quality. - * @see OPUS_GET_PREDICTION_DISABLED - * @param[in] x opus_int32: Allowed values: - *
- *
0
Enable prediction (default).
- *
1
Disable prediction.
- *
- * @hideinitializer */ -#define OPUS_SET_PREDICTION_DISABLED(x) OPUS_SET_PREDICTION_DISABLED_REQUEST, __opus_check_int(x) -/** Gets the encoder's configured prediction status. - * @see OPUS_SET_PREDICTION_DISABLED - * @param[out] x opus_int32 *: Returns one of the following values: - *
- *
0
Prediction enabled (default).
- *
1
Prediction disabled.
- *
- * @hideinitializer */ -#define OPUS_GET_PREDICTION_DISABLED(x) OPUS_GET_PREDICTION_DISABLED_REQUEST, __opus_check_int_ptr(x) - -/**@}*/ - -/** @defgroup opus_genericctls Generic CTLs - * - * These macros are used with the \c opus_decoder_ctl and - * \c opus_encoder_ctl calls to generate a particular - * request. - * - * When called on an \c OpusDecoder they apply to that - * particular decoder instance. When called on an - * \c OpusEncoder they apply to the corresponding setting - * on that encoder instance, if present. - * - * Some usage examples: - * - * @code - * int ret; - * opus_int32 pitch; - * ret = opus_decoder_ctl(dec_ctx, OPUS_GET_PITCH(&pitch)); - * if (ret == OPUS_OK) return ret; - * - * opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE); - * opus_decoder_ctl(dec_ctx, OPUS_RESET_STATE); - * - * opus_int32 enc_bw, dec_bw; - * opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&enc_bw)); - * opus_decoder_ctl(dec_ctx, OPUS_GET_BANDWIDTH(&dec_bw)); - * if (enc_bw != dec_bw) { - * printf("packet bandwidth mismatch!\n"); - * } - * @endcode - * - * @see opus_encoder, opus_decoder_ctl, opus_encoder_ctl, opus_decoderctls, opus_encoderctls - * @{ - */ - -/** Resets the codec state to be equivalent to a freshly initialized state. - * This should be called when switching streams in order to prevent - * the back to back decoding from giving different results from - * one at a time decoding. - * @hideinitializer */ -#define OPUS_RESET_STATE 4028 - -/** Gets the final state of the codec's entropy coder. - * This is used for testing purposes, - * The encoder and decoder state should be identical after coding a payload - * (assuming no data corruption or software bugs) - * - * @param[out] x opus_uint32 *: Entropy coder state - * - * @hideinitializer */ -#define OPUS_GET_FINAL_RANGE(x) OPUS_GET_FINAL_RANGE_REQUEST, __opus_check_uint_ptr(x) - -/** Gets the encoder's configured bandpass or the decoder's last bandpass. - * @see OPUS_SET_BANDWIDTH - * @param[out] x opus_int32 *: Returns one of the following values: - *
- *
#OPUS_AUTO
(default)
- *
#OPUS_BANDWIDTH_NARROWBAND
4 kHz passband
- *
#OPUS_BANDWIDTH_MEDIUMBAND
6 kHz passband
- *
#OPUS_BANDWIDTH_WIDEBAND
8 kHz passband
- *
#OPUS_BANDWIDTH_SUPERWIDEBAND
12 kHz passband
- *
#OPUS_BANDWIDTH_FULLBAND
20 kHz passband
- *
- * @hideinitializer */ -#define OPUS_GET_BANDWIDTH(x) OPUS_GET_BANDWIDTH_REQUEST, __opus_check_int_ptr(x) - -/** Gets the sampling rate the encoder or decoder was initialized with. - * This simply returns the Fs value passed to opus_encoder_init() - * or opus_decoder_init(). - * @param[out] x opus_int32 *: Sampling rate of encoder or decoder. - * @hideinitializer - */ -#define OPUS_GET_SAMPLE_RATE(x) OPUS_GET_SAMPLE_RATE_REQUEST, __opus_check_int_ptr(x) - -/** If set to 1, disables the use of phase inversion for intensity stereo, - * improving the quality of mono downmixes, but slightly reducing normal - * stereo quality. Disabling phase inversion in the decoder does not comply - * with RFC 6716, although it does not cause any interoperability issue and - * is expected to become part of the Opus standard once RFC 6716 is updated - * by draft-ietf-codec-opus-update. - * @see OPUS_GET_PHASE_INVERSION_DISABLED - * @param[in] x opus_int32: Allowed values: - *
- *
0
Enable phase inversion (default).
- *
1
Disable phase inversion.
- *
- * @hideinitializer */ -#define OPUS_SET_PHASE_INVERSION_DISABLED(x) OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int(x) -/** Gets the encoder's configured phase inversion status. - * @see OPUS_SET_PHASE_INVERSION_DISABLED - * @param[out] x opus_int32 *: Returns one of the following values: - *
- *
0
Stereo phase inversion enabled (default).
- *
1
Stereo phase inversion disabled.
- *
- * @hideinitializer */ -#define OPUS_GET_PHASE_INVERSION_DISABLED(x) OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int_ptr(x) - -/**@}*/ - -/** @defgroup opus_decoderctls Decoder related CTLs - * @see opus_genericctls, opus_encoderctls, opus_decoder - * @{ - */ - -/** Configures decoder gain adjustment. - * Scales the decoded output by a factor specified in Q8 dB units. - * This has a maximum range of -32768 to 32767 inclusive, and returns - * OPUS_BAD_ARG otherwise. The default is zero indicating no adjustment. - * This setting survives decoder reset. - * - * gain = pow(10, x/(20.0*256)) - * - * @param[in] x opus_int32: Amount to scale PCM signal by in Q8 dB units. - * @hideinitializer */ -#define OPUS_SET_GAIN(x) OPUS_SET_GAIN_REQUEST, __opus_check_int(x) -/** Gets the decoder's configured gain adjustment. @see OPUS_SET_GAIN - * - * @param[out] x opus_int32 *: Amount to scale PCM signal by in Q8 dB units. - * @hideinitializer */ -#define OPUS_GET_GAIN(x) OPUS_GET_GAIN_REQUEST, __opus_check_int_ptr(x) - -/** Gets the duration (in samples) of the last packet successfully decoded or concealed. - * @param[out] x opus_int32 *: Number of samples (at current sampling rate). - * @hideinitializer */ -#define OPUS_GET_LAST_PACKET_DURATION(x) OPUS_GET_LAST_PACKET_DURATION_REQUEST, __opus_check_int_ptr(x) - -/** Gets the pitch of the last decoded frame, if available. - * This can be used for any post-processing algorithm requiring the use of pitch, - * e.g. time stretching/shortening. If the last frame was not voiced, or if the - * pitch was not coded in the frame, then zero is returned. - * - * This CTL is only implemented for decoder instances. - * - * @param[out] x opus_int32 *: pitch period at 48 kHz (or 0 if not available) - * - * @hideinitializer */ -#define OPUS_GET_PITCH(x) OPUS_GET_PITCH_REQUEST, __opus_check_int_ptr(x) - -/**@}*/ - -/** @defgroup opus_libinfo Opus library information functions - * @{ - */ - -/** Converts an opus error code into a human readable string. - * - * @param[in] error int: Error number - * @returns Error string - */ -OPUS_EXPORT const char *opus_strerror(int error); - -/** Gets the libopus version string. - * - * Applications may look for the substring "-fixed" in the version string to - * determine whether they have a fixed-point or floating-point build at - * runtime. - * - * @returns Version string - */ -OPUS_EXPORT const char *opus_get_version_string(void); -/**@}*/ - -#ifdef __cplusplus -} -#endif - -#endif /* OPUS_DEFINES_H */ diff --git a/library/opusencoder/src/main/cpp/opus/include/opus_multistream.h b/library/opusencoder/src/main/cpp/opus/include/opus_multistream.h deleted file mode 100644 index babcee6905..0000000000 --- a/library/opusencoder/src/main/cpp/opus/include/opus_multistream.h +++ /dev/null @@ -1,660 +0,0 @@ -/* Copyright (c) 2011 Xiph.Org Foundation - Written by Jean-Marc Valin */ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/** - * @file opus_multistream.h - * @brief Opus reference implementation multistream API - */ - -#ifndef OPUS_MULTISTREAM_H -#define OPUS_MULTISTREAM_H - -#include "opus.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** @cond OPUS_INTERNAL_DOC */ - -/** Macros to trigger compilation errors when the wrong types are provided to a - * CTL. */ -/**@{*/ -#define __opus_check_encstate_ptr(ptr) ((ptr) + ((ptr) - (OpusEncoder**)(ptr))) -#define __opus_check_decstate_ptr(ptr) ((ptr) + ((ptr) - (OpusDecoder**)(ptr))) -/**@}*/ - -/** These are the actual encoder and decoder CTL ID numbers. - * They should not be used directly by applications. - * In general, SETs should be even and GETs should be odd.*/ -/**@{*/ -#define OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST 5120 -#define OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST 5122 -/**@}*/ - -/** @endcond */ - -/** @defgroup opus_multistream_ctls Multistream specific encoder and decoder CTLs - * - * These are convenience macros that are specific to the - * opus_multistream_encoder_ctl() and opus_multistream_decoder_ctl() - * interface. - * The CTLs from @ref opus_genericctls, @ref opus_encoderctls, and - * @ref opus_decoderctls may be applied to a multistream encoder or decoder as - * well. - * In addition, you may retrieve the encoder or decoder state for an specific - * stream via #OPUS_MULTISTREAM_GET_ENCODER_STATE or - * #OPUS_MULTISTREAM_GET_DECODER_STATE and apply CTLs to it individually. - */ -/**@{*/ - -/** Gets the encoder state for an individual stream of a multistream encoder. - * @param[in] x opus_int32: The index of the stream whose encoder you - * wish to retrieve. - * This must be non-negative and less than - * the streams parameter used - * to initialize the encoder. - * @param[out] y OpusEncoder**: Returns a pointer to the given - * encoder state. - * @retval OPUS_BAD_ARG The index of the requested stream was out of range. - * @hideinitializer - */ -#define OPUS_MULTISTREAM_GET_ENCODER_STATE(x,y) OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST, __opus_check_int(x), __opus_check_encstate_ptr(y) - -/** Gets the decoder state for an individual stream of a multistream decoder. - * @param[in] x opus_int32: The index of the stream whose decoder you - * wish to retrieve. - * This must be non-negative and less than - * the streams parameter used - * to initialize the decoder. - * @param[out] y OpusDecoder**: Returns a pointer to the given - * decoder state. - * @retval OPUS_BAD_ARG The index of the requested stream was out of range. - * @hideinitializer - */ -#define OPUS_MULTISTREAM_GET_DECODER_STATE(x,y) OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST, __opus_check_int(x), __opus_check_decstate_ptr(y) - -/**@}*/ - -/** @defgroup opus_multistream Opus Multistream API - * @{ - * - * The multistream API allows individual Opus streams to be combined into a - * single packet, enabling support for up to 255 channels. Unlike an - * elementary Opus stream, the encoder and decoder must negotiate the channel - * configuration before the decoder can successfully interpret the data in the - * packets produced by the encoder. Some basic information, such as packet - * duration, can be computed without any special negotiation. - * - * The format for multistream Opus packets is defined in - * RFC 7845 - * and is based on the self-delimited Opus framing described in Appendix B of - * RFC 6716. - * Normal Opus packets are just a degenerate case of multistream Opus packets, - * and can be encoded or decoded with the multistream API by setting - * streams to 1 when initializing the encoder or - * decoder. - * - * Multistream Opus streams can contain up to 255 elementary Opus streams. - * These may be either "uncoupled" or "coupled", indicating that the decoder - * is configured to decode them to either 1 or 2 channels, respectively. - * The streams are ordered so that all coupled streams appear at the - * beginning. - * - * A mapping table defines which decoded channel i - * should be used for each input/output (I/O) channel j. This table is - * typically provided as an unsigned char array. - * Let i = mapping[j] be the index for I/O channel j. - * If i < 2*coupled_streams, then I/O channel j is - * encoded as the left channel of stream (i/2) if i - * is even, or as the right channel of stream (i/2) if - * i is odd. Otherwise, I/O channel j is encoded as - * mono in stream (i - coupled_streams), unless it has the special - * value 255, in which case it is omitted from the encoding entirely (the - * decoder will reproduce it as silence). Each value i must either - * be the special value 255 or be less than streams + coupled_streams. - * - * The output channels specified by the encoder - * should use the - * Vorbis - * channel ordering. A decoder may wish to apply an additional permutation - * to the mapping the encoder used to achieve a different output channel - * order (e.g. for outputing in WAV order). - * - * Each multistream packet contains an Opus packet for each stream, and all of - * the Opus packets in a single multistream packet must have the same - * duration. Therefore the duration of a multistream packet can be extracted - * from the TOC sequence of the first stream, which is located at the - * beginning of the packet, just like an elementary Opus stream: - * - * @code - * int nb_samples; - * int nb_frames; - * nb_frames = opus_packet_get_nb_frames(data, len); - * if (nb_frames < 1) - * return nb_frames; - * nb_samples = opus_packet_get_samples_per_frame(data, 48000) * nb_frames; - * @endcode - * - * The general encoding and decoding process proceeds exactly the same as in - * the normal @ref opus_encoder and @ref opus_decoder APIs. - * See their documentation for an overview of how to use the corresponding - * multistream functions. - */ - -/** Opus multistream encoder state. - * This contains the complete state of a multistream Opus encoder. - * It is position independent and can be freely copied. - * @see opus_multistream_encoder_create - * @see opus_multistream_encoder_init - */ -typedef struct OpusMSEncoder OpusMSEncoder; - -/** Opus multistream decoder state. - * This contains the complete state of a multistream Opus decoder. - * It is position independent and can be freely copied. - * @see opus_multistream_decoder_create - * @see opus_multistream_decoder_init - */ -typedef struct OpusMSDecoder OpusMSDecoder; - -/**\name Multistream encoder functions */ -/**@{*/ - -/** Gets the size of an OpusMSEncoder structure. - * @param streams int: The total number of streams to encode from the - * input. - * This must be no more than 255. - * @param coupled_streams int: Number of coupled (2 channel) streams - * to encode. - * This must be no larger than the total - * number of streams. - * Additionally, The total number of - * encoded channels (streams + - * coupled_streams) must be no - * more than 255. - * @returns The size in bytes on success, or a negative error code - * (see @ref opus_errorcodes) on error. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_encoder_get_size( - int streams, - int coupled_streams -); - -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_surround_encoder_get_size( - int channels, - int mapping_family -); - - -/** Allocates and initializes a multistream encoder state. - * Call opus_multistream_encoder_destroy() to release - * this object when finished. - * @param Fs opus_int32: Sampling rate of the input signal (in Hz). - * This must be one of 8000, 12000, 16000, - * 24000, or 48000. - * @param channels int: Number of channels in the input signal. - * This must be at most 255. - * It may be greater than the number of - * coded channels (streams + - * coupled_streams). - * @param streams int: The total number of streams to encode from the - * input. - * This must be no more than the number of channels. - * @param coupled_streams int: Number of coupled (2 channel) streams - * to encode. - * This must be no larger than the total - * number of streams. - * Additionally, The total number of - * encoded channels (streams + - * coupled_streams) must be no - * more than the number of input channels. - * @param[in] mapping const unsigned char[channels]: Mapping from - * encoded channels to input channels, as described in - * @ref opus_multistream. As an extra constraint, the - * multistream encoder does not allow encoding coupled - * streams for which one channel is unused since this - * is never a good idea. - * @param application int: The target encoder application. - * This must be one of the following: - *
- *
#OPUS_APPLICATION_VOIP
- *
Process signal for improved speech intelligibility.
- *
#OPUS_APPLICATION_AUDIO
- *
Favor faithfulness to the original input.
- *
#OPUS_APPLICATION_RESTRICTED_LOWDELAY
- *
Configure the minimum possible coding delay by disabling certain modes - * of operation.
- *
- * @param[out] error int *: Returns #OPUS_OK on success, or an error - * code (see @ref opus_errorcodes) on - * failure. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_encoder_create( - opus_int32 Fs, - int channels, - int streams, - int coupled_streams, - const unsigned char *mapping, - int application, - int *error -) OPUS_ARG_NONNULL(5); - -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_surround_encoder_create( - opus_int32 Fs, - int channels, - int mapping_family, - int *streams, - int *coupled_streams, - unsigned char *mapping, - int application, - int *error -) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6); - -/** Initialize a previously allocated multistream encoder state. - * The memory pointed to by \a st must be at least the size returned by - * opus_multistream_encoder_get_size(). - * This is intended for applications which use their own allocator instead of - * malloc. - * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. - * @see opus_multistream_encoder_create - * @see opus_multistream_encoder_get_size - * @param st OpusMSEncoder*: Multistream encoder state to initialize. - * @param Fs opus_int32: Sampling rate of the input signal (in Hz). - * This must be one of 8000, 12000, 16000, - * 24000, or 48000. - * @param channels int: Number of channels in the input signal. - * This must be at most 255. - * It may be greater than the number of - * coded channels (streams + - * coupled_streams). - * @param streams int: The total number of streams to encode from the - * input. - * This must be no more than the number of channels. - * @param coupled_streams int: Number of coupled (2 channel) streams - * to encode. - * This must be no larger than the total - * number of streams. - * Additionally, The total number of - * encoded channels (streams + - * coupled_streams) must be no - * more than the number of input channels. - * @param[in] mapping const unsigned char[channels]: Mapping from - * encoded channels to input channels, as described in - * @ref opus_multistream. As an extra constraint, the - * multistream encoder does not allow encoding coupled - * streams for which one channel is unused since this - * is never a good idea. - * @param application int: The target encoder application. - * This must be one of the following: - *
- *
#OPUS_APPLICATION_VOIP
- *
Process signal for improved speech intelligibility.
- *
#OPUS_APPLICATION_AUDIO
- *
Favor faithfulness to the original input.
- *
#OPUS_APPLICATION_RESTRICTED_LOWDELAY
- *
Configure the minimum possible coding delay by disabling certain modes - * of operation.
- *
- * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes) - * on failure. - */ -OPUS_EXPORT int opus_multistream_encoder_init( - OpusMSEncoder *st, - opus_int32 Fs, - int channels, - int streams, - int coupled_streams, - const unsigned char *mapping, - int application -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6); - -OPUS_EXPORT int opus_multistream_surround_encoder_init( - OpusMSEncoder *st, - opus_int32 Fs, - int channels, - int mapping_family, - int *streams, - int *coupled_streams, - unsigned char *mapping, - int application -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6) OPUS_ARG_NONNULL(7); - -/** Encodes a multistream Opus frame. - * @param st OpusMSEncoder*: Multistream encoder state. - * @param[in] pcm const opus_int16*: The input signal as interleaved - * samples. - * This must contain - * frame_size*channels - * samples. - * @param frame_size int: Number of samples per channel in the input - * signal. - * This must be an Opus frame size for the - * encoder's sampling rate. - * For example, at 48 kHz the permitted values - * are 120, 240, 480, 960, 1920, and 2880. - * Passing in a duration of less than 10 ms - * (480 samples at 48 kHz) will prevent the - * encoder from using the LPC or hybrid modes. - * @param[out] data unsigned char*: Output payload. - * This must contain storage for at - * least \a max_data_bytes. - * @param [in] max_data_bytes opus_int32: Size of the allocated - * memory for the output - * payload. This may be - * used to impose an upper limit on - * the instant bitrate, but should - * not be used as the only bitrate - * control. Use #OPUS_SET_BITRATE to - * control the bitrate. - * @returns The length of the encoded packet (in bytes) on success or a - * negative error code (see @ref opus_errorcodes) on failure. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode( - OpusMSEncoder *st, - const opus_int16 *pcm, - int frame_size, - unsigned char *data, - opus_int32 max_data_bytes -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); - -/** Encodes a multistream Opus frame from floating point input. - * @param st OpusMSEncoder*: Multistream encoder state. - * @param[in] pcm const float*: The input signal as interleaved - * samples with a normal range of - * +/-1.0. - * Samples with a range beyond +/-1.0 - * are supported but will be clipped by - * decoders using the integer API and - * should only be used if it is known - * that the far end supports extended - * dynamic range. - * This must contain - * frame_size*channels - * samples. - * @param frame_size int: Number of samples per channel in the input - * signal. - * This must be an Opus frame size for the - * encoder's sampling rate. - * For example, at 48 kHz the permitted values - * are 120, 240, 480, 960, 1920, and 2880. - * Passing in a duration of less than 10 ms - * (480 samples at 48 kHz) will prevent the - * encoder from using the LPC or hybrid modes. - * @param[out] data unsigned char*: Output payload. - * This must contain storage for at - * least \a max_data_bytes. - * @param [in] max_data_bytes opus_int32: Size of the allocated - * memory for the output - * payload. This may be - * used to impose an upper limit on - * the instant bitrate, but should - * not be used as the only bitrate - * control. Use #OPUS_SET_BITRATE to - * control the bitrate. - * @returns The length of the encoded packet (in bytes) on success or a - * negative error code (see @ref opus_errorcodes) on failure. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode_float( - OpusMSEncoder *st, - const float *pcm, - int frame_size, - unsigned char *data, - opus_int32 max_data_bytes -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); - -/** Frees an OpusMSEncoder allocated by - * opus_multistream_encoder_create(). - * @param st OpusMSEncoder*: Multistream encoder state to be freed. - */ -OPUS_EXPORT void opus_multistream_encoder_destroy(OpusMSEncoder *st); - -/** Perform a CTL function on a multistream Opus encoder. - * - * Generally the request and subsequent arguments are generated by a - * convenience macro. - * @param st OpusMSEncoder*: Multistream encoder state. - * @param request This and all remaining parameters should be replaced by one - * of the convenience macros in @ref opus_genericctls, - * @ref opus_encoderctls, or @ref opus_multistream_ctls. - * @see opus_genericctls - * @see opus_encoderctls - * @see opus_multistream_ctls - */ -OPUS_EXPORT int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) OPUS_ARG_NONNULL(1); - -/**@}*/ - -/**\name Multistream decoder functions */ -/**@{*/ - -/** Gets the size of an OpusMSDecoder structure. - * @param streams int: The total number of streams coded in the - * input. - * This must be no more than 255. - * @param coupled_streams int: Number streams to decode as coupled - * (2 channel) streams. - * This must be no larger than the total - * number of streams. - * Additionally, The total number of - * coded channels (streams + - * coupled_streams) must be no - * more than 255. - * @returns The size in bytes on success, or a negative error code - * (see @ref opus_errorcodes) on error. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_decoder_get_size( - int streams, - int coupled_streams -); - -/** Allocates and initializes a multistream decoder state. - * Call opus_multistream_decoder_destroy() to release - * this object when finished. - * @param Fs opus_int32: Sampling rate to decode at (in Hz). - * This must be one of 8000, 12000, 16000, - * 24000, or 48000. - * @param channels int: Number of channels to output. - * This must be at most 255. - * It may be different from the number of coded - * channels (streams + - * coupled_streams). - * @param streams int: The total number of streams coded in the - * input. - * This must be no more than 255. - * @param coupled_streams int: Number of streams to decode as coupled - * (2 channel) streams. - * This must be no larger than the total - * number of streams. - * Additionally, The total number of - * coded channels (streams + - * coupled_streams) must be no - * more than 255. - * @param[in] mapping const unsigned char[channels]: Mapping from - * coded channels to output channels, as described in - * @ref opus_multistream. - * @param[out] error int *: Returns #OPUS_OK on success, or an error - * code (see @ref opus_errorcodes) on - * failure. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSDecoder *opus_multistream_decoder_create( - opus_int32 Fs, - int channels, - int streams, - int coupled_streams, - const unsigned char *mapping, - int *error -) OPUS_ARG_NONNULL(5); - -/** Intialize a previously allocated decoder state object. - * The memory pointed to by \a st must be at least the size returned by - * opus_multistream_encoder_get_size(). - * This is intended for applications which use their own allocator instead of - * malloc. - * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. - * @see opus_multistream_decoder_create - * @see opus_multistream_deocder_get_size - * @param st OpusMSEncoder*: Multistream encoder state to initialize. - * @param Fs opus_int32: Sampling rate to decode at (in Hz). - * This must be one of 8000, 12000, 16000, - * 24000, or 48000. - * @param channels int: Number of channels to output. - * This must be at most 255. - * It may be different from the number of coded - * channels (streams + - * coupled_streams). - * @param streams int: The total number of streams coded in the - * input. - * This must be no more than 255. - * @param coupled_streams int: Number of streams to decode as coupled - * (2 channel) streams. - * This must be no larger than the total - * number of streams. - * Additionally, The total number of - * coded channels (streams + - * coupled_streams) must be no - * more than 255. - * @param[in] mapping const unsigned char[channels]: Mapping from - * coded channels to output channels, as described in - * @ref opus_multistream. - * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes) - * on failure. - */ -OPUS_EXPORT int opus_multistream_decoder_init( - OpusMSDecoder *st, - opus_int32 Fs, - int channels, - int streams, - int coupled_streams, - const unsigned char *mapping -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6); - -/** Decode a multistream Opus packet. - * @param st OpusMSDecoder*: Multistream decoder state. - * @param[in] data const unsigned char*: Input payload. - * Use a NULL - * pointer to indicate packet - * loss. - * @param len opus_int32: Number of bytes in payload. - * @param[out] pcm opus_int16*: Output signal, with interleaved - * samples. - * This must contain room for - * frame_size*channels - * samples. - * @param frame_size int: The number of samples per channel of - * available space in \a pcm. - * If this is less than the maximum packet duration - * (120 ms; 5760 for 48kHz), this function will not be capable - * of decoding some packets. In the case of PLC (data==NULL) - * or FEC (decode_fec=1), then frame_size needs to be exactly - * the duration of audio that is missing, otherwise the - * decoder will not be in the optimal state to decode the - * next incoming packet. For the PLC and FEC cases, frame_size - * must be a multiple of 2.5 ms. - * @param decode_fec int: Flag (0 or 1) to request that any in-band - * forward error correction data be decoded. - * If no such data is available, the frame is - * decoded as if it were lost. - * @returns Number of samples decoded on success or a negative error code - * (see @ref opus_errorcodes) on failure. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode( - OpusMSDecoder *st, - const unsigned char *data, - opus_int32 len, - opus_int16 *pcm, - int frame_size, - int decode_fec -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); - -/** Decode a multistream Opus packet with floating point output. - * @param st OpusMSDecoder*: Multistream decoder state. - * @param[in] data const unsigned char*: Input payload. - * Use a NULL - * pointer to indicate packet - * loss. - * @param len opus_int32: Number of bytes in payload. - * @param[out] pcm opus_int16*: Output signal, with interleaved - * samples. - * This must contain room for - * frame_size*channels - * samples. - * @param frame_size int: The number of samples per channel of - * available space in \a pcm. - * If this is less than the maximum packet duration - * (120 ms; 5760 for 48kHz), this function will not be capable - * of decoding some packets. In the case of PLC (data==NULL) - * or FEC (decode_fec=1), then frame_size needs to be exactly - * the duration of audio that is missing, otherwise the - * decoder will not be in the optimal state to decode the - * next incoming packet. For the PLC and FEC cases, frame_size - * must be a multiple of 2.5 ms. - * @param decode_fec int: Flag (0 or 1) to request that any in-band - * forward error correction data be decoded. - * If no such data is available, the frame is - * decoded as if it were lost. - * @returns Number of samples decoded on success or a negative error code - * (see @ref opus_errorcodes) on failure. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode_float( - OpusMSDecoder *st, - const unsigned char *data, - opus_int32 len, - float *pcm, - int frame_size, - int decode_fec -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); - -/** Perform a CTL function on a multistream Opus decoder. - * - * Generally the request and subsequent arguments are generated by a - * convenience macro. - * @param st OpusMSDecoder*: Multistream decoder state. - * @param request This and all remaining parameters should be replaced by one - * of the convenience macros in @ref opus_genericctls, - * @ref opus_decoderctls, or @ref opus_multistream_ctls. - * @see opus_genericctls - * @see opus_decoderctls - * @see opus_multistream_ctls - */ -OPUS_EXPORT int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...) OPUS_ARG_NONNULL(1); - -/** Frees an OpusMSDecoder allocated by - * opus_multistream_decoder_create(). - * @param st OpusMSDecoder: Multistream decoder state to be freed. - */ -OPUS_EXPORT void opus_multistream_decoder_destroy(OpusMSDecoder *st); - -/**@}*/ - -/**@}*/ - -#ifdef __cplusplus -} -#endif - -#endif /* OPUS_MULTISTREAM_H */ diff --git a/library/opusencoder/src/main/cpp/opus/include/opus_projection.h b/library/opusencoder/src/main/cpp/opus/include/opus_projection.h deleted file mode 100644 index 9dabf4e85c..0000000000 --- a/library/opusencoder/src/main/cpp/opus/include/opus_projection.h +++ /dev/null @@ -1,568 +0,0 @@ -/* Copyright (c) 2017 Google Inc. - Written by Andrew Allen */ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/** - * @file opus_projection.h - * @brief Opus projection reference API - */ - -#ifndef OPUS_PROJECTION_H -#define OPUS_PROJECTION_H - -#include "opus_multistream.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** @cond OPUS_INTERNAL_DOC */ - -/** These are the actual encoder and decoder CTL ID numbers. - * They should not be used directly by applications.c - * In general, SETs should be even and GETs should be odd.*/ -/**@{*/ -#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST 6001 -#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST 6003 -#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST 6005 -/**@}*/ - - -/** @endcond */ - -/** @defgroup opus_projection_ctls Projection specific encoder and decoder CTLs - * - * These are convenience macros that are specific to the - * opus_projection_encoder_ctl() and opus_projection_decoder_ctl() - * interface. - * The CTLs from @ref opus_genericctls, @ref opus_encoderctls, - * @ref opus_decoderctls, and @ref opus_multistream_ctls may be applied to a - * projection encoder or decoder as well. - */ -/**@{*/ - -/** Gets the gain (in dB. S7.8-format) of the demixing matrix from the encoder. - * @param[out] x opus_int32 *: Returns the gain (in dB. S7.8-format) - * of the demixing matrix. - * @hideinitializer - */ -#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN(x) OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST, __opus_check_int_ptr(x) - - -/** Gets the size in bytes of the demixing matrix from the encoder. - * @param[out] x opus_int32 *: Returns the size in bytes of the - * demixing matrix. - * @hideinitializer - */ -#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE(x) OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST, __opus_check_int_ptr(x) - - -/** Copies the demixing matrix to the supplied pointer location. - * @param[out] x unsigned char *: Returns the demixing matrix to the - * supplied pointer location. - * @param y opus_int32: The size in bytes of the reserved memory at the - * pointer location. - * @hideinitializer - */ -#define OPUS_PROJECTION_GET_DEMIXING_MATRIX(x,y) OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST, x, __opus_check_int(y) - - -/**@}*/ - -/** Opus projection encoder state. - * This contains the complete state of a projection Opus encoder. - * It is position independent and can be freely copied. - * @see opus_projection_ambisonics_encoder_create - */ -typedef struct OpusProjectionEncoder OpusProjectionEncoder; - - -/** Opus projection decoder state. - * This contains the complete state of a projection Opus decoder. - * It is position independent and can be freely copied. - * @see opus_projection_decoder_create - * @see opus_projection_decoder_init - */ -typedef struct OpusProjectionDecoder OpusProjectionDecoder; - - -/**\name Projection encoder functions */ -/**@{*/ - -/** Gets the size of an OpusProjectionEncoder structure. - * @param channels int: The total number of input channels to encode. - * This must be no more than 255. - * @param mapping_family int: The mapping family to use for selecting - * the appropriate projection. - * @returns The size in bytes on success, or a negative error code - * (see @ref opus_errorcodes) on error. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_projection_ambisonics_encoder_get_size( - int channels, - int mapping_family -); - - -/** Allocates and initializes a projection encoder state. - * Call opus_projection_encoder_destroy() to release - * this object when finished. - * @param Fs opus_int32: Sampling rate of the input signal (in Hz). - * This must be one of 8000, 12000, 16000, - * 24000, or 48000. - * @param channels int: Number of channels in the input signal. - * This must be at most 255. - * It may be greater than the number of - * coded channels (streams + - * coupled_streams). - * @param mapping_family int: The mapping family to use for selecting - * the appropriate projection. - * @param[out] streams int *: The total number of streams that will - * be encoded from the input. - * @param[out] coupled_streams int *: Number of coupled (2 channel) - * streams that will be encoded from the input. - * @param application int: The target encoder application. - * This must be one of the following: - *
- *
#OPUS_APPLICATION_VOIP
- *
Process signal for improved speech intelligibility.
- *
#OPUS_APPLICATION_AUDIO
- *
Favor faithfulness to the original input.
- *
#OPUS_APPLICATION_RESTRICTED_LOWDELAY
- *
Configure the minimum possible coding delay by disabling certain modes - * of operation.
- *
- * @param[out] error int *: Returns #OPUS_OK on success, or an error - * code (see @ref opus_errorcodes) on - * failure. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusProjectionEncoder *opus_projection_ambisonics_encoder_create( - opus_int32 Fs, - int channels, - int mapping_family, - int *streams, - int *coupled_streams, - int application, - int *error -) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5); - - -/** Initialize a previously allocated projection encoder state. - * The memory pointed to by \a st must be at least the size returned by - * opus_projection_ambisonics_encoder_get_size(). - * This is intended for applications which use their own allocator instead of - * malloc. - * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. - * @see opus_projection_ambisonics_encoder_create - * @see opus_projection_ambisonics_encoder_get_size - * @param st OpusProjectionEncoder*: Projection encoder state to initialize. - * @param Fs opus_int32: Sampling rate of the input signal (in Hz). - * This must be one of 8000, 12000, 16000, - * 24000, or 48000. - * @param channels int: Number of channels in the input signal. - * This must be at most 255. - * It may be greater than the number of - * coded channels (streams + - * coupled_streams). - * @param streams int: The total number of streams to encode from the - * input. - * This must be no more than the number of channels. - * @param coupled_streams int: Number of coupled (2 channel) streams - * to encode. - * This must be no larger than the total - * number of streams. - * Additionally, The total number of - * encoded channels (streams + - * coupled_streams) must be no - * more than the number of input channels. - * @param application int: The target encoder application. - * This must be one of the following: - *
- *
#OPUS_APPLICATION_VOIP
- *
Process signal for improved speech intelligibility.
- *
#OPUS_APPLICATION_AUDIO
- *
Favor faithfulness to the original input.
- *
#OPUS_APPLICATION_RESTRICTED_LOWDELAY
- *
Configure the minimum possible coding delay by disabling certain modes - * of operation.
- *
- * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes) - * on failure. - */ -OPUS_EXPORT int opus_projection_ambisonics_encoder_init( - OpusProjectionEncoder *st, - opus_int32 Fs, - int channels, - int mapping_family, - int *streams, - int *coupled_streams, - int application -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6); - - -/** Encodes a projection Opus frame. - * @param st OpusProjectionEncoder*: Projection encoder state. - * @param[in] pcm const opus_int16*: The input signal as interleaved - * samples. - * This must contain - * frame_size*channels - * samples. - * @param frame_size int: Number of samples per channel in the input - * signal. - * This must be an Opus frame size for the - * encoder's sampling rate. - * For example, at 48 kHz the permitted values - * are 120, 240, 480, 960, 1920, and 2880. - * Passing in a duration of less than 10 ms - * (480 samples at 48 kHz) will prevent the - * encoder from using the LPC or hybrid modes. - * @param[out] data unsigned char*: Output payload. - * This must contain storage for at - * least \a max_data_bytes. - * @param [in] max_data_bytes opus_int32: Size of the allocated - * memory for the output - * payload. This may be - * used to impose an upper limit on - * the instant bitrate, but should - * not be used as the only bitrate - * control. Use #OPUS_SET_BITRATE to - * control the bitrate. - * @returns The length of the encoded packet (in bytes) on success or a - * negative error code (see @ref opus_errorcodes) on failure. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode( - OpusProjectionEncoder *st, - const opus_int16 *pcm, - int frame_size, - unsigned char *data, - opus_int32 max_data_bytes -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); - - -/** Encodes a projection Opus frame from floating point input. - * @param st OpusProjectionEncoder*: Projection encoder state. - * @param[in] pcm const float*: The input signal as interleaved - * samples with a normal range of - * +/-1.0. - * Samples with a range beyond +/-1.0 - * are supported but will be clipped by - * decoders using the integer API and - * should only be used if it is known - * that the far end supports extended - * dynamic range. - * This must contain - * frame_size*channels - * samples. - * @param frame_size int: Number of samples per channel in the input - * signal. - * This must be an Opus frame size for the - * encoder's sampling rate. - * For example, at 48 kHz the permitted values - * are 120, 240, 480, 960, 1920, and 2880. - * Passing in a duration of less than 10 ms - * (480 samples at 48 kHz) will prevent the - * encoder from using the LPC or hybrid modes. - * @param[out] data unsigned char*: Output payload. - * This must contain storage for at - * least \a max_data_bytes. - * @param [in] max_data_bytes opus_int32: Size of the allocated - * memory for the output - * payload. This may be - * used to impose an upper limit on - * the instant bitrate, but should - * not be used as the only bitrate - * control. Use #OPUS_SET_BITRATE to - * control the bitrate. - * @returns The length of the encoded packet (in bytes) on success or a - * negative error code (see @ref opus_errorcodes) on failure. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode_float( - OpusProjectionEncoder *st, - const float *pcm, - int frame_size, - unsigned char *data, - opus_int32 max_data_bytes -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); - - -/** Frees an OpusProjectionEncoder allocated by - * opus_projection_ambisonics_encoder_create(). - * @param st OpusProjectionEncoder*: Projection encoder state to be freed. - */ -OPUS_EXPORT void opus_projection_encoder_destroy(OpusProjectionEncoder *st); - - -/** Perform a CTL function on a projection Opus encoder. - * - * Generally the request and subsequent arguments are generated by a - * convenience macro. - * @param st OpusProjectionEncoder*: Projection encoder state. - * @param request This and all remaining parameters should be replaced by one - * of the convenience macros in @ref opus_genericctls, - * @ref opus_encoderctls, @ref opus_multistream_ctls, or - * @ref opus_projection_ctls - * @see opus_genericctls - * @see opus_encoderctls - * @see opus_multistream_ctls - * @see opus_projection_ctls - */ -OPUS_EXPORT int opus_projection_encoder_ctl(OpusProjectionEncoder *st, int request, ...) OPUS_ARG_NONNULL(1); - - -/**@}*/ - -/**\name Projection decoder functions */ -/**@{*/ - -/** Gets the size of an OpusProjectionDecoder structure. - * @param channels int: The total number of output channels. - * This must be no more than 255. - * @param streams int: The total number of streams coded in the - * input. - * This must be no more than 255. - * @param coupled_streams int: Number streams to decode as coupled - * (2 channel) streams. - * This must be no larger than the total - * number of streams. - * Additionally, The total number of - * coded channels (streams + - * coupled_streams) must be no - * more than 255. - * @returns The size in bytes on success, or a negative error code - * (see @ref opus_errorcodes) on error. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_projection_decoder_get_size( - int channels, - int streams, - int coupled_streams -); - - -/** Allocates and initializes a projection decoder state. - * Call opus_projection_decoder_destroy() to release - * this object when finished. - * @param Fs opus_int32: Sampling rate to decode at (in Hz). - * This must be one of 8000, 12000, 16000, - * 24000, or 48000. - * @param channels int: Number of channels to output. - * This must be at most 255. - * It may be different from the number of coded - * channels (streams + - * coupled_streams). - * @param streams int: The total number of streams coded in the - * input. - * This must be no more than 255. - * @param coupled_streams int: Number of streams to decode as coupled - * (2 channel) streams. - * This must be no larger than the total - * number of streams. - * Additionally, The total number of - * coded channels (streams + - * coupled_streams) must be no - * more than 255. - * @param[in] demixing_matrix const unsigned char[demixing_matrix_size]: Demixing matrix - * that mapping from coded channels to output channels, - * as described in @ref opus_projection and - * @ref opus_projection_ctls. - * @param demixing_matrix_size opus_int32: The size in bytes of the - * demixing matrix, as - * described in @ref - * opus_projection_ctls. - * @param[out] error int *: Returns #OPUS_OK on success, or an error - * code (see @ref opus_errorcodes) on - * failure. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusProjectionDecoder *opus_projection_decoder_create( - opus_int32 Fs, - int channels, - int streams, - int coupled_streams, - unsigned char *demixing_matrix, - opus_int32 demixing_matrix_size, - int *error -) OPUS_ARG_NONNULL(5); - - -/** Intialize a previously allocated projection decoder state object. - * The memory pointed to by \a st must be at least the size returned by - * opus_projection_decoder_get_size(). - * This is intended for applications which use their own allocator instead of - * malloc. - * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. - * @see opus_projection_decoder_create - * @see opus_projection_deocder_get_size - * @param st OpusProjectionDecoder*: Projection encoder state to initialize. - * @param Fs opus_int32: Sampling rate to decode at (in Hz). - * This must be one of 8000, 12000, 16000, - * 24000, or 48000. - * @param channels int: Number of channels to output. - * This must be at most 255. - * It may be different from the number of coded - * channels (streams + - * coupled_streams). - * @param streams int: The total number of streams coded in the - * input. - * This must be no more than 255. - * @param coupled_streams int: Number of streams to decode as coupled - * (2 channel) streams. - * This must be no larger than the total - * number of streams. - * Additionally, The total number of - * coded channels (streams + - * coupled_streams) must be no - * more than 255. - * @param[in] demixing_matrix const unsigned char[demixing_matrix_size]: Demixing matrix - * that mapping from coded channels to output channels, - * as described in @ref opus_projection and - * @ref opus_projection_ctls. - * @param demixing_matrix_size opus_int32: The size in bytes of the - * demixing matrix, as - * described in @ref - * opus_projection_ctls. - * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes) - * on failure. - */ -OPUS_EXPORT int opus_projection_decoder_init( - OpusProjectionDecoder *st, - opus_int32 Fs, - int channels, - int streams, - int coupled_streams, - unsigned char *demixing_matrix, - opus_int32 demixing_matrix_size -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6); - - -/** Decode a projection Opus packet. - * @param st OpusProjectionDecoder*: Projection decoder state. - * @param[in] data const unsigned char*: Input payload. - * Use a NULL - * pointer to indicate packet - * loss. - * @param len opus_int32: Number of bytes in payload. - * @param[out] pcm opus_int16*: Output signal, with interleaved - * samples. - * This must contain room for - * frame_size*channels - * samples. - * @param frame_size int: The number of samples per channel of - * available space in \a pcm. - * If this is less than the maximum packet duration - * (120 ms; 5760 for 48kHz), this function will not be capable - * of decoding some packets. In the case of PLC (data==NULL) - * or FEC (decode_fec=1), then frame_size needs to be exactly - * the duration of audio that is missing, otherwise the - * decoder will not be in the optimal state to decode the - * next incoming packet. For the PLC and FEC cases, frame_size - * must be a multiple of 2.5 ms. - * @param decode_fec int: Flag (0 or 1) to request that any in-band - * forward error correction data be decoded. - * If no such data is available, the frame is - * decoded as if it were lost. - * @returns Number of samples decoded on success or a negative error code - * (see @ref opus_errorcodes) on failure. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode( - OpusProjectionDecoder *st, - const unsigned char *data, - opus_int32 len, - opus_int16 *pcm, - int frame_size, - int decode_fec -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); - - -/** Decode a projection Opus packet with floating point output. - * @param st OpusProjectionDecoder*: Projection decoder state. - * @param[in] data const unsigned char*: Input payload. - * Use a NULL - * pointer to indicate packet - * loss. - * @param len opus_int32: Number of bytes in payload. - * @param[out] pcm opus_int16*: Output signal, with interleaved - * samples. - * This must contain room for - * frame_size*channels - * samples. - * @param frame_size int: The number of samples per channel of - * available space in \a pcm. - * If this is less than the maximum packet duration - * (120 ms; 5760 for 48kHz), this function will not be capable - * of decoding some packets. In the case of PLC (data==NULL) - * or FEC (decode_fec=1), then frame_size needs to be exactly - * the duration of audio that is missing, otherwise the - * decoder will not be in the optimal state to decode the - * next incoming packet. For the PLC and FEC cases, frame_size - * must be a multiple of 2.5 ms. - * @param decode_fec int: Flag (0 or 1) to request that any in-band - * forward error correction data be decoded. - * If no such data is available, the frame is - * decoded as if it were lost. - * @returns Number of samples decoded on success or a negative error code - * (see @ref opus_errorcodes) on failure. - */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode_float( - OpusProjectionDecoder *st, - const unsigned char *data, - opus_int32 len, - float *pcm, - int frame_size, - int decode_fec -) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); - - -/** Perform a CTL function on a projection Opus decoder. - * - * Generally the request and subsequent arguments are generated by a - * convenience macro. - * @param st OpusProjectionDecoder*: Projection decoder state. - * @param request This and all remaining parameters should be replaced by one - * of the convenience macros in @ref opus_genericctls, - * @ref opus_decoderctls, @ref opus_multistream_ctls, or - * @ref opus_projection_ctls. - * @see opus_genericctls - * @see opus_decoderctls - * @see opus_multistream_ctls - * @see opus_projection_ctls - */ -OPUS_EXPORT int opus_projection_decoder_ctl(OpusProjectionDecoder *st, int request, ...) OPUS_ARG_NONNULL(1); - - -/** Frees an OpusProjectionDecoder allocated by - * opus_projection_decoder_create(). - * @param st OpusProjectionDecoder: Projection decoder state to be freed. - */ -OPUS_EXPORT void opus_projection_decoder_destroy(OpusProjectionDecoder *st); - - -/**@}*/ - -/**@}*/ - -#ifdef __cplusplus -} -#endif - -#endif /* OPUS_PROJECTION_H */ diff --git a/library/opusencoder/src/main/cpp/opus/include/opus_types.h b/library/opusencoder/src/main/cpp/opus/include/opus_types.h deleted file mode 100644 index 7cf675580f..0000000000 --- a/library/opusencoder/src/main/cpp/opus/include/opus_types.h +++ /dev/null @@ -1,166 +0,0 @@ -/* (C) COPYRIGHT 1994-2002 Xiph.Org Foundation */ -/* Modified by Jean-Marc Valin */ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -/* opus_types.h based on ogg_types.h from libogg */ - -/** - @file opus_types.h - @brief Opus reference implementation types -*/ -#ifndef OPUS_TYPES_H -#define OPUS_TYPES_H - -#define opus_int int /* used for counters etc; at least 16 bits */ -#define opus_int64 long long -#define opus_int8 signed char - -#define opus_uint unsigned int /* used for counters etc; at least 16 bits */ -#define opus_uint64 unsigned long long -#define opus_uint8 unsigned char - -/* Use the real stdint.h if it's there (taken from Paul Hsieh's pstdint.h) */ -#if (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H)) -#include -# undef opus_int64 -# undef opus_int8 -# undef opus_uint64 -# undef opus_uint8 - typedef int8_t opus_int8; - typedef uint8_t opus_uint8; - typedef int16_t opus_int16; - typedef uint16_t opus_uint16; - typedef int32_t opus_int32; - typedef uint32_t opus_uint32; - typedef int64_t opus_int64; - typedef uint64_t opus_uint64; -#elif defined(_WIN32) - -# if defined(__CYGWIN__) -# include <_G_config.h> - typedef _G_int32_t opus_int32; - typedef _G_uint32_t opus_uint32; - typedef _G_int16 opus_int16; - typedef _G_uint16 opus_uint16; -# elif defined(__MINGW32__) - typedef short opus_int16; - typedef unsigned short opus_uint16; - typedef int opus_int32; - typedef unsigned int opus_uint32; -# elif defined(__MWERKS__) - typedef int opus_int32; - typedef unsigned int opus_uint32; - typedef short opus_int16; - typedef unsigned short opus_uint16; -# else - /* MSVC/Borland */ - typedef __int32 opus_int32; - typedef unsigned __int32 opus_uint32; - typedef __int16 opus_int16; - typedef unsigned __int16 opus_uint16; -# endif - -#elif defined(__MACOS__) - -# include - typedef SInt16 opus_int16; - typedef UInt16 opus_uint16; - typedef SInt32 opus_int32; - typedef UInt32 opus_uint32; - -#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */ - -# include - typedef int16_t opus_int16; - typedef u_int16_t opus_uint16; - typedef int32_t opus_int32; - typedef u_int32_t opus_uint32; - -#elif defined(__BEOS__) - - /* Be */ -# include - typedef int16 opus_int16; - typedef u_int16 opus_uint16; - typedef int32_t opus_int32; - typedef u_int32_t opus_uint32; - -#elif defined (__EMX__) - - /* OS/2 GCC */ - typedef short opus_int16; - typedef unsigned short opus_uint16; - typedef int opus_int32; - typedef unsigned int opus_uint32; - -#elif defined (DJGPP) - - /* DJGPP */ - typedef short opus_int16; - typedef unsigned short opus_uint16; - typedef int opus_int32; - typedef unsigned int opus_uint32; - -#elif defined(R5900) - - /* PS2 EE */ - typedef int opus_int32; - typedef unsigned opus_uint32; - typedef short opus_int16; - typedef unsigned short opus_uint16; - -#elif defined(__SYMBIAN32__) - - /* Symbian GCC */ - typedef signed short opus_int16; - typedef unsigned short opus_uint16; - typedef signed int opus_int32; - typedef unsigned int opus_uint32; - -#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X) - - typedef short opus_int16; - typedef unsigned short opus_uint16; - typedef long opus_int32; - typedef unsigned long opus_uint32; - -#elif defined(CONFIG_TI_C6X) - - typedef short opus_int16; - typedef unsigned short opus_uint16; - typedef int opus_int32; - typedef unsigned int opus_uint32; - -#else - - /* Give up, take a reasonable guess */ - typedef short opus_int16; - typedef unsigned short opus_uint16; - typedef int opus_int32; - typedef unsigned int opus_uint32; - -#endif - -#endif /* OPUS_TYPES_H */ diff --git a/library/opusencoder/src/main/cpp/opus/include/opusenc.h b/library/opusencoder/src/main/cpp/opus/include/opusenc.h deleted file mode 100644 index ca1a5efe8e..0000000000 --- a/library/opusencoder/src/main/cpp/opus/include/opusenc.h +++ /dev/null @@ -1,358 +0,0 @@ -/* Copyright (c) 2017 Jean-Marc Valin */ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#if !defined(_opusenc_h) -# define _opusenc_h (1) - -/**\mainpage - \section Introduction - - This is the documentation for the libopusenc C API. - - The libopusenc package provides a convenient high-level API for - encoding Ogg Opus files. - - \section Organization - - The main API is divided into several sections: - - \ref encoding - - \ref comments - - \ref encoder_ctl - - \ref callbacks - - \ref error_codes - - \section Overview - - The libopusfile API provides an easy way to encode Ogg Opus files using - libopus. -*/ - -# if defined(__cplusplus) -extern "C" { -# endif - -#include - -#ifndef OPE_EXPORT -# if defined(WIN32) -# if defined(OPE_BUILD) && defined(DLL_EXPORT) -# define OPE_EXPORT __declspec(dllexport) -# else -# define OPE_EXPORT -# endif -# elif defined(__GNUC__) && defined(OPE_BUILD) -# define OPE_EXPORT __attribute__ ((visibility ("default"))) -# else -# define OPE_EXPORT -# endif -#endif - -/**\defgroup error_codes Error Codes*/ -/*@{*/ -/**\name List of possible error codes - Many of the functions in this library return a negative error code when a - function fails. - This list provides a brief explanation of the common errors. - See each individual function for more details on what a specific error code - means in that context.*/ -/*@{*/ - - -/* Bump this when we change the API. */ -/** API version for this header. Can be used to check for features at compile time. */ -#define OPE_API_VERSION 0 - -#define OPE_OK 0 -/* Based on the relevant libopus code minus 10. */ -#define OPE_BAD_ARG -11 -#define OPE_INTERNAL_ERROR -13 -#define OPE_UNIMPLEMENTED -15 -#define OPE_ALLOC_FAIL -17 - -/* Specific to libopusenc. */ -#define OPE_CANNOT_OPEN -30 -#define OPE_TOO_LATE -31 -#define OPE_UNRECOVERABLE -32 -#define OPE_INVALID_PICTURE -33 -#define OPE_INVALID_ICON -34 -/*@}*/ -/*@}*/ - - -/* These are the "raw" request values -- they should usually not be used. */ -#define OPE_SET_DECISION_DELAY_REQUEST 14000 -#define OPE_GET_DECISION_DELAY_REQUEST 14001 -#define OPE_SET_MUXING_DELAY_REQUEST 14002 -#define OPE_GET_MUXING_DELAY_REQUEST 14003 -#define OPE_SET_COMMENT_PADDING_REQUEST 14004 -#define OPE_GET_COMMENT_PADDING_REQUEST 14005 -#define OPE_SET_SERIALNO_REQUEST 14006 -#define OPE_GET_SERIALNO_REQUEST 14007 -#define OPE_SET_PACKET_CALLBACK_REQUEST 14008 -/*#define OPE_GET_PACKET_CALLBACK_REQUEST 14009*/ -#define OPE_SET_HEADER_GAIN_REQUEST 14010 -#define OPE_GET_HEADER_GAIN_REQUEST 14011 - -/**\defgroup encoder_ctl Encoding Options*/ -/*@{*/ - -/**\name Control parameters - - Macros for setting encoder options.*/ -/*@{*/ - -#define OPE_SET_DECISION_DELAY(x) OPE_SET_DECISION_DELAY_REQUEST, __opus_check_int(x) -#define OPE_GET_DECISION_DELAY(x) OPE_GET_DECISION_DELAY_REQUEST, __opus_check_int_ptr(x) -#define OPE_SET_MUXING_DELAY(x) OPE_SET_MUXING_DELAY_REQUEST, __opus_check_int(x) -#define OPE_GET_MUXING_DELAY(x) OPE_GET_MUXING_DELAY_REQUEST, __opus_check_int_ptr(x) -#define OPE_SET_COMMENT_PADDING(x) OPE_SET_COMMENT_PADDING_REQUEST, __opus_check_int(x) -#define OPE_GET_COMMENT_PADDING(x) OPE_GET_COMMENT_PADDING_REQUEST, __opus_check_int_ptr(x) -#define OPE_SET_SERIALNO(x) OPE_SET_SERIALNO_REQUEST, __opus_check_int(x) -#define OPE_GET_SERIALNO(x) OPE_GET_SERIALNO_REQUEST, __opus_check_int_ptr(x) -/* FIXME: Add type-checking macros to these. */ -#define OPE_SET_PACKET_CALLBACK(x,u) OPE_SET_PACKET_CALLBACK_REQUEST, (x), (u) -/*#define OPE_GET_PACKET_CALLBACK(x,u) OPE_GET_PACKET_CALLBACK_REQUEST, (x), (u)*/ -#define OPE_SET_HEADER_GAIN(x,u) OPE_SET_HEADER_GAIN_REQUEST, __opus_check_int(x) -#define OPE_GET_HEADER_GAIN(x,u) OPE_GET_HEADER_GAIN_REQUEST, __opus_check_int_ptr(x) -/*@}*/ -/*@}*/ - -/**\defgroup callbacks Callback Functions */ -/*@{*/ - -/**\name Callback functions - - These are the callbacks that can be implemented for an encoder.*/ -/*@{*/ - -/** Called for writing a page. */ -typedef int (*ope_write_func)(void *user_data, const unsigned char *ptr, opus_int32 len); - -/** Called for closing a stream. */ -typedef int (*ope_close_func)(void *user_data); - -/** Called on every packet encoded (including header). */ -typedef int (*ope_packet_func)(void *user_data, const unsigned char *packet_ptr, opus_int32 packet_len, opus_uint32 flags); - -/** Callback functions for accessing the stream. */ -typedef struct { - /** Callback for writing to the stream. */ - ope_write_func write; - /** Callback for closing the stream. */ - ope_close_func close; -} OpusEncCallbacks; -/*@}*/ -/*@}*/ - -/** Opaque comments struct. */ -typedef struct OggOpusComments OggOpusComments; - -/** Opaque encoder struct. */ -typedef struct OggOpusEnc OggOpusEnc; - -/**\defgroup comments Comments Handling */ -/*@{*/ - -/**\name Functions for handling comments - - These functions make it possible to add comments and pictures to Ogg Opus files.*/ -/*@{*/ - -/** Create a new comments object. - \return Newly-created comments object. */ -OPE_EXPORT OggOpusComments *ope_comments_create(void); - -/** Create a deep copy of a comments object. - \param comments Comments object to copy - \return Deep copy of input. */ -OPE_EXPORT OggOpusComments *ope_comments_copy(OggOpusComments *comments); - -/** Destroys a comments object. - \param comments Comments object to destroy*/ -OPE_EXPORT void ope_comments_destroy(OggOpusComments *comments); - -/** Add a comment. - \param[in,out] comments Where to add the comments - \param tag Tag for the comment (must not contain = char) - \param val Value for the tag - \return Error code - */ -OPE_EXPORT int ope_comments_add(OggOpusComments *comments, const char *tag, const char *val); - -/** Add a comment as a single tag=value string. - \param[in,out] comments Where to add the comments - \param tag_and_val string of the form tag=value (must contain = char) - \return Error code - */ -OPE_EXPORT int ope_comments_add_string(OggOpusComments *comments, const char *tag_and_val); - -/** Add a picture. - \param[in,out] comments Where to add the comments - \param filename File name for the picture - \param picture_type Type of picture (-1 for default) - \param description Description (NULL means no comment) - \return Error code - */ -OPE_EXPORT int ope_comments_add_picture(OggOpusComments *comments, const char *filename, int picture_type, const char *description); - -/*@}*/ -/*@}*/ - -/**\defgroup encoding Encoding */ -/*@{*/ - -/**\name Functions for encoding Ogg Opus files - - These functions make it possible to encode Ogg Opus files.*/ -/*@{*/ - -/** Create a new OggOpus file. - \param path Path where to create the file - \param comments Comments associated with the stream - \param rate Input sampling rate (48 kHz is faster) - \param channels Number of channels - \param family Mapping family (0 for mono/stereo, 1 for surround) - \param[out] error Error code (NULL if no error is to be returned) - \return Newly-created encoder. - */ -OPE_EXPORT OggOpusEnc *ope_encoder_create_file(const char *path, OggOpusComments *comments, opus_int32 rate, int channels, int family, int *error); - -/** Create a new OggOpus stream to be handled using callbacks - \param callbacks Callback functions - \param user_data Pointer to be associated with the stream and passed to the callbacks - \param comments Comments associated with the stream - \param rate Input sampling rate (48 kHz is faster) - \param channels Number of channels - \param family Mapping family (0 for mono/stereo, 1 for surround) - \param[out] error Error code (NULL if no error is to be returned) - \return Newly-created encoder. - */ -OPE_EXPORT OggOpusEnc *ope_encoder_create_callbacks(const OpusEncCallbacks *callbacks, void *user_data, - OggOpusComments *comments, opus_int32 rate, int channels, int family, int *error); - -/** Create a new OggOpus stream to be used along with.ope_encoder_get_page(). - This is mostly useful for muxing with other streams. - \param comments Comments associated with the stream - \param rate Input sampling rate (48 kHz is faster) - \param channels Number of channels - \param family Mapping family (0 for mono/stereo, 1 for surround) - \param[out] error Error code (NULL if no error is to be returned) - \return Newly-created encoder. - */ -OPE_EXPORT OggOpusEnc *ope_encoder_create_pull(OggOpusComments *comments, opus_int32 rate, int channels, int family, int *error); - -/** Add/encode any number of float samples to the stream. - \param[in,out] enc Encoder - \param pcm Floating-point PCM values in the +/-1 range (interleaved if multiple channels) - \param samples_per_channel Number of samples for each channel - \return Error code*/ -OPE_EXPORT int ope_encoder_write_float(OggOpusEnc *enc, const float *pcm, int samples_per_channel); - -/** Add/encode any number of 16-bit linear samples to the stream. - \param[in,out] enc Encoder - \param pcm Linear 16-bit PCM values in the [-32768,32767] range (interleaved if multiple channels) - \param samples_per_channel Number of samples for each channel - \return Error code*/ -OPE_EXPORT int ope_encoder_write(OggOpusEnc *enc, const opus_int16 *pcm, int samples_per_channel); - -/** Get the next page from the stream (only if using ope_encoder_create_pull()). - \param[in,out] enc Encoder - \param[out] page Next available encoded page - \param[out] len Size (in bytes) of the page returned - \param flush If non-zero, forces a flush of the page (if any data avaiable) - \return 1 if there is a page available, 0 if not. */ -OPE_EXPORT int ope_encoder_get_page(OggOpusEnc *enc, unsigned char **page, opus_int32 *len, int flush); - -/** Finalizes the stream, but does not deallocate the object. - \param[in,out] enc Encoder - \return Error code - */ -OPE_EXPORT int ope_encoder_drain(OggOpusEnc *enc); - -/** Deallocates the obect. Make sure to ope_drain() first. - \param[in,out] enc Encoder - */ -OPE_EXPORT void ope_encoder_destroy(OggOpusEnc *enc); - -/** Ends the stream and create a new stream within the same file. - \param[in,out] enc Encoder - \param comments Comments associated with the stream - \return Error code - */ -OPE_EXPORT int ope_encoder_chain_current(OggOpusEnc *enc, OggOpusComments *comments); - -/** Ends the stream and create a new file. - \param[in,out] enc Encoder - \param path Path where to write the new file - \param comments Comments associated with the stream - \return Error code - */ -OPE_EXPORT int ope_encoder_continue_new_file(OggOpusEnc *enc, const char *path, OggOpusComments *comments); - -/** Ends the stream and create a new file (callback-based). - \param[in,out] enc Encoder - \param user_data Pointer to be associated with the new stream and passed to the callbacks - \param comments Comments associated with the stream - \return Error code - */ -OPE_EXPORT int ope_encoder_continue_new_callbacks(OggOpusEnc *enc, void *user_data, OggOpusComments *comments); - -/** Write out the header now rather than wait for audio to begin. - \param[in,out] enc Encoder - \return Error code - */ -OPE_EXPORT int ope_encoder_flush_header(OggOpusEnc *enc); - -/** Sets encoder options. - \param[in,out] enc Encoder - \param request Use a request macro - \return Error code - */ -OPE_EXPORT int ope_encoder_ctl(OggOpusEnc *enc, int request, ...); - -/** Converts a libopusenc error code into a human readable string. - * - * @param error Error number - * @returns Error string - */ -OPE_EXPORT const char *ope_strerror(int error); - -/** Returns a string representing the version of libopusenc being used at run time. - \return A string describing the version of this library */ -OPE_EXPORT const char *ope_get_version_string(void); - -/** ABI version for this header. Can be used to check for features at run time. - \return An integer representing the ABI version */ -OPE_EXPORT int ope_get_abi_version(void); - -/*@}*/ -/*@}*/ - -# if defined(__cplusplus) -} -# endif - -#endif diff --git a/library/opusencoder/src/main/cpp/opus/libs/arm64-v8a/libopus.so b/library/opusencoder/src/main/cpp/opus/libs/arm64-v8a/libopus.so deleted file mode 100755 index 466c1df13ae33ebef9ba62a6f7caf35ec62ef771..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 318136 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%0DRz)#>N;9HsvNau*pRwiUKn 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 diff --git a/library/opusencoder/src/main/cpp/opus/libs/arm64-v8a/libopusenc.so b/library/opusencoder/src/main/cpp/opus/libs/arm64-v8a/libopusenc.so deleted file mode 100755 index 9389efd9199c23332edceacd1ca5528f90d528b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49448 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

-LJ5Va)V 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⪻%S0-`bbE;@{wG(w`U>G$*5(nw;)0 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

@r5{|A)5CtC0dDwtXwqF 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 Ld<5Vb@%O(0r{|su diff --git a/library/opusencoder/src/main/cpp/opus/libs/armeabi-v7a/libopusenc.so b/library/opusencoder/src/main/cpp/opus/libs/armeabi-v7a/libopusenc.so deleted file mode 100755 index 655f296d90a6d8da70387bdefbf54ece5aa13688..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39836 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 diff --git a/library/opusencoder/src/main/cpp/opus/libs/x86/libopus.so b/library/opusencoder/src/main/cpp/opus/libs/x86/libopus.so deleted file mode 100755 index 0acf14474b50e79f44bacedc092575ac3ea9fa15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 329156 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�NQ7PcEW=8M1l6t1_o|Jd$9u*qXwn^quPga3>yNy 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%0AX|AgYSm@Y1KjZR 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 diff --git a/library/opusencoder/src/main/cpp/opus/libs/x86/libopusenc.so b/library/opusencoder/src/main/cpp/opus/libs/x86/libopusenc.so deleted file mode 100755 index f862ea15f7f6062346f562f2794e1ca798e89eb0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56796 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 diff --git a/library/opusencoder/src/main/cpp/opus/libs/x86_64/libopus.so b/library/opusencoder/src/main/cpp/opus/libs/x86_64/libopus.so deleted file mode 100755 index 1480c8c586fab9df0bf3baebfa7454029531f978..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 346688 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%0D}yAbuigF??pM;n^e3ExCU`O70chpTqs+ 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 jE~IrMlX5jYs3~dPNORvB%f3UwiMHrZGDV@R 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 diff --git a/library/opusencoder/src/main/cpp/opuscodec.cpp b/library/opusencoder/src/main/cpp/opuscodec.cpp deleted file mode 100644 index 51bd656c5d..0000000000 --- a/library/opusencoder/src/main/cpp/opuscodec.cpp +++ /dev/null @@ -1,42 +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. - */ - -#include -#include "codec/CodecOggOpus.h" - -CodecOggOpus oggCodec; - -extern "C" -JNIEXPORT jint JNICALL Java_im_vector_opusencoder_OggOpusEncoder_init(JNIEnv *env, jobject thiz, jstring file_path, jint sample_rate) { - char *path = (char*) env->GetStringUTFChars(file_path, 0); - return oggCodec.encoderInit(path, sample_rate); -} - -extern "C" -JNIEXPORT jint JNICALL Java_im_vector_opusencoder_OggOpusEncoder_writeFrame(JNIEnv *env, jobject thiz, jshortArray shorts, jint samples_per_channel) { - jshort *nativeShorts = env->GetShortArrayElements(shorts, 0); - return oggCodec.writeFrame((short *) nativeShorts, samples_per_channel); -} - -extern "C" -JNIEXPORT jint JNICALL Java_im_vector_opusencoder_OggOpusEncoder_setBitrate(JNIEnv *env, jobject thiz, jint bitrate) { - return oggCodec.setBitrate(bitrate); -} - -extern "C" -JNIEXPORT void JNICALL Java_im_vector_opusencoder_OggOpusEncoder_encoderRelease(JNIEnv *env, jobject thiz) { - oggCodec.encoderRelease(); -} diff --git a/library/opusencoder/src/main/cpp/utils/Logger.h b/library/opusencoder/src/main/cpp/utils/Logger.h deleted file mode 100644 index 9efdc51d41..0000000000 --- a/library/opusencoder/src/main/cpp/utils/Logger.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef ANDROIDOPUSENCODER_LOGGER_H -#define ANDROIDOPUSENCODER_LOGGER_H -#include - - -#define LOGE(tag, ...) __android_log_print(ANDROID_LOG_ERROR, tag, __VA_ARGS__) -#define LOGW(tag, ...) __android_log_print(ANDROID_LOG_WARN, tag, __VA_ARGS__) -#define LOGI(tag, ...) __android_log_print(ANDROID_LOG_INFO, tag, __VA_ARGS__) -#define LOGD(tag, ...) __android_log_print(ANDROID_LOG_DEBUG, tag, __VA_ARGS__) - -#endif //ANDROIDOPUSENCODER_LOGGER_H diff --git a/library/opusencoder/src/main/java/im/vector/opusencoder/OggOpusEncoder.kt b/library/opusencoder/src/main/java/im/vector/opusencoder/OggOpusEncoder.kt deleted file mode 100644 index 8af11f8516..0000000000 --- a/library/opusencoder/src/main/java/im/vector/opusencoder/OggOpusEncoder.kt +++ /dev/null @@ -1,57 +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.opusencoder - -import android.util.Log -import androidx.annotation.IntRange -import im.vector.opusencoder.configuration.SampleRate - -/** - * JNI bridge to CodecOggOpus in the native opuscodec library. - */ -class OggOpusEncoder { - - companion object { - - private const val TAG = "OggOpusEncoder" - - init { - try { - System.loadLibrary("opuscodec") - } catch (e: Exception) { - Log.e(TAG, "Couldn't load opus library: $e") - } - } - } - - fun init(filePath: String, sampleRate: SampleRate): Int { - return init(filePath, sampleRate.value) - } - private external fun init(filePath: String, sampleRate: Int): Int - - external fun setBitrate(@IntRange(from = 500, to = 512000) bitrate: Int): Int - - fun encode(shorts: ShortArray, samplesPerChannel: Int): Int { - return writeFrame(shorts, samplesPerChannel) - } - private external fun writeFrame(shorts: ShortArray, samplesPerChannel: Int): Int - - fun release() { - encoderRelease() - } - private external fun encoderRelease() -} diff --git a/library/opusencoder/src/main/java/im/vector/opusencoder/configuration/SampleRate.kt b/library/opusencoder/src/main/java/im/vector/opusencoder/configuration/SampleRate.kt deleted file mode 100644 index e1a8f10725..0000000000 --- a/library/opusencoder/src/main/java/im/vector/opusencoder/configuration/SampleRate.kt +++ /dev/null @@ -1,28 +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.opusencoder.configuration - -/** - * Sampling rate of the input signal in Hz. - */ -sealed class SampleRate private constructor(val value: Int) { - object Rate8khz : SampleRate(8000) - object Rate12kHz : SampleRate(12000) - object Rate16kHz : SampleRate(16000) - object Rate24KHz : SampleRate(24000) - object Rate48kHz : SampleRate(48000) -} diff --git a/settings.gradle b/settings.gradle index 0f537ed48a..782d2caf4a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,4 +8,3 @@ include ':library:attachment-viewer' include ':library:diff-match-patch' include ':library:multipicker' include ':matrix-sdk-android-flow' -include ':library:opusencoder' diff --git a/vector/build.gradle b/vector/build.gradle index dd160f9574..3ca843309b 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -342,8 +342,6 @@ android { } dependencies { - implementation project(':library:opusencoder') - implementation project(":vector-config") implementation project(":matrix-sdk-android") implementation project(":matrix-sdk-android-flow") @@ -381,6 +379,8 @@ dependencies { implementation libs.androidx.datastorepreferences + // Opus Encoder + implementation libs.element.opusencoder // Log implementation libs.jakewharton.timber diff --git a/vector/src/main/java/im/vector/app/features/voice/VoiceRecorderL.kt b/vector/src/main/java/im/vector/app/features/voice/VoiceRecorderL.kt index f0eed41637..c8eeb45635 100644 --- a/vector/src/main/java/im/vector/app/features/voice/VoiceRecorderL.kt +++ b/vector/src/main/java/im/vector/app/features/voice/VoiceRecorderL.kt @@ -23,8 +23,8 @@ import android.media.MediaRecorder import android.media.audiofx.AutomaticGainControl import android.media.audiofx.NoiseSuppressor import android.os.Build -import im.vector.opusencoder.OggOpusEncoder -import im.vector.opusencoder.configuration.SampleRate +import io.element.android.opusencoder.OggOpusEncoder +import io.element.android.opusencoder.configuration.SampleRate import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.isActive From d904ebbd70d9a122ca8824636ea1cb6851d54717 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 5 Jul 2022 14:27:42 +0100 Subject: [PATCH 075/131] overriding the default list handler with an implementation that takes into account the initial starting position --- .../app/features/html/EventHtmlRenderer.kt | 2 + .../html/ListHandlerWithInitialStart.java | 111 ++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 vector/src/main/java/im/vector/app/features/html/ListHandlerWithInitialStart.java diff --git a/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt b/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt index ed6b68e04a..768e0f222d 100644 --- a/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt @@ -152,7 +152,9 @@ class EventHtmlRenderer @Inject constructor( class MatrixHtmlPluginConfigure @Inject constructor(private val colorProvider: ColorProvider, private val resources: Resources) : HtmlPlugin.HtmlConfigure { override fun configureHtml(plugin: HtmlPlugin) { + plugin + .addHandler(ListHandlerWithInitialStart()) .addHandler(FontTagHandler()) .addHandler(ParagraphHandler(DimensionConverter(resources))) .addHandler(MxReplyTagHandler()) diff --git a/vector/src/main/java/im/vector/app/features/html/ListHandlerWithInitialStart.java b/vector/src/main/java/im/vector/app/features/html/ListHandlerWithInitialStart.java new file mode 100644 index 0000000000..c7ba881da0 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/html/ListHandlerWithInitialStart.java @@ -0,0 +1,111 @@ +/* + * 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.html; + +import androidx.annotation.NonNull; + +import org.commonmark.node.ListItem; + +import java.util.Arrays; +import java.util.Collection; + +import io.noties.markwon.MarkwonConfiguration; +import io.noties.markwon.MarkwonVisitor; +import io.noties.markwon.RenderProps; +import io.noties.markwon.SpanFactory; +import io.noties.markwon.SpannableBuilder; +import io.noties.markwon.core.CoreProps; +import io.noties.markwon.html.HtmlTag; +import io.noties.markwon.html.MarkwonHtmlRenderer; +import io.noties.markwon.html.TagHandler; + +/** + * Copied from https://github.com/noties/Markwon/blob/master/markwon-html/src/main/java/io/noties/markwon/html/tag/ListHandler.java#L44 + * With a modification on the starting list position + */ +public class ListHandlerWithInitialStart extends TagHandler { + + private static final String START_KEY = "start"; + + @Override + public void handle( + @NonNull MarkwonVisitor visitor, + @NonNull MarkwonHtmlRenderer renderer, + @NonNull HtmlTag tag) { + + if (!tag.isBlock()) { + return; + } + + final HtmlTag.Block block = tag.getAsBlock(); + final boolean ol = "ol".equals(block.name()); + final boolean ul = "ul".equals(block.name()); + + if (!ol && !ul) { + return; + } + + final MarkwonConfiguration configuration = visitor.configuration(); + final RenderProps renderProps = visitor.renderProps(); + final SpanFactory spanFactory = configuration.spansFactory().get(ListItem.class); + + // Modified line + int number = Integer.parseInt(block.attributes().containsKey(START_KEY) ? block.attributes().get(START_KEY) : "1"); + + final int bulletLevel = currentBulletListLevel(block); + + for (HtmlTag.Block child : block.children()) { + + visitChildren(visitor, renderer, child); + + if (spanFactory != null && "li".equals(child.name())) { + + // insert list item here + if (ol) { + CoreProps.LIST_ITEM_TYPE.set(renderProps, CoreProps.ListItemType.ORDERED); + CoreProps.ORDERED_LIST_ITEM_NUMBER.set(renderProps, number++); + } else { + CoreProps.LIST_ITEM_TYPE.set(renderProps, CoreProps.ListItemType.BULLET); + CoreProps.BULLET_LIST_ITEM_LEVEL.set(renderProps, bulletLevel); + } + + SpannableBuilder.setSpans( + visitor.builder(), + spanFactory.getSpans(configuration, renderProps), + child.start(), + child.end()); + } + } + } + + @NonNull + @Override + public Collection supportedTags() { + return Arrays.asList("ol", "ul"); + } + + private static int currentBulletListLevel(@NonNull HtmlTag.Block block) { + int level = 0; + while ((block = block.parent()) != null) { + if ("ul".equals(block.name()) + || "ol".equals(block.name())) { + level += 1; + } + } + return level; + } +} From ff2fc3e0a76706ebc9ff1e94c3726c7b2d5deec9 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 5 Jul 2022 15:29:58 +0100 Subject: [PATCH 076/131] adding changelog entry --- changelog.d/4777.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/4777.bugfix diff --git a/changelog.d/4777.bugfix b/changelog.d/4777.bugfix new file mode 100644 index 0000000000..428101f649 --- /dev/null +++ b/changelog.d/4777.bugfix @@ -0,0 +1 @@ +Fixes numbered lists always starting from 1 From a0f86d270b699a311bc0b23634829379fc29d029 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 5 Jul 2022 15:38:45 +0100 Subject: [PATCH 077/131] removing extra line --- .../main/java/im/vector/app/features/html/EventHtmlRenderer.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt b/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt index 768e0f222d..412b28862a 100644 --- a/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt @@ -152,7 +152,6 @@ class EventHtmlRenderer @Inject constructor( class MatrixHtmlPluginConfigure @Inject constructor(private val colorProvider: ColorProvider, private val resources: Resources) : HtmlPlugin.HtmlConfigure { override fun configureHtml(plugin: HtmlPlugin) { - plugin .addHandler(ListHandlerWithInitialStart()) .addHandler(FontTagHandler()) From cfb1e09d64c184e12787824ce67c7b0e93917ff0 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 6 Jul 2022 11:44:33 +0100 Subject: [PATCH 078/131] adding tests around the event html rendering - the test helper is a little hacky in order to covert the spans to something human readable --- .../java/im/vector/app/core/utils/TestSpan.kt | 91 +++++++++++++++++++ .../features/html/EventHtmlRendererTest.kt | 75 +++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 vector/src/androidTest/java/im/vector/app/core/utils/TestSpan.kt create mode 100644 vector/src/androidTest/java/im/vector/app/features/html/EventHtmlRendererTest.kt diff --git a/vector/src/androidTest/java/im/vector/app/core/utils/TestSpan.kt b/vector/src/androidTest/java/im/vector/app/core/utils/TestSpan.kt new file mode 100644 index 0000000000..9e23e76f0c --- /dev/null +++ b/vector/src/androidTest/java/im/vector/app/core/utils/TestSpan.kt @@ -0,0 +1,91 @@ +/* + * 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.core.utils + +import android.graphics.Canvas +import android.graphics.Paint +import android.text.Layout +import android.text.Spannable +import androidx.core.text.getSpans +import im.vector.app.features.html.HtmlCodeSpan +import io.mockk.justRun +import io.mockk.mockk +import io.mockk.slot +import io.mockk.verify +import io.noties.markwon.core.spans.EmphasisSpan +import io.noties.markwon.core.spans.OrderedListItemSpan +import io.noties.markwon.core.spans.StrongEmphasisSpan + +fun Spannable.toTestSpan(): String { + var output = toString() + readSpansWithContent().forEach { + val tags = it.span.readTags() + val remappedContent = it.span.remapContent(source = this, originalContent = it.content) + output = output.replace(it.content, "${tags.open}$remappedContent${tags.close}") + } + return output +} + +private fun Spannable.readSpansWithContent() = getSpans().map { span -> + val start = getSpanStart(span) + val end = getSpanEnd(span) + SpanWithContent( + content = substring(start, end), + span = span + ) +}.reversed() + +private fun Any.readTags(): SpanTags { + return when (this::class) { + OrderedListItemSpan::class -> SpanTags("[list item]", "[/list item]") + HtmlCodeSpan::class -> SpanTags("[code]", "[/code]") + StrongEmphasisSpan::class -> SpanTags("[bold]", "[/bold]") + EmphasisSpan::class -> SpanTags("[italic]", "[/italic]") + else -> throw IllegalArgumentException("Unknown ${this::class}") + } +} + +private fun Any.remapContent(source: CharSequence, originalContent: String): String { + return when (this::class) { + OrderedListItemSpan::class -> { + val prefix = (this as OrderedListItemSpan).collectNumber(source) + "$prefix$originalContent" + } + else -> originalContent + } +} + +private fun OrderedListItemSpan.collectNumber(text: CharSequence): String { + val fakeCanvas = mockk() + val fakeLayout = mockk() + justRun { fakeCanvas.drawText(any(), any(), any(), any()) } + val paint = Paint() + drawLeadingMargin(fakeCanvas, paint, 0, 0, 0, 0, 0, text, 0, text.length - 1, true, fakeLayout) + val slot = slot() + verify { fakeCanvas.drawText(capture(slot), any(), any(), any()) } + return slot.captured +} + +private data class SpanTags( + val open: String, + val close: String, +) + +private data class SpanWithContent( + val content: String, + val span: Any +) diff --git a/vector/src/androidTest/java/im/vector/app/features/html/EventHtmlRendererTest.kt b/vector/src/androidTest/java/im/vector/app/features/html/EventHtmlRendererTest.kt new file mode 100644 index 0000000000..a1b74778a5 --- /dev/null +++ b/vector/src/androidTest/java/im/vector/app/features/html/EventHtmlRendererTest.kt @@ -0,0 +1,75 @@ +/* + * 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.html + +import androidx.core.text.toSpannable +import androidx.test.platform.app.InstrumentationRegistry +import im.vector.app.core.resources.ColorProvider +import im.vector.app.core.utils.toTestSpan +import im.vector.app.features.settings.VectorPreferences +import io.mockk.every +import io.mockk.mockk +import org.amshove.kluent.shouldBeEqualTo +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import kotlin.text.Typography.nbsp + +@RunWith(JUnit4::class) +class EventHtmlRendererTest { + + private val context = InstrumentationRegistry.getInstrumentation().targetContext + private val fakeVectorPreferences = mockk().also { + every { it.latexMathsIsEnabled() } returns false + } + + private val renderer = EventHtmlRenderer( + MatrixHtmlPluginConfigure(ColorProvider(context), context.resources), + context, + fakeVectorPreferences + ) + + @Test + fun takesInitialListPositionIntoAccount() { + val result = """

  1. first entry
""".renderAsTestSpan() + + result shouldBeEqualTo "[list item]5.${nbsp}first entry[/list item]\n" + } + + @Test + fun doesNotProcessMarkdownWithinCodeBlocks() { + val result = """__italic__ **bold**""".renderAsTestSpan() + + result shouldBeEqualTo "[code]__italic__ **bold**[/code]" + } + + @Test + fun doesNotProcessMarkdownBoldAndItalic() { + val result = """__italic__ **bold**""".renderAsTestSpan() + + result shouldBeEqualTo "__italic__ **bold**" + } + + @Test + fun processesHtmlWithinCodeBlocks() { + val result = """italic bold""".renderAsTestSpan() + + result shouldBeEqualTo "[code][italic]italic[/italic] [bold]bold[/bold][/code]" + } + + private fun String.renderAsTestSpan() = renderer.render(this).toSpannable().toTestSpan() +} From ead8cec4a69155d0995098f4575fc79be9486dd2 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 7 Jul 2022 13:54:42 +0100 Subject: [PATCH 079/131] adding test case for showing html entities are processed --- .../im/vector/app/features/html/EventHtmlRendererTest.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/vector/src/androidTest/java/im/vector/app/features/html/EventHtmlRendererTest.kt b/vector/src/androidTest/java/im/vector/app/features/html/EventHtmlRendererTest.kt index a1b74778a5..41c0f51322 100644 --- a/vector/src/androidTest/java/im/vector/app/features/html/EventHtmlRendererTest.kt +++ b/vector/src/androidTest/java/im/vector/app/features/html/EventHtmlRendererTest.kt @@ -71,5 +71,12 @@ class EventHtmlRendererTest { result shouldBeEqualTo "[code][italic]italic[/italic] [bold]bold[/bold][/code]" } + @Test + fun processesHtmlEntities() { + val result = """& < > ' """".renderAsTestSpan() + + result shouldBeEqualTo """& < > ' """" + } + private fun String.renderAsTestSpan() = renderer.render(this).toSpannable().toTestSpan() } From 64871e368104e87c8ed90c0262a6ff5dc5460791 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 7 Jul 2022 17:40:48 +0200 Subject: [PATCH 080/131] Add documentation about nightly build. --- docs/nightly_build.md | 54 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 docs/nightly_build.md diff --git a/docs/nightly_build.md b/docs/nightly_build.md new file mode 100644 index 0000000000..91f18214c4 --- /dev/null +++ b/docs/nightly_build.md @@ -0,0 +1,54 @@ +# Nightly builds + + + +* [Configuration](#configuration) +* [How to register to get nightly build](#how-to-register-to-get-nightly-build) +* [Build nightly manually](#build-nightly-manually) + + + +## Configuration + +The nightly build will contain what's on develop, in release mode, for Gplay variant. It is signed using a dedicated signature, and has a dedicated appId (`im.vector.app.nightly`), so it can be installed along with the production version of Element Android. The only other difference compared to Element Android is a different app icon background. We do not want to change the app name since it will also affect some strings in the app, and we do want to do that. + +Nightly builds are built and released to Firebase every days, and automatically. + +This is recommended to exclusively use this app, with your main account, instead of Element Android, and fallback to Element Android just in case of regression, to discover as soon as possible any regression, and report it to the team. To avoid double notification, you may want to disable the notification from the Element Android production version. Just open Element Android, navigate to `Settings/Notifications` and uncheck `Enable notifications for this session`. + +*Note:* Due to a limitation of Firebase, the nightly build is the universal build, which means that the size of the APK is a bit bigger, but this should not have any other side effect. + +## How to register to get nightly build + +Provide your email to the Android team, who will add it to the list "External testers" on Firebase. You will then receive an invite on the provided email. + +Follow the instructions on the email to install the latest nightly build. This is not clear yet if new nightly build will be automatically installed or not. + +## Build nightly manually + +Nightly build can be built manually from your computer. You will need to retrieved some secrets from Passbolt and add them to your file `~/.gradle/gradle.properties`: + +``` +signing.element.nightly.storePassword=VALUE_FROM_PASSBOLT +signing.element.nightly.keyId=VALUE_FROM_PASSBOLT +signing.element.nightly.keyPassword=VALUE_FROM_PASSBOLT +``` + +You will also need to add the environment variable `FIREBASE_TOKEN`: + +```sh +export FIREBASE_TOKEN=VALUE_FROM_PASSBOLT +``` + +Then you can run the following commands (which are also used in the file for [the GitHub action](../.github/workflows/nightly.yml)): + +```sh +git checkout develop +mv towncrier.toml towncrier.toml.bak +sed 's/CHANGES\.md/CHANGES_NIGHTLY\.md/' towncrier.toml.bak > towncrier.toml +rm towncrier.toml.bak +yes n | towncrier --version nightly +./gradlew assembleGplayNightly appDistributionUploadGplayNightly $CI_GRADLE_ARG_PROPERTIES --stacktrace +``` + +Then you can reset the change on the codebase. From 95f4d884617c97dc29972859db1641c3faa450d2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 7 Jul 2022 17:45:18 +0200 Subject: [PATCH 081/131] Do not alter the app name for the nightly, and finally use `initWith release` to avoid too many copy paste. --- vector/build.gradle | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/vector/build.gradle b/vector/build.gradle index 4de97199b4..f4d4453fb9 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -267,6 +267,7 @@ android { buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false" buildConfigField "boolean", "ENABLE_STRICT_MODE_LOGS", "false" + // When updating this block, please also update the same block in the `nightly` buildType below postprocessing { removeUnusedCode true removeUnusedResources true @@ -281,12 +282,12 @@ android { nightly { applicationIdSuffix ".nightly" versionNameSuffix "-nightly" - resValue "string", "app_name", "Element nightly" + + initWith release + // Just override the background color of the launcher icon for the nightly build. resValue "color", "launcher_background", "#07007E" - buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false" - buildConfigField "boolean", "ENABLE_STRICT_MODE_LOGS", "false" - + // We need to copy paste this block, this is not done automatically by `initWith release` postprocessing { removeUnusedCode true removeUnusedResources true From 9a059ead440e48838016583038802204aeffa72e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 7 Jul 2022 18:29:02 +0200 Subject: [PATCH 082/131] Add a VectorFeatures to force usage of the library OpusEncoder --- .../vector/app/features/voice/VoiceRecorderProviderTests.kt | 3 ++- .../app/features/debug/features/DebugFeaturesStateFactory.kt | 5 +++++ .../app/features/debug/features/DebugVectorFeatures.kt | 4 ++++ .../src/main/java/im/vector/app/features/VectorFeatures.kt | 2 ++ .../im/vector/app/features/voice/VoiceRecorderProvider.kt | 4 +++- 5 files changed, 16 insertions(+), 2 deletions(-) diff --git a/vector/src/androidTest/java/im/vector/app/features/voice/VoiceRecorderProviderTests.kt b/vector/src/androidTest/java/im/vector/app/features/voice/VoiceRecorderProviderTests.kt index c7105b613f..61f745178c 100644 --- a/vector/src/androidTest/java/im/vector/app/features/voice/VoiceRecorderProviderTests.kt +++ b/vector/src/androidTest/java/im/vector/app/features/voice/VoiceRecorderProviderTests.kt @@ -19,6 +19,7 @@ package im.vector.app.features.voice import android.os.Build import androidx.test.platform.app.InstrumentationRegistry import im.vector.app.AndroidVersionTestOverrider +import im.vector.app.features.DefaultVectorFeatures import org.amshove.kluent.shouldBeInstanceOf import org.junit.After import org.junit.Test @@ -26,7 +27,7 @@ import org.junit.Test class VoiceRecorderProviderTests { private val context = InstrumentationRegistry.getInstrumentation().targetContext - private val provider = VoiceRecorderProvider(context) + private val provider = VoiceRecorderProvider(context, DefaultVectorFeatures()) @After fun tearDown() { diff --git a/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt b/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt index 248d9d232b..32dfd432d9 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt +++ b/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt @@ -70,6 +70,11 @@ class DebugFeaturesStateFactory @Inject constructor( key = DebugFeatureKeys.allowExternalUnifiedPushDistributors, factory = VectorFeatures::allowExternalUnifiedPushDistributors ), + createBooleanFeature( + label = "Force usage of OpusEncoder library", + key = DebugFeatureKeys.forceUsageOfOpusEncoder, + factory = VectorFeatures::forceUsageOfOpusEncoder + ), ) ) } diff --git a/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt b/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt index 99b56bb0ca..cc581fe5ab 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt +++ b/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt @@ -66,6 +66,9 @@ class DebugVectorFeatures( override fun isScreenSharingEnabled(): Boolean = read(DebugFeatureKeys.screenSharing) ?: vectorFeatures.isScreenSharingEnabled() + override fun forceUsageOfOpusEncoder(): Boolean = read(DebugFeatureKeys.forceUsageOfOpusEncoder) + ?: vectorFeatures.forceUsageOfOpusEncoder() + fun override(value: T?, key: Preferences.Key) = updatePreferences { if (value == null) { it.remove(key) @@ -123,4 +126,5 @@ object DebugFeatureKeys { val allowExternalUnifiedPushDistributors = booleanPreferencesKey("allow-external-unified-push-distributors") val liveLocationSharing = booleanPreferencesKey("live-location-sharing") val screenSharing = booleanPreferencesKey("screen-sharing") + val forceUsageOfOpusEncoder = booleanPreferencesKey("force-usage-of-opus-encoder") } diff --git a/vector/src/main/java/im/vector/app/features/VectorFeatures.kt b/vector/src/main/java/im/vector/app/features/VectorFeatures.kt index 6fe4beff95..fd3bbf4a89 100644 --- a/vector/src/main/java/im/vector/app/features/VectorFeatures.kt +++ b/vector/src/main/java/im/vector/app/features/VectorFeatures.kt @@ -30,6 +30,7 @@ interface VectorFeatures { fun isOnboardingCombinedLoginEnabled(): Boolean fun allowExternalUnifiedPushDistributors(): Boolean fun isScreenSharingEnabled(): Boolean + fun forceUsageOfOpusEncoder(): Boolean enum class OnboardingVariant { LEGACY, @@ -48,4 +49,5 @@ class DefaultVectorFeatures : VectorFeatures { override fun isOnboardingCombinedLoginEnabled() = false override fun allowExternalUnifiedPushDistributors(): Boolean = Config.ALLOW_EXTERNAL_UNIFIED_PUSH_DISTRIBUTORS override fun isScreenSharingEnabled(): Boolean = true + override fun forceUsageOfOpusEncoder(): Boolean = false } diff --git a/vector/src/main/java/im/vector/app/features/voice/VoiceRecorderProvider.kt b/vector/src/main/java/im/vector/app/features/voice/VoiceRecorderProvider.kt index d24e7fcc8c..28693ca287 100644 --- a/vector/src/main/java/im/vector/app/features/voice/VoiceRecorderProvider.kt +++ b/vector/src/main/java/im/vector/app/features/voice/VoiceRecorderProvider.kt @@ -18,14 +18,16 @@ package im.vector.app.features.voice import android.content.Context import android.os.Build +import im.vector.app.features.VectorFeatures import kotlinx.coroutines.Dispatchers import javax.inject.Inject class VoiceRecorderProvider @Inject constructor( private val context: Context, + private val vectorFeatures: VectorFeatures, ) { fun provideVoiceRecorder(): VoiceRecorder { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && vectorFeatures.forceUsageOfOpusEncoder().not()) { VoiceRecorderQ(context) } else { VoiceRecorderL(context, Dispatchers.IO) From dd5c3432690b6fa1e783fcd9e40042b6686d68b1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 7 Jul 2022 20:34:27 +0200 Subject: [PATCH 083/131] io.element.android:opusencoder:1.0.1 --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 7c6d6c3e08..1f91f20f0d 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -97,7 +97,7 @@ ext.libs = [ 'flipperNetworkPlugin' : "com.facebook.flipper:flipper-network-plugin:$flipper", ], element : [ - 'opusencoder' : "io.element.android:opusencoder:1.0.0", + 'opusencoder' : "io.element.android:opusencoder:1.0.1", ], squareup : [ 'moshi' : "com.squareup.moshi:moshi:$moshi", From 07f2d9b44959e2e73052b45e82515937c4036c51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Wed, 6 Jul 2022 16:38:51 +0000 Subject: [PATCH 084/131] Translated using Weblate (Estonian) Currently translated at 99.6% (2252 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/et/ --- vector/src/main/res/values-et/strings.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/vector/src/main/res/values-et/strings.xml b/vector/src/main/res/values-et/strings.xml index fdb4506142..be3991e625 100644 --- a/vector/src/main/res/values-et/strings.xml +++ b/vector/src/main/res/values-et/strings.xml @@ -2508,4 +2508,17 @@ Lähtesta teavituse meetod Profiili silt: Järgmine + Hetkel on kasutusel %s. + Meetod + + Leidsin %d meetodi. + Leidsin %d meetodit. + + Ühtegi teist meetodit peale taustal sünkroniseerimise ei leidunud. + Ühtegi teist meetodit peale Google Play Service ei leidunud. + Saadaval olevad meetodid + Teavituse meetod + Sünkroniseerimine taustal + Google\'i teenused + Vali teavituste laadimise viis \ No newline at end of file From 6acd37e45795aea2552081175911b37260f844e5 Mon Sep 17 00:00:00 2001 From: Nikita Epifanov Date: Wed, 6 Jul 2022 20:29:26 +0000 Subject: [PATCH 085/131] Translated using Weblate (Russian) Currently translated at 100.0% (2260 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ru/ --- vector/src/main/res/values-ru/strings.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/vector/src/main/res/values-ru/strings.xml b/vector/src/main/res/values-ru/strings.xml index 17d48c59f2..2d7e700b06 100644 --- a/vector/src/main/res/values-ru/strings.xml +++ b/vector/src/main/res/values-ru/strings.xml @@ -2602,4 +2602,12 @@ Сбросить способ оповещения Фоновая синхронизация Далее + Не удалось зарегистрировать токен конечной точки на домашнем сервере: +\n%1$s + Конечная точка успешно зарегистрирована на домашнем сервере. + Регистрация конечной точки + Не удалось найти конечную точку. + Текущая конечная точка: %s + Конечная точка + Вещи в этом пространстве \ No newline at end of file From dc1ac779f1a8536362f79051b4f89c6c4be5041e Mon Sep 17 00:00:00 2001 From: Nikita Epifanov Date: Wed, 6 Jul 2022 20:41:31 +0000 Subject: [PATCH 086/131] Translated using Weblate (Russian) Currently translated at 100.0% (68 of 68 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/ru/ --- fastlane/metadata/android/ru-RU/changelogs/40104060.txt | 2 ++ fastlane/metadata/android/ru-RU/changelogs/40104070.txt | 2 ++ fastlane/metadata/android/ru-RU/changelogs/40104080.txt | 2 ++ fastlane/metadata/android/ru-RU/changelogs/40104100.txt | 2 ++ fastlane/metadata/android/ru-RU/changelogs/40104110.txt | 2 ++ fastlane/metadata/android/ru-RU/changelogs/40104120.txt | 2 ++ fastlane/metadata/android/ru-RU/changelogs/40104130.txt | 2 ++ fastlane/metadata/android/ru-RU/changelogs/40104140.txt | 2 ++ fastlane/metadata/android/ru-RU/changelogs/40104160.txt | 2 ++ fastlane/metadata/android/ru-RU/changelogs/40104180.txt | 2 ++ fastlane/metadata/android/ru-RU/changelogs/40104190.txt | 2 ++ fastlane/metadata/android/ru-RU/changelogs/40104200.txt | 2 ++ fastlane/metadata/android/ru-RU/changelogs/40104220.txt | 2 ++ fastlane/metadata/android/ru-RU/changelogs/40104230.txt | 2 ++ fastlane/metadata/android/ru-RU/changelogs/40104240.txt | 2 ++ fastlane/metadata/android/ru-RU/full_description.txt | 2 +- 16 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 fastlane/metadata/android/ru-RU/changelogs/40104060.txt create mode 100644 fastlane/metadata/android/ru-RU/changelogs/40104070.txt create mode 100644 fastlane/metadata/android/ru-RU/changelogs/40104080.txt create mode 100644 fastlane/metadata/android/ru-RU/changelogs/40104100.txt create mode 100644 fastlane/metadata/android/ru-RU/changelogs/40104110.txt create mode 100644 fastlane/metadata/android/ru-RU/changelogs/40104120.txt create mode 100644 fastlane/metadata/android/ru-RU/changelogs/40104130.txt create mode 100644 fastlane/metadata/android/ru-RU/changelogs/40104140.txt create mode 100644 fastlane/metadata/android/ru-RU/changelogs/40104160.txt create mode 100644 fastlane/metadata/android/ru-RU/changelogs/40104180.txt create mode 100644 fastlane/metadata/android/ru-RU/changelogs/40104190.txt create mode 100644 fastlane/metadata/android/ru-RU/changelogs/40104200.txt create mode 100644 fastlane/metadata/android/ru-RU/changelogs/40104220.txt create mode 100644 fastlane/metadata/android/ru-RU/changelogs/40104230.txt create mode 100644 fastlane/metadata/android/ru-RU/changelogs/40104240.txt diff --git a/fastlane/metadata/android/ru-RU/changelogs/40104060.txt b/fastlane/metadata/android/ru-RU/changelogs/40104060.txt new file mode 100644 index 0000000000..e241853529 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40104060.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: Лента веток работает в реальном времени и быстрее. Различные исправления ошибок и улучшения стабильности. +Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.4.6 diff --git a/fastlane/metadata/android/ru-RU/changelogs/40104070.txt b/fastlane/metadata/android/ru-RU/changelogs/40104070.txt new file mode 100644 index 0000000000..d53e18c58d --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40104070.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: Различные исправления ошибок и улучшения стабильности. +Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.4.7 diff --git a/fastlane/metadata/android/ru-RU/changelogs/40104080.txt b/fastlane/metadata/android/ru-RU/changelogs/40104080.txt new file mode 100644 index 0000000000..faa12f093b --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40104080.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: Лента веток работает в реальном времени и быстрее. Различные исправления ошибок и улучшения стабильности. +Полный список изменений: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/ru-RU/changelogs/40104100.txt b/fastlane/metadata/android/ru-RU/changelogs/40104100.txt new file mode 100644 index 0000000000..853c7aabec --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40104100.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: Прокрутка голосовых сообщений. Различные исправления ошибок и улучшения стабильности. +Полный список изменений: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/ru-RU/changelogs/40104110.txt b/fastlane/metadata/android/ru-RU/changelogs/40104110.txt new file mode 100644 index 0000000000..31cc5effa6 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40104110.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: Различные исправления ошибок и улучшения стабильности. +Полный список изменений: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/ru-RU/changelogs/40104120.txt b/fastlane/metadata/android/ru-RU/changelogs/40104120.txt new file mode 100644 index 0000000000..0dc35fac76 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40104120.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: Позволяет пользователям появляться в автономном режиме и добавляет аудиопроигрыватель для аудиовложений +Полный список изменений: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/ru-RU/changelogs/40104130.txt b/fastlane/metadata/android/ru-RU/changelogs/40104130.txt new file mode 100644 index 0000000000..3eec4c4987 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40104130.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: Позволяет пользователям появляться в автономном режиме и добавляет аудиопроигрыватель для аудиовложений. +Полный список изменений: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/ru-RU/changelogs/40104140.txt b/fastlane/metadata/android/ru-RU/changelogs/40104140.txt new file mode 100644 index 0000000000..dcb6d19cbf --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40104140.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: Улучшено управление игнорируемыми пользователями. Различные исправления ошибок и улучшения стабильности. +Полный список изменений: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/ru-RU/changelogs/40104160.txt b/fastlane/metadata/android/ru-RU/changelogs/40104160.txt new file mode 100644 index 0000000000..ea8f0f84cb --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40104160.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: Улучшено управление зашифрованными сообщениями. Различные исправления ошибок и улучшения стабильности. +Полный список изменений: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/ru-RU/changelogs/40104180.txt b/fastlane/metadata/android/ru-RU/changelogs/40104180.txt new file mode 100644 index 0000000000..31cc5effa6 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40104180.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: Различные исправления ошибок и улучшения стабильности. +Полный список изменений: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/ru-RU/changelogs/40104190.txt b/fastlane/metadata/android/ru-RU/changelogs/40104190.txt new file mode 100644 index 0000000000..31cc5effa6 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40104190.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: Различные исправления ошибок и улучшения стабильности. +Полный список изменений: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/ru-RU/changelogs/40104200.txt b/fastlane/metadata/android/ru-RU/changelogs/40104200.txt new file mode 100644 index 0000000000..31cc5effa6 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40104200.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: Различные исправления ошибок и улучшения стабильности. +Полный список изменений: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/ru-RU/changelogs/40104220.txt b/fastlane/metadata/android/ru-RU/changelogs/40104220.txt new file mode 100644 index 0000000000..31cc5effa6 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40104220.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: Различные исправления ошибок и улучшения стабильности. +Полный список изменений: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/ru-RU/changelogs/40104230.txt b/fastlane/metadata/android/ru-RU/changelogs/40104230.txt new file mode 100644 index 0000000000..31cc5effa6 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40104230.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: Различные исправления ошибок и улучшения стабильности. +Полный список изменений: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/ru-RU/changelogs/40104240.txt b/fastlane/metadata/android/ru-RU/changelogs/40104240.txt new file mode 100644 index 0000000000..31cc5effa6 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40104240.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: Различные исправления ошибок и улучшения стабильности. +Полный список изменений: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/ru-RU/full_description.txt b/fastlane/metadata/android/ru-RU/full_description.txt index 3d8949e466..b2320d9f0b 100644 --- a/fastlane/metadata/android/ru-RU/full_description.txt +++ b/fastlane/metadata/android/ru-RU/full_description.txt @@ -40,4 +40,4 @@ Element дает вам возможность контролировать си Открытый исходный код -Element Android - это проект с открытым исходным кодом, размещенный на GitHub. Пожалуйста, сообщайте об ошибках и/или вносите вклад в его развитие по адресу https://github.com/vector-im/element-android. +Element Android - это проект с открытым исходным кодом, размещенный на GitHub. Пожалуйста, сообщайте об ошибках и/или вносите вклад в его развитие по адресу https://github.com/vector-im/element-android From bdc370474e1e9478b4c611fcb9ee4ad23425ff17 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Fri, 8 Jul 2022 10:38:52 +0100 Subject: [PATCH 087/131] migrating the previous orphaned rooms settings in order to fix the inconsistent value - only uses the previous value if the key exists, otherwise we end up defaulting to true instead of false (which the preferences screen expects) - manually deletes the key after migrating the value --- changelog.d/6510.bugfix | 1 + .../features/settings/VectorPreferences.kt | 30 +++++++++++++------ 2 files changed, 22 insertions(+), 9 deletions(-) create mode 100644 changelog.d/6510.bugfix diff --git a/changelog.d/6510.bugfix b/changelog.d/6510.bugfix new file mode 100644 index 0000000000..bd21b5c498 --- /dev/null +++ b/changelog.d/6510.bugfix @@ -0,0 +1 @@ +Fixes inconsistency with rooms within spaces showing or disappearing from home diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index ea039f0ed8..2215bb8a4f 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -1020,20 +1020,32 @@ class VectorPreferences @Inject constructor( } } - private fun labsSpacesOnlyOrphansInHome(): Boolean { - return defaultPrefs.getBoolean(SETTINGS_LABS_SPACES_HOME_AS_ORPHAN, false) - } - fun labsAutoReportUISI(): Boolean { return defaultPrefs.getBoolean(SETTINGS_LABS_AUTO_REPORT_UISI, false) } fun prefSpacesShowAllRoomInHome(): Boolean { - return defaultPrefs.getBoolean( - SETTINGS_PREF_SPACE_SHOW_ALL_ROOM_IN_HOME, - // migration of old property - !labsSpacesOnlyOrphansInHome() - ) + val defaultValue = false + return when { + defaultPrefs.contains(SETTINGS_PREF_SPACE_SHOW_ALL_ROOM_IN_HOME) -> { + defaultPrefs.getBoolean(SETTINGS_PREF_SPACE_SHOW_ALL_ROOM_IN_HOME, defaultValue) + } + defaultPrefs.contains(SETTINGS_LABS_SPACES_HOME_AS_ORPHAN) -> migrateOrphansInSpacesToShowAllInHome() + else -> defaultValue + } + } + + private fun migrateOrphansInSpacesToShowAllInHome(): Boolean { + val showAllRoomsInHome = !labsSpacesOnlyOrphansInHome() + defaultPrefs.edit { + putBoolean(SETTINGS_PREF_SPACE_SHOW_ALL_ROOM_IN_HOME, showAllRoomsInHome) + remove(SETTINGS_LABS_SPACES_HOME_AS_ORPHAN) + } + return showAllRoomsInHome + } + + private fun labsSpacesOnlyOrphansInHome(): Boolean { + return defaultPrefs.getBoolean(SETTINGS_LABS_SPACES_HOME_AS_ORPHAN, false) } /* From 94567510ca6b9a3227f7cf3a4f6b9e21f4633dc9 Mon Sep 17 00:00:00 2001 From: Mya Rohit Date: Sat, 9 Jul 2022 14:45:07 +0000 Subject: [PATCH 088/131] Translated using Weblate (Bulgarian) Currently translated at 66.6% (1507 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/bg/ --- vector/src/main/res/values-bg/strings.xml | 57 +++++------------------ 1 file changed, 12 insertions(+), 45 deletions(-) diff --git a/vector/src/main/res/values-bg/strings.xml b/vector/src/main/res/values-bg/strings.xml index 3c4df52d6b..1ee559f8f7 100644 --- a/vector/src/main/res/values-bg/strings.xml +++ b/vector/src/main/res/values-bg/strings.xml @@ -38,7 +38,6 @@ Устройството на подателя не изпрати ключовете за това съобщение. Покана за стая %1$s и %2$s - Празна стая Начална синхронизация: \nИмпортиране на профил… @@ -46,15 +45,16 @@ \nИмпортиране на данни за шифроване Начална синхронизация: \nИмпортиране на стаи - Начална синхронизация: + Начална синхронизация. +\nЗареждане на моите разговори \nИмпортиране на стаи, от които съм част - Начална синхронизация: + Начална синхронизация. \nИмпортиране на стаи, към които съм поканен - Начална синхронизация: + Начална синхронизация. \nИмпортиране на стаи, които съм напуснал - Начална синхронизация: + Начална синхронизация. \nИмпортиране на общности - Начална синхронизация: + Начална синхронизация. \nИмпортиране на данни за профила %s обнови тази стая. Изпращане на съобщение… @@ -194,7 +194,6 @@ В момента тече разговор… Свързване… Разговорът приключи - %d член %d членове @@ -226,7 +225,6 @@ Шумни известия Уведомления без звук Прегледай разшифрования източник - или Покани Отписване @@ -248,7 +246,6 @@ Само потребители на Matrix Няма резултати Стаи - Общности Изпращане на логове Изпращане на логове за забивания @@ -284,9 +281,7 @@ Този Home сървър би искал да се увери, че не сте робот Имейл адресът, свързан с профила Ви, трябва да бъде въведен. Неуспешно потвърждаване на имейл адреса: уверете се, че сте кликнали върху връзката в имейла - Напредък (%s%%) - Въведете валиден URL адрес Грешно формиран JSON Не съдържаше валиден JSON @@ -322,12 +317,9 @@ Приемайте сертификата само ако администратора на сървъра е публикувал отпечатък, който съвпада с този по-горе. Довери се Не се доверявай - Търси Филтриране на членовете Няма резултати - - Всички съобщения Добави на главния екран Профилна снимка @@ -370,7 +362,6 @@ Обнови публичното име Последно видян %1$s @ %2$s - Автентикация Влезли сте като Home сървър @@ -406,7 +397,6 @@ Това са експериментални функции, които могат да се счупят по неочаквани начини. Внимавайте при използване. Задай като основен адрес Премахни задаването като основен адрес - Тема Грешка при разшифроване Публично име @@ -418,7 +408,6 @@ Експортирай Въведи парола Потвърди парола - Импортирай E2E ключове за стая Импортиране на ключове за стая Импортирай ключовете в локален файл @@ -430,7 +419,6 @@ Потвърди За да потвърдите, че на това устройство може да се вярва, моля свържете се със собственика му по друг начин (напр. на живо или чрез телефонен разговор) и го попитайте дали ключът, който вижда в настройките на потребителя за това устройство, съвпада с ключа по-долу: Ако съвпада, моля натиснете бутона за потвърждение по-долу. Ако не съвпада, то тогава някой друг имитира това устройство и вероятно бихте искали да го вкарате в черния списък. В бъдеще този процес на потвърждение ще бъде по-лесен. - Адрес на Home сървър Всички стаи на сървър %s Всички изцяло %s стаи @@ -453,14 +441,10 @@ Липсва user_id в заявката. Стая %s не е видима. Добави Matrix приложения - - ${app_name} иска разшерение за достъп до Вашия микрофон, за да се извърши звуков разговор. - ${app_name} иска разширение за достъп до микрофона и камерата Ви, за да извърши видео разговор. \n \nМоля, разрешете достъпа от следващия прозорец, който ще се покаже, за да можете да се обадите. - ДА НЕ Продължи @@ -470,7 +454,6 @@ Профилна снимка Списък с членове Отиди до първото непрочетено съобщение. - Напускане на стая Покани Покажи системния екран с информация за приложението. @@ -490,7 +473,6 @@ %d непрочетено съобщение %d непрочетени съобщения - Размер на шрифта Ситен Малък @@ -559,16 +541,10 @@ Кореспонденцията продължава тук Тази стая е продължение от предишна кореспонденция Натиснете тук за да видите по-стари съобщения - - - - %d избран %d избрани - - Системни уведомления свържете се със администратора на услугата Сървърът е надвишил някой от лимитите си, така че някои потребители няма да успеят да влязат в профила си. @@ -660,7 +636,6 @@ ${app_name} не се влияе от Оптимизация на батерията. Ако потребител остави устройството неподвижно с изключен екран за известно време, то влиза в режим на заспиване. Това предотвратява приложенията да достъпват мрежата и отлага техните задачи, синхронизации и стандартни аларми. Игнорирай оптимизацията - Не беше открит валиден APK пакет за Google Play услугите. Уведомленията може да не работят правилно. В момента тече видео разговор… Резервно копие на ключовете @@ -697,7 +672,6 @@ Готово Запази ключа за възстановяване Запази като файл - Моля, направете копие Сподели ключа за възстановяване с… Генериране на ключ за възстановяване използвайки парола. Процесът може да отнеме няколко секунди. @@ -783,7 +757,6 @@ Алгоритъм Подпис За да използвате резервно копие на ключовете, възстановете с паролата или ключа за възстановяване. - Изчисляване на ключ за възстановяване… Изтегляне на ключове… Импортиране на ключове… @@ -791,7 +764,6 @@ Изпращай съобщения с Enter Enter бутонът на клавиатурата ще изпраща съобщение вместо да добавя нов ред Паролата не е валидна - Медия Компресия по подразбиране Избери @@ -829,8 +801,6 @@ Отхвърли Потвърдено! Разбрах - - Заявка за потвърждение %s иска да потвърди устройството Ви Неизвестна грешка @@ -927,7 +897,6 @@ Нищо Оттегли Прекъсни - Неуспешна връзка със сървъра на този адрес, моля проверете Режим на фонова синхронизация Пестящ батерия @@ -938,7 +907,6 @@ \nТова ще повлияе на използването на антената и батерията. Ще се показва перманентна нотификация, че ${app_name} слуша за събития. Без фонова синхронизация Няма да бъдете уведомени за входящи съобщения, когато приложението е във фонов режим. - Откриване Управлявайте настройките на откриваемостта. Не използвате сървър за самоличност @@ -1008,7 +976,6 @@ Съдържанието беше докладвано като неподходящо. \n \nАко не искате да виждате повече съдържание от този потребител, може да ги игнорирате за да скриете съобщенията им. - Това не е валиден адрес на Matrix сървър Интеграции Използвайте мениджър на интеграции за да управлявате ботове, връзки с други мрежи, приспособления и стикери. @@ -1298,7 +1265,6 @@ \nСъобщенията ви са защитени чрез заключване, и само вие и получателят имате уникалните ключове да го отключите. Съобщенията тук не са шифровани от-край-до-край. Съобщенията в тази стая не са шифровани от-край-до-край. - Изчакване на %s… Потвърден %s Потвърди %s @@ -1596,7 +1562,6 @@ Ако се откажете сега, може да загубите шифрованите съобщения и данни, в случай че загубите достъп до сесиите си. \n \nМоже също така да настроите защитено резервно копие и да управлявате ключовете си от Настройки. - Копирайте го в личното си облачно пространство Запазете го на USB флашка или резервен диск Принтирайте го и го съхранете на безопасно място @@ -1759,9 +1724,9 @@ • Сървърите съдържащи IP адреси ще бъдат блокирани. • Сървърите съдържащи IP адреси ще бъдат разрешени. • Сървърите съдържащи %s бяха премахнати от списъка с разрешени. - • Сървърите съдържащи %s ще бъдат разрешени. - "• Сървърите съдържащи %s бяха премахнати от списъка с блокирани." - "• Сървърите съдържащи %s ще бъдат блокирани." + • Сървърите съдържащи %s сега ще бъдат разрешени. + • Сървърите съдържащи %s бяха премахнати от списъка с блокирани. + • Сървърите съдържащи %s сега ще бъдат блокирани. Променихте сървърните разрешения (ACL) за тази стая. %s промени разрешенията (ACL) за тази стая. • Сървърите съдържащи IP адрес са блокирани. @@ -1770,4 +1735,6 @@ • Сървърите съдържащи %s са блокирани. Настроихте сървърните разрешения (ACL) за тази стая. %s настрой разрешенията (ACL) за тази стая. - + Първоначална заявка за синхронизация + Нямате права да се присъедините към тази стая + \ No newline at end of file From 40949aaf7e655111d91bf63a3dd88318302f0db2 Mon Sep 17 00:00:00 2001 From: Johan Smits Date: Sat, 9 Jul 2022 08:20:02 +0000 Subject: [PATCH 089/131] Translated using Weblate (Dutch) Currently translated at 100.0% (2260 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/nl/ --- vector/src/main/res/values-nl/strings.xml | 32 ++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/vector/src/main/res/values-nl/strings.xml b/vector/src/main/res/values-nl/strings.xml index 2ee0313c24..3c561a4bad 100644 --- a/vector/src/main/res/values-nl/strings.xml +++ b/vector/src/main/res/values-nl/strings.xml @@ -2500,4 +2500,34 @@ sec min u - + Locatie delen inschakelen + Let op: dit is een labfunctie met een tijdelijke implementatie. Dit betekent dat u uw locatiegeschiedenis niet kunt verwijderen en dat geavanceerde gebruikers uw locatiegeschiedenis kunnen zien, zelfs nadat u stopt met het delen van uw live locatie met deze ruimte. + Live locatie delen + Huidige gateway: %s + Gateway + Kan het eindpunt niet vinden. + Huidig eindpunt: %s + Eindpunt + Gebruikt momenteel %s. + Methode + + %d methode gevonden. + %d methoden gevonden. + + Geen andere methode dan achtergrondsynchronisatie gevonden. + Geen andere methode dan Google Play Service gevonden. + Beschikbare methoden + Meldingsmethode + Achtergrondsynchronisatie + Google Services + Kies hoe u meldingen wilt ontvangen + Kan biometrische authenticatie niet inschakelen. + Biometrische authenticatie is uitgeschakeld omdat er onlangs een nieuwe biometrische authenticatiemethode is toegevoegd. U kunt het weer inschakelen in Instellingen. + Meldingsmethode resetten + Profieltag: + Kan eindpunt token niet registreren op server: +\n%1$s + Eindpunt succesvol geregistreerd bij server. + Registratie van eindpunt + Volgende + \ No newline at end of file From b9b261a3a3178133163e5d7f5ee4490c578774d8 Mon Sep 17 00:00:00 2001 From: LinAGKar Date: Sat, 9 Jul 2022 19:29:12 +0000 Subject: [PATCH 090/131] Translated using Weblate (Swedish) Currently translated at 100.0% (2260 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sv/ --- vector/src/main/res/values-sv/strings.xml | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/vector/src/main/res/values-sv/strings.xml b/vector/src/main/res/values-sv/strings.xml index 845515def1..857f3b66ad 100644 --- a/vector/src/main/res/values-sv/strings.xml +++ b/vector/src/main/res/values-sv/strings.xml @@ -2501,4 +2501,33 @@ min t Nästa + Aktivera platsdelning + OBS: det här är en experimentell funktion som använder en temporär implementation. Det betyder att du inte kommer kunna radera din platshistorik, och avancerade användare kommer kunna se din platshistorik även efter att du slutar dela din realtidsplats med det här rummet. + Positionsdelning i realtid + Nuvarande gateway: %s + Gateway + Kan inte hitta ändpunkten. + Nuvarande ändpunkt: %s + Ändpunkt + Använder för närvarande %s. + Metod + + Hittade %d metod. + Hittade %d metoder. + + Ingen annan metod än bakgrundssynkronisering hittad. + Ingen annan metod än Google Play-tjänster hittad. + Tillgängliga metoder + Aviseringsmetod + Bakgrundssynkronisering + Googletjänster + Välj hur du vill ta emot aviseringar + Kunde inte aktivera biometrisk autentisering. + Biometrisk autentisering inaktiverades eftersom att en ny biometrisk autentiseringsmetod nyligen lades till. Du kan aktivera den igen i inställningarna. + Återställ aviseringsmetod + Profiltagg: + Misslyckades att registrera ändpunktstoken med hemservern: +\n%1$s + Lyckades registrera ändpunkten hos hemservern. + Ändpunktsregistrering \ No newline at end of file From b7b1a96bc2999c550903d32d1937fc0f1ae88a1c Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Fri, 8 Jul 2022 03:30:02 +0000 Subject: [PATCH 091/131] Translated using Weblate (Ukrainian) Currently translated at 100.0% (2260 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/uk/ --- vector/src/main/res/values-uk/strings.xml | 32 +++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/vector/src/main/res/values-uk/strings.xml b/vector/src/main/res/values-uk/strings.xml index 635594f505..957d759bc9 100644 --- a/vector/src/main/res/values-uk/strings.xml +++ b/vector/src/main/res/values-uk/strings.xml @@ -295,7 +295,7 @@ Copyright Політика приватності Очистити кеш - Очистити медіа кеш + Очистити медіакеш Зберігати медіа Налаштування користувача Сповіщення @@ -463,7 +463,7 @@ Попередній перегляд посилань Попередній перегляд медіа перед надсиланням - ${app_name} збирає анонімну аналітику, щоб ми могли вдосконалювати цей додаток. + ${app_name} збирає анонімну аналітику, щоб ми могли вдосконалювати цей застосунок. Будь ласка, створіть пароль для шифрування ключів що експортуються. Вам знадобиться ввести такий самий пароль для імпорту цих ключів. Створіть пароль Паролі мають збігатися @@ -499,7 +499,7 @@ Вилучити користувача із вказаним ID Змінити Ваш псевдонім Увімкнути/Вимкнути розмітку Markdown - Для виправлення керування додатками Matrix + Для виправлення керування застосунками Matrix Створити Домівка Кімнати @@ -1294,8 +1294,8 @@ QR-код Додати за QR-кодом Зазначте адресу сервера ідентифікації - В іншому разі, ви можете зазначити адресу будь-якого іншого сервера ідентифікації - Ваш домашній сервер (%1$s) пропонує використовувати %2$s як ваш сервер ідентифікації + Крім того, ви можете вказати URL-адресу будь-якого іншого сервера ідентифікації + Ваш домашній сервер (%1$s) пропонує використовувати %2$s вашим сервером ідентифікації Спочатку погодьтесь з умовами користування сервером ідентифікації в налаштуваннях. Спочатку налаштуйте сервер ідентифікації. Цей сервер ідентифікації є застарілим. ${app_name} підтримує лише API V2. @@ -1335,7 +1335,7 @@ Надсилання файлу (%1$s / %2$s) Шифрування файлу… Струс виявлено! - Потрясіть вашим пристроєм, щоб перевірити поріг чутливості + Струсніть пристроєм, щоб перевірити поріг чутливості Поріг чутливості Лютоcтрус Режим розробника вмикає приховані функції та може зробити застосунок менш стабільним. Лише для розробників! @@ -1347,9 +1347,9 @@ Неможливо під\'єднатись до сервера ідентифікації Зазначте адресу сервера ідентифікації Повторити - Від\'єднання від вашого сервера ідентифікації означатиме, що ви не будете виявними для інших користувачів та не зможете запрошувати інших через електронну пошту або номер телефону. - Ви наразі не використовуєте жодного сервера ідентифікації. Для того, щоб виявляти інших та бути виявним для знайомих вам наявних контактів, налаштуйте такий сервер нижче. - Ви зараз використовуєте %1$s для того, щоб виявляти інших та бути виявним для знайомих вам наявних контактів. + Від\'єднання від вашого сервера ідентифікації означатиме, що ви не будете виявними для інших користувачів і не зможете запрошувати інших електронною поштою або телефоном. + Наразі ви не використовуєте жодного сервера ідентифікації. Щоб виявляти інших і бути виявним для знайомих вам наявних контактів, налаштуйте сервер внизу. + Зараз ви використовуєте %1$s, щоб виявляти інших та бути виявним для знайомих вам наявних контактів. Змінити сервер ідентифікації Налаштувати сервер ідентифікації Від\'єднати сервер ідентифікації @@ -1617,8 +1617,8 @@ Застосувати типовим і більше не запитувати Завжди запитувати URL-адреса API домашнього сервера - Показати всі кімнати в каталозі кімнат, включно з кімнатами з делікатним вмістом. - Показати кімнати з делікатним вмістом + Показувати всі кімнати в каталозі кімнат, включно з кімнатами з делікатним вмістом. + Показувати кімнати з делікатним вмістом Каталог кімнат Пропоновані кімнати Нове значення @@ -1994,8 +1994,8 @@ Якщо ви не бачите особу, порівняйте натомість емоджі Ваш домен е-пошти не авторизовано для реєстрації на цьому сервері Заборонити будь-кому, хто не є учасником %s, будь-коли приєднуватися до цієї кімнати - Показати корисні дані для зневадження застосунку - Показати дані зневадження на екрані + Показувати корисні для зневадження застосунку дані + Показувати дані зневадження на екрані ${app_name} може частіше виходити з ладу, коли виникає несподівана помилка Швидкий збій Показано лише перші результати, введіть більше букв… @@ -2310,7 +2310,7 @@ %d ваших знайомих уже приєдналися %d ваших знайомих уже приєдналися - Зараз ви не використовуєте сервер ідентифікації. Налаштуйте його нижче, щоб запрошувати інших і щоб інші могли вас знаходити. + Зараз ви не використовуєте сервер ідентифікації. Налаштуйте його нижче, щоб запрошувати інших і щоб інші могли знаходити вас. Наразі тут лише ви. %s стане ще краще з іншими. Різне Створімо по кімнаті для кожної теми. Згодом ви зможете додати ще, зокрема створені раніше. @@ -2570,8 +2570,8 @@ \n \nЗауважте, що ця дія перезапустить застосунок, і це може тривати деякий час. Початковий запит синхронізації - Показати найновіші відомості про профіль (аватар і показуване ім\'я) для всіх повідомлень. - Показати найновіші відомості про користувача + Показувати найновіші дані профілю (аватар і показуване ім\'я) для всіх повідомлень. + Показувати найновіші дані користувача Зайнятий Резервна копія має дійсний підпис від цього користувача. Оновлено %1$s тому From 38904cc021575e2b89084a2045f23c4493b024ce Mon Sep 17 00:00:00 2001 From: LinAGKar Date: Fri, 8 Jul 2022 19:01:49 +0000 Subject: [PATCH 092/131] Translated using Weblate (Swedish) Currently translated at 100.0% (68 of 68 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/sv/ --- fastlane/metadata/android/sv-SE/changelogs/40104220.txt | 2 ++ fastlane/metadata/android/sv-SE/changelogs/40104230.txt | 2 ++ fastlane/metadata/android/sv-SE/changelogs/40104240.txt | 2 ++ fastlane/metadata/android/sv-SE/changelogs/40104250.txt | 2 ++ 4 files changed, 8 insertions(+) create mode 100644 fastlane/metadata/android/sv-SE/changelogs/40104220.txt create mode 100644 fastlane/metadata/android/sv-SE/changelogs/40104230.txt create mode 100644 fastlane/metadata/android/sv-SE/changelogs/40104240.txt create mode 100644 fastlane/metadata/android/sv-SE/changelogs/40104250.txt diff --git a/fastlane/metadata/android/sv-SE/changelogs/40104220.txt b/fastlane/metadata/android/sv-SE/changelogs/40104220.txt new file mode 100644 index 0000000000..d8db452b51 --- /dev/null +++ b/fastlane/metadata/android/sv-SE/changelogs/40104220.txt @@ -0,0 +1,2 @@ +Huvudsakliga ändringar i den här versionen: Diverse buggfixar och stabilitetsförbättringar. +Full ändringslogg: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/sv-SE/changelogs/40104230.txt b/fastlane/metadata/android/sv-SE/changelogs/40104230.txt new file mode 100644 index 0000000000..d8db452b51 --- /dev/null +++ b/fastlane/metadata/android/sv-SE/changelogs/40104230.txt @@ -0,0 +1,2 @@ +Huvudsakliga ändringar i den här versionen: Diverse buggfixar och stabilitetsförbättringar. +Full ändringslogg: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/sv-SE/changelogs/40104240.txt b/fastlane/metadata/android/sv-SE/changelogs/40104240.txt new file mode 100644 index 0000000000..d8db452b51 --- /dev/null +++ b/fastlane/metadata/android/sv-SE/changelogs/40104240.txt @@ -0,0 +1,2 @@ +Huvudsakliga ändringar i den här versionen: Diverse buggfixar och stabilitetsförbättringar. +Full ändringslogg: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/sv-SE/changelogs/40104250.txt b/fastlane/metadata/android/sv-SE/changelogs/40104250.txt new file mode 100644 index 0000000000..d8db452b51 --- /dev/null +++ b/fastlane/metadata/android/sv-SE/changelogs/40104250.txt @@ -0,0 +1,2 @@ +Huvudsakliga ändringar i den här versionen: Diverse buggfixar och stabilitetsförbättringar. +Full ändringslogg: https://github.com/vector-im/element-android/releases From 1fd0fe504df84e5e157a373ff7e725751f6b8a20 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 11 Jul 2022 12:37:35 +0200 Subject: [PATCH 093/131] Format file --- .github/workflows/quality.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index e4b06a6348..0171831c18 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -21,7 +21,7 @@ jobs: - name: Run code quality check suite run: ./tools/check/check_code_quality.sh -# Knit for all the modules (https://github.com/Kotlin/kotlinx-knit) + # Knit for all the modules (https://github.com/Kotlin/kotlinx-knit) knit: name: Knit runs-on: ubuntu-latest @@ -31,7 +31,7 @@ jobs: run: | ./gradlew knit -# ktlint for all the modules + # ktlint for all the modules ktlint: name: Kotlin Linter runs-on: ubuntu-latest @@ -104,7 +104,7 @@ jobs: comment_id: ${{ steps.fc.outputs.comment-id }} }) -# Gradle dependency analysis using https://github.com/autonomousapps/dependency-analysis-android-gradle-plugin + # Gradle dependency analysis using https://github.com/autonomousapps/dependency-analysis-android-gradle-plugin dependency-analysis: name: Dependency analysis runs-on: ubuntu-latest @@ -123,7 +123,7 @@ jobs: name: dependency-analysis path: build/reports/dependency-check-report.html -# Lint for main module + # Lint for main module android-lint: name: Android Linter runs-on: ubuntu-latest @@ -151,7 +151,7 @@ jobs: path: | vector/build/reports/*.* -# Lint for Gplay and Fdroid release APK + # Lint for Gplay and Fdroid release APK apk-lint: name: Lint APK (${{ matrix.target }}) runs-on: ubuntu-latest From 63419fcf5e652f8e2b5a362be087093dd0e4601e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 11 Jul 2022 12:38:45 +0200 Subject: [PATCH 094/131] Do the check on towncrier only for PR targeting develop branch --- .github/workflows/quality.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 0171831c18..b971dfc1e4 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -207,6 +207,7 @@ jobs: towncrier: name: Towncrier check runs-on: ubuntu-latest + if: github.head_ref == 'develop' steps: - uses: actions/checkout@v3 - name: Set up Python 3.8 From 6feca4badf939353fab736bcf173cb684e28e854 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 11 Jul 2022 12:41:17 +0200 Subject: [PATCH 095/131] Indentation, move comment above the block. --- .github/workflows/quality.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index b971dfc1e4..f90a99a24b 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -218,12 +218,12 @@ jobs: run: | python3 -m pip install towncrier - name: Run towncrier - run: | # Fetch the pull request' base branch so towncrier will be able to # compare the current branch with the base branch. # Source: https://github.com/actions/checkout/#fetch-all-branches. - git fetch --no-tags origin +refs/heads/${BASE_BRANCH}:refs/remotes/origin/${BASE_BRANCH} - towncrier check --compare-with origin/${BASE_BRANCH} + run: | + git fetch --no-tags origin +refs/heads/${BASE_BRANCH}:refs/remotes/origin/${BASE_BRANCH} + towncrier check --compare-with origin/${BASE_BRANCH} env: BASE_BRANCH: ${{ github.base_ref }} if: github.event_name == 'pull_request' From 10796f1fa0c3d8d31c4b9cd7eb7c6b2e33301ee4 Mon Sep 17 00:00:00 2001 From: Ultimator14 Date: Mon, 11 Jul 2022 07:00:57 +0000 Subject: [PATCH 096/131] Translated using Weblate (German) Currently translated at 99.6% (2251 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/de/ --- vector/src/main/res/values-de/strings.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vector/src/main/res/values-de/strings.xml b/vector/src/main/res/values-de/strings.xml index 10e8d1b58b..c1c3c42b03 100644 --- a/vector/src/main/res/values-de/strings.xml +++ b/vector/src/main/res/values-de/strings.xml @@ -2421,4 +2421,5 @@ Threads Beta Bildschirm teilen Ausprobieren - + Live bis %1$s + \ No newline at end of file From 6ab746d8be2f0d3a7c87da4d9c1c85bc7c8c4eed Mon Sep 17 00:00:00 2001 From: Coruna Date: Sun, 10 Jul 2022 11:26:39 +0000 Subject: [PATCH 097/131] Translated using Weblate (German) Currently translated at 99.6% (2251 of 2260 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/de/ --- vector/src/main/res/values-de/strings.xml | 113 +++++++++++++++++++++- 1 file changed, 110 insertions(+), 3 deletions(-) diff --git a/vector/src/main/res/values-de/strings.xml b/vector/src/main/res/values-de/strings.xml index c1c3c42b03..dce916514a 100644 --- a/vector/src/main/res/values-de/strings.xml +++ b/vector/src/main/res/values-de/strings.xml @@ -607,7 +607,7 @@ aufklappen zusammenklappen %1$s: %2$s - %d+ + +%d Entfernen Linkvorschau im Chat aktivieren, falls dein Homeserver diese Funktion unterstützt. Schreibbenachrichtigungen senden @@ -2215,7 +2215,7 @@ \nUm sie für immer zu entfernen, solltest du sie bannen. Aufnahme beenden Einrichtung beenden - Nicht stören + Nicht da Offline Online %1$s Klicke zum Zurückkehren @@ -2278,7 +2278,7 @@ hier Hilf mit, ${app_name} zu verbessern Aktivieren - Farbe des Nicknamens ändern + Farbe des Anzeigenamens ändern Du hast die volle Kontrolle. Du hast nicht die Berechtigung um diesen Raum zu betreten @@ -2422,4 +2422,111 @@ Bildschirm teilen Ausprobieren Live bis %1$s + Wähle Deine Benachrichtigungsmethode + Vorläufige Implementierung: Standorte bleiben im Nachrichtenverlauf von Räumen erhalten + Profil-Tag: + h + Standortfreigabe aktivieren + Bitte beachten: Dies ist eine Testfunktion mit einer vorübergehenden Implementierung. Das bedeutet, dass Du Deinen Standortverlauf nicht löschen kannst und dass fortgeschrittene Nutzer Deinen Standortverlauf auch dann noch sehen können, wenn Du Deinen Live-Standort nicht mehr mit diesem Raum teilst. + Live-Standortfreigabe + Aktuelles Gateway: %s + Gateway + Kann den Endpunkt nicht finden. + Aktueller Endpunkt: %s + Endpunkt + Derzeit wird %s verwendet. + Methode + + %d Methode gefunden. + %d Methoden gefunden. + + Keine andere Methode als die Hintergrund-Synchronisation gefunden. + Keine andere Methode als Google Play Service gefunden. + Verfügbare Methoden + Benachrichtigungsmethode + Hintergrund-Synchronisation + Google Services + Bildschirmfreigabe ist in Arbeit + ${app_name} Bildschirmfreigabe + Aktualisiert vor %1$s + Teilen beenden + Aktiviere Live-Standortfreigabe + Standortfreigabe ist in Arbeit + ${app_name} Live-Standort + %1$s übrig + Live-Standort anzeigen + Live-Standort beendet + Live-Standort laden… + 8 Stunden + 1 Stunde + 15 Minuten + Teile Deinen Live-Standort für + Auf aktuellen Standort zoomen + Pin des ausgewählten Ortes auf der Karte + (%1$s) + %1$s (%2$s) + Kann %1$s nicht abspielen + Pausieren %1$s + Abspielen %1$s + %1$d Minuten %2$d Sekunden + %1$s, %2$s, %3$s + Die neuesten Profilinformationen (Avatar und Anzeigename) für alle Nachrichten anzeigen. + Aktuelle Benutzerinformationen anzeigen + Du kannst loslegen! + einen Anzeigenamen wählen + Zurück zum Home-Screen + Threads Beta-Feedback + Benachrichtigungsmethode zurücksetzen + ${app_name} muss aus folgendem Grund eine Cache-Löschung durchführen, um auf dem neuesten Stand zu bleiben: +\n%s +\n +\nDiese Aktion wird die Anwendung neu starten und einige Zeit dauern. + Die Sicherung hat eine gültige Signatur von diesem Benutzer. + Wenn diese Option aktiviert ist, wirst Du anderen Nutzer:innen immer als offline angezeigt, auch wenn Du die Anwendung verwendest. + Offline Modus + Präsenz + Animierte Bilder in der Zeitleiste abspielen, sobald sie sichtbar sind + Animierte Bilder automatisch abspielen + Das Endpunkt-Token konnte nicht auf dem Heimserver registriert werden: +\n%1$s + Endpunkt erfolgreich beim Heimserver registriert. + Endpunkt-Registrierung + Dein Heimserver unterstützt derzeit keine Threads, daher kann diese Funktion evtl. nicht richtig funktionieren. Einige Nachrichten mit Threads sind möglicherweise nicht zuverlässig verfügbar. %sMöchtest Du Threads trotzdem aktivieren\? + Threads helfen dabei, Unterhaltungen beim Thema zu halten und leichter zu verfolgen. %sDie Aktivierung von Threads aktualisiert die App. Dies kann bei einigen Konten länger dauern. + Wir nähern uns der Veröffentlichung einer öffentlichen Beta für Threads. +\n +\nIn Vorbereitung darauf müssen wir einige Änderungen vornehmen: Threads, die vor diesem Zeitpunkt erstellt wurden, werden als normale Antworten angezeigt. +\n +\nDies wird ein einmaliger Übergang sein, da Threads nun Teil der Matrix-Spezifikation sind. + Bildschirmfreigabe beenden + Weiter + Mehr erfahren + sek + min + - das Ignorieren einiger Benutzer:innen wurde rückgängig gemacht + Initiale Synchronisierungsanfrage + Einige Ergebnisse werden möglicherweise ausgeblendet, weil sie privat sind und Du eine Einladung benötigst, um sie zu sehen. + Keine Ergebnisse gefunden + Nichts verlassen + Alles verlassen + Dinge in diesem Space + Beschäftigt + Die biometrische Authentifizierung konnte nicht aktiviert werden. + Die biometrische Authentifizierung wurde deaktiviert, weil kürzlich eine neue biometrische Authentifizierungsmethode hinzugefügt wurde. Du kannst sie in den Einstellungen wieder aktivieren. + Der Heimserver akzeptiert keine Benutzernamen, die nur aus Ziffern bestehen. + teilten ihren Live-Standort + Schritt überspringen + Speichern und fortfahren + Deine Einstellungen wurden gespeichert. + Los geht\'s + Du kannst das jederzeit ändern. + Profilbild hinzufügen + Du kannst dies später ändern + Anzeigename + Dies wird angezeigt, wenn Du Nachrichten sendest. + Dein Konto %s wurde erstellt. + Herzlichen Glückwunsch! + Profil personalisieren + ${app_name} ist auch für den Arbeitsplatz geeignet. Die sichersten Organisationen der Welt vertrauen darauf. + Threads sind noch in Arbeit, und es stehen neue, aufregende Funktionen an, wie z. B. verbesserte Benachrichtigungen. Wir würden uns sehr über Dein Feedback freuen! \ No newline at end of file From a69c1fa584d68d05236640919820205c0c7041aa Mon Sep 17 00:00:00 2001 From: Coruna Date: Sun, 10 Jul 2022 11:06:27 +0000 Subject: [PATCH 098/131] Translated using Weblate (German) Currently translated at 100.0% (68 of 68 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/de/ --- fastlane/metadata/android/de-DE/changelogs/40104140.txt | 2 ++ fastlane/metadata/android/de-DE/changelogs/40104160.txt | 2 ++ fastlane/metadata/android/de-DE/changelogs/40104180.txt | 2 ++ fastlane/metadata/android/de-DE/changelogs/40104190.txt | 2 ++ fastlane/metadata/android/de-DE/changelogs/40104200.txt | 2 ++ fastlane/metadata/android/de-DE/changelogs/40104220.txt | 2 ++ fastlane/metadata/android/de-DE/changelogs/40104230.txt | 2 ++ fastlane/metadata/android/de-DE/changelogs/40104240.txt | 2 ++ fastlane/metadata/android/de-DE/changelogs/40104250.txt | 2 ++ 9 files changed, 18 insertions(+) create mode 100644 fastlane/metadata/android/de-DE/changelogs/40104140.txt create mode 100644 fastlane/metadata/android/de-DE/changelogs/40104160.txt create mode 100644 fastlane/metadata/android/de-DE/changelogs/40104180.txt create mode 100644 fastlane/metadata/android/de-DE/changelogs/40104190.txt create mode 100644 fastlane/metadata/android/de-DE/changelogs/40104200.txt create mode 100644 fastlane/metadata/android/de-DE/changelogs/40104220.txt create mode 100644 fastlane/metadata/android/de-DE/changelogs/40104230.txt create mode 100644 fastlane/metadata/android/de-DE/changelogs/40104240.txt create mode 100644 fastlane/metadata/android/de-DE/changelogs/40104250.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/40104140.txt b/fastlane/metadata/android/de-DE/changelogs/40104140.txt new file mode 100644 index 0000000000..3915434ee0 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/40104140.txt @@ -0,0 +1,2 @@ +Die wichtigsten Änderungen in dieser Version: Verbesserte Verwaltung der ignorierten Benutzer:innen. Verschiedene Fehlerbehebungen und Stabilitätsverbesserungen. +Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/de-DE/changelogs/40104160.txt b/fastlane/metadata/android/de-DE/changelogs/40104160.txt new file mode 100644 index 0000000000..cdf06e217a --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/40104160.txt @@ -0,0 +1,2 @@ +Die wichtigsten Änderungen in dieser Version: Bessere Verwaltung von verschlüsselten Nachrichten. Verschiedene Fehlerbehebungen und Stabilitätsverbesserungen. +Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/de-DE/changelogs/40104180.txt b/fastlane/metadata/android/de-DE/changelogs/40104180.txt new file mode 100644 index 0000000000..50b5647608 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/40104180.txt @@ -0,0 +1,2 @@ +Die wichtigsten Änderungen in dieser Version: Verschiedene Fehlerbehebungen und Stabilitätsverbesserungen. +Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/de-DE/changelogs/40104190.txt b/fastlane/metadata/android/de-DE/changelogs/40104190.txt new file mode 100644 index 0000000000..50b5647608 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/40104190.txt @@ -0,0 +1,2 @@ +Die wichtigsten Änderungen in dieser Version: Verschiedene Fehlerbehebungen und Stabilitätsverbesserungen. +Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/de-DE/changelogs/40104200.txt b/fastlane/metadata/android/de-DE/changelogs/40104200.txt new file mode 100644 index 0000000000..50b5647608 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/40104200.txt @@ -0,0 +1,2 @@ +Die wichtigsten Änderungen in dieser Version: Verschiedene Fehlerbehebungen und Stabilitätsverbesserungen. +Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/de-DE/changelogs/40104220.txt b/fastlane/metadata/android/de-DE/changelogs/40104220.txt new file mode 100644 index 0000000000..50b5647608 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/40104220.txt @@ -0,0 +1,2 @@ +Die wichtigsten Änderungen in dieser Version: Verschiedene Fehlerbehebungen und Stabilitätsverbesserungen. +Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/de-DE/changelogs/40104230.txt b/fastlane/metadata/android/de-DE/changelogs/40104230.txt new file mode 100644 index 0000000000..50b5647608 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/40104230.txt @@ -0,0 +1,2 @@ +Die wichtigsten Änderungen in dieser Version: Verschiedene Fehlerbehebungen und Stabilitätsverbesserungen. +Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/de-DE/changelogs/40104240.txt b/fastlane/metadata/android/de-DE/changelogs/40104240.txt new file mode 100644 index 0000000000..50b5647608 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/40104240.txt @@ -0,0 +1,2 @@ +Die wichtigsten Änderungen in dieser Version: Verschiedene Fehlerbehebungen und Stabilitätsverbesserungen. +Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/de-DE/changelogs/40104250.txt b/fastlane/metadata/android/de-DE/changelogs/40104250.txt new file mode 100644 index 0000000000..50b5647608 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/40104250.txt @@ -0,0 +1,2 @@ +Die wichtigsten Änderungen in dieser Version: Verschiedene Fehlerbehebungen und Stabilitätsverbesserungen. +Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases From fb87d31ce479124a8cfcbeba109ae42d9e56fe1c Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Mon, 11 Jul 2022 15:24:48 +0200 Subject: [PATCH 099/131] Update the title of the local room timeline --- .../im/vector/app/features/home/room/detail/TimelineFragment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt index d327bb48d4..25947cc22b 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt @@ -1709,7 +1709,7 @@ class TimelineFragment @Inject constructor( views.includeRoomToolbar.roomToolbarContentView.isVisible = false views.includeThreadToolbar.roomToolbarThreadConstraintLayout.isVisible = false setupToolbar(views.roomToolbar) - .setTitle(R.string.fab_menu_create_chat) + .setTitle(R.string.room_member_open_or_create_dm) .allowBack(useCross = true) } isThreadTimeLine() -> { From a10a8ce5ca8571e04fd11cef97b86560a06a0ab2 Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Mon, 11 Jul 2022 16:19:27 +0200 Subject: [PATCH 100/131] Add margin after the action button of the user list toolbar --- vector/src/main/res/layout/fragment_user_list.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/vector/src/main/res/layout/fragment_user_list.xml b/vector/src/main/res/layout/fragment_user_list.xml index b3149f05c5..989cb2feef 100644 --- a/vector/src/main/res/layout/fragment_user_list.xml +++ b/vector/src/main/res/layout/fragment_user_list.xml @@ -15,7 +15,9 @@ android:id="@+id/userListToolbar" android:layout_width="match_parent" android:layout_height="?actionBarSize" - app:title="@string/fab_menu_create_chat"/> + android:paddingEnd="@dimen/layout_horizontal_margin" + app:title="@string/fab_menu_create_chat" + tools:ignore="RtlSymmetry" /> @@ -94,4 +96,4 @@ app:layout_constraintTop_toBottomOf="@id/userListE2EbyDefaultDisabled" tools:listitem="@layout/item_known_user" /> - \ No newline at end of file + From fdb9ed80d4955a28b35aa708e39258edcbf5b588 Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Mon, 11 Jul 2022 16:22:49 +0200 Subject: [PATCH 101/131] Change method visibility --- .../sdk/api/session/room/model/localecho/RoomLocalEcho.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/localecho/RoomLocalEcho.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/localecho/RoomLocalEcho.kt index e48baff5a2..7ef0d63924 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/localecho/RoomLocalEcho.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/localecho/RoomLocalEcho.kt @@ -22,7 +22,10 @@ object RoomLocalEcho { private const val PREFIX = "!local." + /** + * Tell whether the provider room id is a local id. + */ fun isLocalEchoId(roomId: String) = roomId.startsWith(PREFIX) - fun createLocalEchoId() = "${PREFIX}${UUID.randomUUID()}" + internal fun createLocalEchoId() = "${PREFIX}${UUID.randomUUID()}" } From fca4df352253a8feddc5d590771038c293ad9b10 Mon Sep 17 00:00:00 2001 From: Florian Renaud Date: Mon, 11 Jul 2022 16:44:32 +0200 Subject: [PATCH 102/131] Revert "Ensure that Realm is up to date before returning the roomId" This reverts commit 8a5a47c6a57863b87f62ca2e123fe619d1d9b612. --- .../room/create/CreateLocalRoomTask.kt | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt index 94c300c3c3..d57491a4c8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomTask.kt @@ -18,7 +18,9 @@ package org.matrix.android.sdk.internal.session.room.create import com.zhuinden.monarchy.Monarchy import io.realm.Realm +import io.realm.RealmConfiguration import io.realm.kotlin.createObject +import kotlinx.coroutines.TimeoutCancellationException import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.events.model.Content @@ -26,6 +28,7 @@ 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.events.model.LocalEcho import org.matrix.android.sdk.api.session.events.model.toContent +import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure import org.matrix.android.sdk.api.session.room.model.GuestAccess import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility @@ -38,6 +41,7 @@ import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.sync.model.RoomSyncSummary import org.matrix.android.sdk.api.session.user.UserService import org.matrix.android.sdk.api.session.user.model.User +import org.matrix.android.sdk.internal.database.awaitNotEmptyResult import org.matrix.android.sdk.internal.database.helper.addTimelineEvent import org.matrix.android.sdk.internal.database.mapper.asDomain import org.matrix.android.sdk.internal.database.mapper.toEntity @@ -47,6 +51,7 @@ import org.matrix.android.sdk.internal.database.model.EventInsertType import org.matrix.android.sdk.internal.database.model.RoomEntity import org.matrix.android.sdk.internal.database.model.RoomMembersLoadStatusType import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity +import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields import org.matrix.android.sdk.internal.database.query.copyToRealmOrIgnore import org.matrix.android.sdk.internal.database.query.getOrCreate import org.matrix.android.sdk.internal.database.query.getOrNull @@ -59,6 +64,7 @@ import org.matrix.android.sdk.internal.session.room.timeline.PaginationDirection import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction import org.matrix.android.sdk.internal.util.time.Clock +import java.util.concurrent.TimeUnit import javax.inject.Inject internal interface CreateLocalRoomTask : Task @@ -68,6 +74,7 @@ internal class DefaultCreateLocalRoomTask @Inject constructor( @SessionDatabase private val monarchy: Monarchy, private val roomMemberEventHandler: RoomMemberEventHandler, private val roomSummaryUpdater: RoomSummaryUpdater, + @SessionDatabase private val realmConfiguration: RealmConfiguration, private val createRoomBodyBuilder: CreateRoomBodyBuilder, private val userService: UserService, private val clock: Clock, @@ -81,8 +88,16 @@ internal class DefaultCreateLocalRoomTask @Inject constructor( createLocalRoomSummaryEntity(realm, roomId, createRoomBody) } - // Ensure that Realm is up to date before returning the roomId. - monarchy.doWithRealm { it.refresh() } + // Wait for room to be created in DB + try { + awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm -> + realm.where(RoomSummaryEntity::class.java) + .equalTo(RoomSummaryEntityFields.ROOM_ID, roomId) + .equalTo(RoomSummaryEntityFields.MEMBERSHIP_STR, Membership.JOIN.name) + } + } catch (exception: TimeoutCancellationException) { + throw CreateRoomFailure.CreatedWithTimeout(roomId) + } return roomId } From a7ed2114be195678ed0c43ab0db8d5be17bdf0ac Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 11 Jul 2022 17:00:17 +0200 Subject: [PATCH 103/131] io.element.android:opusencoder:1.0.3 - should fix lint false positive issues --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 1f91f20f0d..e5a0c53294 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -97,7 +97,7 @@ ext.libs = [ 'flipperNetworkPlugin' : "com.facebook.flipper:flipper-network-plugin:$flipper", ], element : [ - 'opusencoder' : "io.element.android:opusencoder:1.0.1", + 'opusencoder' : "io.element.android:opusencoder:1.0.3", ], squareup : [ 'moshi' : "com.squareup.moshi:moshi:$moshi", From d524f1a7d445768512337e07249a386b8c7aa1b1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 11 Jul 2022 17:03:09 +0200 Subject: [PATCH 104/131] Group if together --- .github/workflows/quality.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index f90a99a24b..21d974602f 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -207,7 +207,7 @@ jobs: towncrier: name: Towncrier check runs-on: ubuntu-latest - if: github.head_ref == 'develop' + if: github.event_name == 'pull_request' && github.head_ref == 'develop' steps: - uses: actions/checkout@v3 - name: Set up Python 3.8 @@ -226,4 +226,3 @@ jobs: towncrier check --compare-with origin/${BASE_BRANCH} env: BASE_BRANCH: ${{ github.base_ref }} - if: github.event_name == 'pull_request' From 7ab7d7cc8038187c6258f09d675d8570d724171b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 12 Jul 2022 10:29:49 +0200 Subject: [PATCH 105/131] Comment the GHA towncrier, there is a syntax error --- .github/workflows/quality.yml | 44 +++++++++++++++++------------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 21d974602f..8bc5efe860 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -204,25 +204,25 @@ jobs: path: | */build/reports/detekt/detekt.html - towncrier: - name: Towncrier check - runs-on: ubuntu-latest - if: github.event_name == 'pull_request' && github.head_ref == 'develop' - steps: - - uses: actions/checkout@v3 - - name: Set up Python 3.8 - uses: actions/setup-python@v4 - with: - python-version: 3.8 - - name: Install towncrier - run: | - python3 -m pip install towncrier - - name: Run towncrier - # Fetch the pull request' base branch so towncrier will be able to - # compare the current branch with the base branch. - # Source: https://github.com/actions/checkout/#fetch-all-branches. - run: | - git fetch --no-tags origin +refs/heads/${BASE_BRANCH}:refs/remotes/origin/${BASE_BRANCH} - towncrier check --compare-with origin/${BASE_BRANCH} - env: - BASE_BRANCH: ${{ github.base_ref }} +# towncrier: +# name: Towncrier check +# runs-on: ubuntu-latest +# if: github.event_name == 'pull_request' && github.head_ref == 'develop' +# steps: +# - uses: actions/checkout@v3 +# - name: Set up Python 3.8 +# uses: actions/setup-python@v4 +# with: +# python-version: 3.8 +# - name: Install towncrier +# run: | +# python3 -m pip install towncrier +# - name: Run towncrier +# # Fetch the pull request' base branch so towncrier will be able to +# # compare the current branch with the base branch. +# # Source: https://github.com/actions/checkout/#fetch-all-branches. +# run: | +# git fetch --no-tags origin +refs/heads/${BASE_BRANCH}:refs/remotes/origin/${BASE_BRANCH} +# towncrier check --compare-with origin/${BASE_BRANCH} +# env: +# BASE_BRANCH: ${{ github.base_ref }} From 6266b2019b01c725299a5d0c6cd02b5249a686ad Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 12 Jul 2022 09:57:48 +0100 Subject: [PATCH 106/131] removing legacy migration flag from 12 months ago --- .../features/settings/VectorPreferences.kt | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index 2215bb8a4f..7bee66d722 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -158,7 +158,6 @@ class VectorPreferences @Inject constructor( private const val SETTINGS_ENABLE_SEND_VOICE_FEATURE_PREFERENCE_KEY = "SETTINGS_ENABLE_SEND_VOICE_FEATURE_PREFERENCE_KEY" const val SETTINGS_LABS_ALLOW_EXTENDED_LOGS = "SETTINGS_LABS_ALLOW_EXTENDED_LOGS" - const val SETTINGS_LABS_SPACES_HOME_AS_ORPHAN = "SETTINGS_LABS_SPACES_HOME_AS_ORPHAN" const val SETTINGS_LABS_AUTO_REPORT_UISI = "SETTINGS_LABS_AUTO_REPORT_UISI" const val SETTINGS_PREF_SPACE_SHOW_ALL_ROOM_IN_HOME = "SETTINGS_PREF_SPACE_SHOW_ALL_ROOM_IN_HOME" @@ -1025,27 +1024,7 @@ class VectorPreferences @Inject constructor( } fun prefSpacesShowAllRoomInHome(): Boolean { - val defaultValue = false - return when { - defaultPrefs.contains(SETTINGS_PREF_SPACE_SHOW_ALL_ROOM_IN_HOME) -> { - defaultPrefs.getBoolean(SETTINGS_PREF_SPACE_SHOW_ALL_ROOM_IN_HOME, defaultValue) - } - defaultPrefs.contains(SETTINGS_LABS_SPACES_HOME_AS_ORPHAN) -> migrateOrphansInSpacesToShowAllInHome() - else -> defaultValue - } - } - - private fun migrateOrphansInSpacesToShowAllInHome(): Boolean { - val showAllRoomsInHome = !labsSpacesOnlyOrphansInHome() - defaultPrefs.edit { - putBoolean(SETTINGS_PREF_SPACE_SHOW_ALL_ROOM_IN_HOME, showAllRoomsInHome) - remove(SETTINGS_LABS_SPACES_HOME_AS_ORPHAN) - } - return showAllRoomsInHome - } - - private fun labsSpacesOnlyOrphansInHome(): Boolean { - return defaultPrefs.getBoolean(SETTINGS_LABS_SPACES_HOME_AS_ORPHAN, false) + return defaultPrefs.getBoolean(SETTINGS_PREF_SPACE_SHOW_ALL_ROOM_IN_HOME, false) } /* From 8db704f3b9c9ad9796c7271a66671ecfb505d592 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Fri, 8 Jul 2022 12:04:12 +0100 Subject: [PATCH 107/131] naming the threads room creation to avoid multiple rooms with empty room as the name, causing ambiguous assertion errors --- .../im/vector/app/ui/UiAllScreensSanityTest.kt | 2 +- .../im/vector/app/ui/robot/CreateNewRoomRobot.kt | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt b/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt index 4333558e7a..09980f405e 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt @@ -159,7 +159,7 @@ class UiAllScreensSanityTest { elementRobot.newRoom { createNewRoom { crawl() - createRoom { + createRoom(roomName = "thread room") { val message = "Hello This message will be a thread!" postMessage(message) replyToThread(message) diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/CreateNewRoomRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/CreateNewRoomRobot.kt index 505dfb33e9..743d16bbd8 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/robot/CreateNewRoomRobot.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/robot/CreateNewRoomRobot.kt @@ -16,8 +16,15 @@ package im.vector.app.ui.robot +import androidx.test.espresso.Espresso.closeSoftKeyboard +import androidx.test.espresso.Espresso.onData +import androidx.test.espresso.Espresso.onView import androidx.test.espresso.Espresso.pressBack +import androidx.test.espresso.action.ViewActions.replaceText +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.withHint import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText import com.adevinta.android.barista.assertion.BaristaListAssertions import com.adevinta.android.barista.interaction.BaristaClickInteractions import com.adevinta.android.barista.interaction.BaristaListInteractions @@ -25,14 +32,20 @@ import im.vector.app.R import im.vector.app.espresso.tools.waitUntilActivityVisible import im.vector.app.espresso.tools.waitUntilViewVisible import im.vector.app.features.home.room.detail.RoomDetailActivity +import org.hamcrest.CoreMatchers.allOf class CreateNewRoomRobot( var createdRoom: Boolean = false ) { - fun createRoom(block: RoomDetailRobot.() -> Unit) { + fun createRoom(roomName: String? = null, block: RoomDetailRobot.() -> Unit) { createdRoom = true BaristaListAssertions.assertListItemCount(R.id.createRoomForm, 12) + roomName?.let { + onView(allOf(withId(R.id.formTextInputTextInputEditText), withHint(R.string.create_room_name_hint))) + .perform(replaceText(roomName)) + closeSoftKeyboard() + } BaristaListInteractions.clickListItemChild(R.id.createRoomForm, 11, R.id.form_submit_button) waitUntilActivityVisible { waitUntilViewVisible(withId(R.id.composerEditText)) From c7efd8a6f6eb4f52b7da39e7515f3371958da940 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Fri, 8 Jul 2022 12:05:44 +0100 Subject: [PATCH 108/131] always attempting to close the keyboard to help avoid can't inject events error --- .../androidTest/java/im/vector/app/ui/robot/ElementRobot.kt | 4 ++-- .../java/im/vector/app/ui/robot/MessageMenuRobot.kt | 2 ++ .../java/im/vector/app/ui/robot/RoomDetailRobot.kt | 4 ++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt index 35027843d6..3b54a8607b 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt @@ -17,6 +17,7 @@ package im.vector.app.ui.robot import android.view.View +import androidx.test.espresso.Espresso.closeSoftKeyboard import androidx.test.espresso.Espresso.onView import androidx.test.espresso.Espresso.pressBack import androidx.test.espresso.action.ViewActions @@ -91,8 +92,7 @@ class ElementRobot { waitUntilActivityVisible { waitUntilViewVisible(withId(R.id.userListSearch)) } - // close keyboard - pressBack() + closeSoftKeyboard() block(NewDirectMessageRobot()) pressBack() waitUntilViewVisible(withId(R.id.bottomNavigationView)) diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/MessageMenuRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/MessageMenuRobot.kt index 53ad2af7e6..01a9ec02dc 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/robot/MessageMenuRobot.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/robot/MessageMenuRobot.kt @@ -16,6 +16,7 @@ package im.vector.app.ui.robot +import androidx.test.espresso.Espresso.closeSoftKeyboard import androidx.test.espresso.Espresso.pressBack import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText @@ -59,6 +60,7 @@ class MessageMenuRobot( clickOn(R.string.message_add_reaction) // Wait for emoji to load, it's async now waitUntilActivityVisible { + closeSoftKeyboard() waitUntilViewVisible(withId(R.id.emojiRecyclerView)) waitUntilViewVisible(withText("😀")) } diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt index 91409582d9..a123484087 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt @@ -17,6 +17,7 @@ package im.vector.app.ui.robot import androidx.recyclerview.widget.RecyclerView +import androidx.test.espresso.Espresso.closeSoftKeyboard import androidx.test.espresso.Espresso.onView import androidx.test.espresso.Espresso.pressBack import androidx.test.espresso.action.ViewActions @@ -44,6 +45,7 @@ class RoomDetailRobot { fun postMessage(content: String) { writeTo(R.id.composerEditText, content) + closeSoftKeyboard() waitUntilViewVisible(withId(R.id.sendButton)) clickOn(R.id.sendButton) waitUntilViewVisible(withText(content)) @@ -68,6 +70,7 @@ class RoomDetailRobot { } val threadMessage = "Hello universe - long message to avoid espresso tapping edited!" writeTo(R.id.composerEditText, threadMessage) + closeSoftKeyboard() waitUntilViewVisible(withId(R.id.sendButton)) clickOn(R.id.sendButton) } @@ -105,6 +108,7 @@ class RoomDetailRobot { // TODO Cancel action val edit = "Hello universe - long message to avoid espresso tapping edited!" writeTo(R.id.composerEditText, edit) + closeSoftKeyboard() // Wait a bit for the keyboard layout to update waitUntilViewVisible(withId(R.id.sendButton)) clickOn(R.id.sendButton) From f501555ff93c35b2d07ff43aa6ad9f14f1cb40b0 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Fri, 8 Jul 2022 12:06:43 +0100 Subject: [PATCH 109/131] adding extra waits for the threads list to appear as it seems to be inconsistent --- .../java/im/vector/app/ui/robot/RoomDetailRobot.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt index a123484087..6436080599 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt @@ -154,7 +154,9 @@ class RoomDetailRobot { fun openThreadSummaries() { clickMenu(R.id.menu_timeline_thread_list) - waitUntilViewVisible(withId(R.id.threadListRecyclerView)) + withRetry { + waitUntilViewVisible(withId(R.id.threadListRecyclerView)) + } } fun selectThreadSummariesFilter() { From f3e0ae08197fc2cd03f9c4ea12be90e3eabf68e6 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Fri, 8 Jul 2022 12:56:17 +0100 Subject: [PATCH 110/131] selecting the space with the empty room before attempt to interact with it --- .../vector/app/ui/UiAllScreensSanityTest.kt | 17 +++++++----- .../app/ui/robot/space/SpaceCreateRobot.kt | 4 +-- .../app/ui/robot/space/SpaceMenuRobot.kt | 17 ------------ .../vector/app/ui/robot/space/SpaceRobot.kt | 26 +++++++++++++++++++ 4 files changed, 38 insertions(+), 26 deletions(-) diff --git a/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt b/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt index 09980f405e..958f22c2bb 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt @@ -99,30 +99,33 @@ class UiAllScreensSanityTest { testThreadScreens() + val spaceName = UUID.randomUUID().toString() elementRobot.space { createSpace { - crawl() + createAndCrawl(spaceName) } - val spaceName = UUID.randomUUID().toString() + val publicSpace = UUID.randomUUID().toString() createSpace { - createPublicSpace(spaceName) + createPublicSpace(publicSpace) } - spaceMenu(spaceName) { + spaceMenu(publicSpace) { spaceMembers() spaceSettings { crawl() } exploreRooms() - invitePeople().also { openMenu(spaceName) } - addRoom().also { openMenu(spaceName) } - addSpace().also { openMenu(spaceName) } + invitePeople().also { openMenu(publicSpace) } + addRoom().also { openMenu(publicSpace) } + addSpace().also { openMenu(publicSpace) } leaveSpace() } } + elementRobot.space { selectSpace(spaceName) } + elementRobot.withDeveloperMode { settings { advancedSettings { crawlDeveloperOptions() } diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/space/SpaceCreateRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/space/SpaceCreateRobot.kt index 68e5fa5059..3116412a5f 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/robot/space/SpaceCreateRobot.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/robot/space/SpaceCreateRobot.kt @@ -36,11 +36,11 @@ import java.util.UUID class SpaceCreateRobot { - fun crawl() { + fun createAndCrawl(name: String) { // public clickOn(R.id.publicButton) waitUntilViewVisible(withId(R.id.recyclerView)) - onView(ViewMatchers.withHint(R.string.create_room_name_hint)).perform(ViewActions.replaceText(UUID.randomUUID().toString())) + onView(ViewMatchers.withHint(R.string.create_room_name_hint)).perform(ViewActions.replaceText(name)) clickOn(R.id.nextButton) waitUntilViewVisible(withId(R.id.recyclerView)) pressBack() diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/space/SpaceMenuRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/space/SpaceMenuRobot.kt index 289c6e21b4..d04746bcd6 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/robot/space/SpaceMenuRobot.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/robot/space/SpaceMenuRobot.kt @@ -16,13 +16,9 @@ package im.vector.app.ui.robot.space -import androidx.recyclerview.widget.RecyclerView import androidx.test.espresso.Espresso -import androidx.test.espresso.Espresso.onView -import androidx.test.espresso.contrib.RecyclerViewActions import androidx.test.espresso.matcher.ViewMatchers import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn -import com.adevinta.android.barista.internal.viewaction.ClickChildAction import im.vector.app.R import im.vector.app.clickOnSheet import im.vector.app.espresso.tools.waitUntilActivityVisible @@ -33,22 +29,9 @@ import im.vector.app.features.roomprofile.RoomProfileActivity import im.vector.app.features.spaces.SpaceExploreActivity import im.vector.app.features.spaces.leave.SpaceLeaveAdvancedActivity import im.vector.app.features.spaces.manage.SpaceManageActivity -import org.hamcrest.Matchers class SpaceMenuRobot { - fun openMenu(spaceName: String) { - waitUntilViewVisible(ViewMatchers.withId(R.id.groupListView)) - onView(ViewMatchers.withId(R.id.groupListView)) - .perform( - RecyclerViewActions.actionOnItem( - ViewMatchers.hasDescendant(Matchers.allOf(ViewMatchers.withId(R.id.groupNameView), ViewMatchers.withText(spaceName))), - ClickChildAction.clickChildWithId(R.id.groupTmpLeave) - ).atPosition(0) - ) - waitUntilDialogVisible(ViewMatchers.withId(R.id.spaceNameView)) - } - fun invitePeople() = apply { clickOnSheet(R.id.invitePeople) waitUntilDialogVisible(ViewMatchers.withId(R.id.inviteByMxidButton)) diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/space/SpaceRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/space/SpaceRobot.kt index bfcf312e76..b8a2f4313b 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/robot/space/SpaceRobot.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/robot/space/SpaceRobot.kt @@ -16,9 +16,17 @@ package im.vector.app.ui.robot.space +import androidx.recyclerview.widget.RecyclerView +import androidx.test.espresso.Espresso +import androidx.test.espresso.contrib.RecyclerViewActions +import androidx.test.espresso.matcher.ViewMatchers import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn import com.adevinta.android.barista.interaction.BaristaDrawerInteractions.openDrawer +import com.adevinta.android.barista.internal.viewaction.ClickChildAction import im.vector.app.R +import im.vector.app.espresso.tools.waitUntilDialogVisible +import im.vector.app.espresso.tools.waitUntilViewVisible +import org.hamcrest.Matchers class SpaceRobot { @@ -35,4 +43,22 @@ class SpaceRobot { block() } } + + fun openMenu(spaceName: String) { + waitUntilViewVisible(ViewMatchers.withId(R.id.groupListView)) + Espresso.onView(ViewMatchers.withId(R.id.groupListView)) + .perform( + RecyclerViewActions.actionOnItem( + ViewMatchers.hasDescendant(Matchers.allOf(ViewMatchers.withId(R.id.groupNameView), ViewMatchers.withText(spaceName))), + ClickChildAction.clickChildWithId(R.id.groupTmpLeave) + ).atPosition(0) + ) + waitUntilDialogVisible(ViewMatchers.withId(R.id.spaceNameView)) + } + + fun selectSpace(spaceName: String) { + openDrawer() + waitUntilViewVisible(ViewMatchers.withId(R.id.groupListView)) + clickOn(spaceName) + } } From 46ed9a87e4de198656148a7f2f3e7279d1c8baea Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Fri, 8 Jul 2022 13:13:22 +0100 Subject: [PATCH 111/131] removing unused imports --- .../java/im/vector/app/ui/robot/CreateNewRoomRobot.kt | 3 --- .../java/im/vector/app/ui/robot/space/SpaceCreateRobot.kt | 1 - 2 files changed, 4 deletions(-) diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/CreateNewRoomRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/CreateNewRoomRobot.kt index 743d16bbd8..854dd0ce0f 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/robot/CreateNewRoomRobot.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/robot/CreateNewRoomRobot.kt @@ -17,14 +17,11 @@ package im.vector.app.ui.robot import androidx.test.espresso.Espresso.closeSoftKeyboard -import androidx.test.espresso.Espresso.onData import androidx.test.espresso.Espresso.onView import androidx.test.espresso.Espresso.pressBack import androidx.test.espresso.action.ViewActions.replaceText -import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.matcher.ViewMatchers.withHint import androidx.test.espresso.matcher.ViewMatchers.withId -import androidx.test.espresso.matcher.ViewMatchers.withText import com.adevinta.android.barista.assertion.BaristaListAssertions import com.adevinta.android.barista.interaction.BaristaClickInteractions import com.adevinta.android.barista.interaction.BaristaListInteractions diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/space/SpaceCreateRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/space/SpaceCreateRobot.kt index 3116412a5f..018f3097ba 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/robot/space/SpaceCreateRobot.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/robot/space/SpaceCreateRobot.kt @@ -32,7 +32,6 @@ 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.spaces.manage.SpaceManageActivity -import java.util.UUID class SpaceCreateRobot { From 2c843985cae65993604351aaa0215d0675992724 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 13 Jul 2022 09:17:50 +0100 Subject: [PATCH 112/131] updating variable to include name (as it's holding the space name --- .../java/im/vector/app/ui/UiAllScreensSanityTest.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt b/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt index 958f22c2bb..9434006060 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt @@ -104,21 +104,21 @@ class UiAllScreensSanityTest { createSpace { createAndCrawl(spaceName) } - val publicSpace = UUID.randomUUID().toString() + val publicSpaceName = UUID.randomUUID().toString() createSpace { - createPublicSpace(publicSpace) + createPublicSpace(publicSpaceName) } - spaceMenu(publicSpace) { + spaceMenu(publicSpaceName) { spaceMembers() spaceSettings { crawl() } exploreRooms() - invitePeople().also { openMenu(publicSpace) } - addRoom().also { openMenu(publicSpace) } - addSpace().also { openMenu(publicSpace) } + invitePeople().also { openMenu(publicSpaceName) } + addRoom().also { openMenu(publicSpaceName) } + addSpace().also { openMenu(publicSpaceName) } leaveSpace() } From 484606bfa48e1142f25ee39103efdf745a1d803f Mon Sep 17 00:00:00 2001 From: Linerly Date: Tue, 12 Jul 2022 23:59:53 +0000 Subject: [PATCH 113/131] Translated using Weblate (Indonesian) Currently translated at 100.0% (68 of 68 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/id/ --- fastlane/metadata/android/id/changelogs/40104220.txt | 2 ++ fastlane/metadata/android/id/changelogs/40104230.txt | 2 ++ fastlane/metadata/android/id/changelogs/40104240.txt | 2 ++ fastlane/metadata/android/id/changelogs/40104250.txt | 2 ++ 4 files changed, 8 insertions(+) create mode 100644 fastlane/metadata/android/id/changelogs/40104220.txt create mode 100644 fastlane/metadata/android/id/changelogs/40104230.txt create mode 100644 fastlane/metadata/android/id/changelogs/40104240.txt create mode 100644 fastlane/metadata/android/id/changelogs/40104250.txt diff --git a/fastlane/metadata/android/id/changelogs/40104220.txt b/fastlane/metadata/android/id/changelogs/40104220.txt new file mode 100644 index 0000000000..1017951d47 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40104220.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: Banyak perbaikan kutu dan perbaikan stabilitas. +Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/id/changelogs/40104230.txt b/fastlane/metadata/android/id/changelogs/40104230.txt new file mode 100644 index 0000000000..1017951d47 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40104230.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: Banyak perbaikan kutu dan perbaikan stabilitas. +Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/id/changelogs/40104240.txt b/fastlane/metadata/android/id/changelogs/40104240.txt new file mode 100644 index 0000000000..1017951d47 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40104240.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: Banyak perbaikan kutu dan perbaikan stabilitas. +Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/id/changelogs/40104250.txt b/fastlane/metadata/android/id/changelogs/40104250.txt new file mode 100644 index 0000000000..1017951d47 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40104250.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: Banyak perbaikan kutu dan perbaikan stabilitas. +Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases From 3a80880ac7930ff800227ca1ef1aeeb08361cc33 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 13 Jul 2022 11:33:54 +0200 Subject: [PATCH 114/131] Delete unused key `error_attachment` --- vector/src/main/res/values-bg/strings.xml | 3 +-- vector/src/main/res/values-ca/strings.xml | 3 +-- vector/src/main/res/values-cs/strings.xml | 3 +-- vector/src/main/res/values-de/strings.xml | 3 +-- vector/src/main/res/values-eo/strings.xml | 1 - vector/src/main/res/values-es/strings.xml | 3 +-- vector/src/main/res/values-et/strings.xml | 3 +-- vector/src/main/res/values-eu/strings.xml | 1 - vector/src/main/res/values-fa/strings.xml | 3 +-- vector/src/main/res/values-fi/strings.xml | 3 +-- vector/src/main/res/values-fr-rCA/strings.xml | 3 +-- vector/src/main/res/values-fr/strings.xml | 3 +-- vector/src/main/res/values-fy/strings.xml | 3 +-- vector/src/main/res/values-hu/strings.xml | 1 - vector/src/main/res/values-in/strings.xml | 3 +-- vector/src/main/res/values-is/strings.xml | 1 - vector/src/main/res/values-it/strings.xml | 3 +-- vector/src/main/res/values-iw/strings.xml | 1 - vector/src/main/res/values-ja/strings.xml | 1 - vector/src/main/res/values-kab/strings.xml | 1 - vector/src/main/res/values-ko/strings.xml | 1 - vector/src/main/res/values-lo/strings.xml | 1 - vector/src/main/res/values-lv/strings.xml | 1 - vector/src/main/res/values-nb-rNO/strings.xml | 1 - vector/src/main/res/values-nl/strings.xml | 3 +-- vector/src/main/res/values-pl/strings.xml | 3 +-- vector/src/main/res/values-pt-rBR/strings.xml | 3 +-- vector/src/main/res/values-ru/strings.xml | 3 +-- vector/src/main/res/values-sk/strings.xml | 3 +-- vector/src/main/res/values-sq/strings.xml | 1 - vector/src/main/res/values-sv/strings.xml | 3 +-- vector/src/main/res/values-tr/strings.xml | 1 - vector/src/main/res/values-uk/strings.xml | 3 +-- vector/src/main/res/values-vi/strings.xml | 1 - vector/src/main/res/values-zh-rCN/strings.xml | 1 - vector/src/main/res/values-zh-rTW/strings.xml | 3 +-- vector/src/main/res/values/strings.xml | 3 --- 37 files changed, 21 insertions(+), 60 deletions(-) diff --git a/vector/src/main/res/values-bg/strings.xml b/vector/src/main/res/values-bg/strings.xml index 1ee559f8f7..96e719f29f 100644 --- a/vector/src/main/res/values-bg/strings.xml +++ b/vector/src/main/res/values-bg/strings.xml @@ -950,7 +950,6 @@ %d потребител прочете %d потребителя прочетоха - Възникна грешка при извличане на прикачения файл. Файл Контакт Камера @@ -1737,4 +1736,4 @@ %s настрой разрешенията (ACL) за тази стая. Първоначална заявка за синхронизация Нямате права да се присъедините към тази стая - \ No newline at end of file + diff --git a/vector/src/main/res/values-ca/strings.xml b/vector/src/main/res/values-ca/strings.xml index ee0aa016d4..9491ebed77 100644 --- a/vector/src/main/res/values-ca/strings.xml +++ b/vector/src/main/res/values-ca/strings.xml @@ -989,7 +989,6 @@ Introdueix l\'adreça del servidor que vulguis utilitzar Galeria Adhesiu - S\'ha produït un error mentre es rebia el fitxer adjunt. Salta al final Crea una nova sala Tanca el menú de creació de sala… @@ -2530,4 +2529,4 @@ \'Endpoint\' registrat correctament al servidor. Registre d\'endpoint Següent - \ No newline at end of file + diff --git a/vector/src/main/res/values-cs/strings.xml b/vector/src/main/res/values-cs/strings.xml index e2cce2f2cc..c15de7cc0d 100644 --- a/vector/src/main/res/values-cs/strings.xml +++ b/vector/src/main/res/values-cs/strings.xml @@ -1045,7 +1045,6 @@ %d uživatelé přečetli %d uživatelů přečetlo - Během načítání přílohy došlo k chybě. Soubor Kontakt Fotoaparát @@ -2578,4 +2577,4 @@ Koncový bod byl úspěšně zaregistrován na domovském serveru. Registrace koncového bodu Další - \ No newline at end of file + diff --git a/vector/src/main/res/values-de/strings.xml b/vector/src/main/res/values-de/strings.xml index dce916514a..bf69883e14 100644 --- a/vector/src/main/res/values-de/strings.xml +++ b/vector/src/main/res/values-de/strings.xml @@ -1020,7 +1020,6 @@ gelesen von einem Nutzer gelesen von %d Nutzern - Beim Abrufen des Anhangs ist ein Fehler aufgetreten. Datei Kontakt Kamera @@ -2529,4 +2528,4 @@ Profil personalisieren ${app_name} ist auch für den Arbeitsplatz geeignet. Die sichersten Organisationen der Welt vertrauen darauf. Threads sind noch in Arbeit, und es stehen neue, aufregende Funktionen an, wie z. B. verbesserte Benachrichtigungen. Wir würden uns sehr über Dein Feedback freuen! - \ No newline at end of file + diff --git a/vector/src/main/res/values-eo/strings.xml b/vector/src/main/res/values-eo/strings.xml index 6caf36909d..09361de4ea 100644 --- a/vector/src/main/res/values-eo/strings.xml +++ b/vector/src/main/res/values-eo/strings.xml @@ -692,7 +692,6 @@ Filmilo Kontakto Dosiero - Eraris akirado de la kunsendaĵo. %d uzanto legis %d uzantoj legis diff --git a/vector/src/main/res/values-es/strings.xml b/vector/src/main/res/values-es/strings.xml index f4ed0d570b..24909dce3b 100644 --- a/vector/src/main/res/values-es/strings.xml +++ b/vector/src/main/res/values-es/strings.xml @@ -1015,7 +1015,6 @@ Leído por %d usuario Leído por %d usuarios - Ha ocurrido un error recuperando el archivo adjunto. Archivo Contacto Cámara @@ -2526,4 +2525,4 @@ El destino se ha registrado de forma satisfactoria al servidor doméstico. Registración de punto final Siguiente - \ No newline at end of file + diff --git a/vector/src/main/res/values-et/strings.xml b/vector/src/main/res/values-et/strings.xml index be3991e625..af4c9d3b4c 100644 --- a/vector/src/main/res/values-et/strings.xml +++ b/vector/src/main/res/values-et/strings.xml @@ -1467,7 +1467,6 @@ %d kasutaja luges %d kasutajat lugesid - Manuse laadimisel tekkis viga. Fail Kontakt Kaamera @@ -2521,4 +2520,4 @@ Sünkroniseerimine taustal Google\'i teenused Vali teavituste laadimise viis - \ No newline at end of file + diff --git a/vector/src/main/res/values-eu/strings.xml b/vector/src/main/res/values-eu/strings.xml index 724b73bbcb..f1465684e2 100644 --- a/vector/src/main/res/values-eu/strings.xml +++ b/vector/src/main/res/values-eu/strings.xml @@ -1215,7 +1215,6 @@ Errore hau ${app_name}-en kontroletik kanpo dago. Ez dago Google konturik gailua - Errore bat gertatu da eranskina eskuratzean. Fitxategia Kontaktua Kamera diff --git a/vector/src/main/res/values-fa/strings.xml b/vector/src/main/res/values-fa/strings.xml index 3d7e86ac5e..95f9bedfae 100644 --- a/vector/src/main/res/values-fa/strings.xml +++ b/vector/src/main/res/values-fa/strings.xml @@ -1460,7 +1460,6 @@ نتوانست هم‌رسانی داده را مدیریت کند چرخش و برش افزودن تصویر از - هنگام دریافت پیوست خطایی رخ داد. %d کاربر خواند %d کاربر خواندند @@ -2522,4 +2521,4 @@ بازنشانی روش آگاهی برچسب نمایه: بعدی - \ No newline at end of file + diff --git a/vector/src/main/res/values-fi/strings.xml b/vector/src/main/res/values-fi/strings.xml index b62e0428cc..1a1db03232 100644 --- a/vector/src/main/res/values-fi/strings.xml +++ b/vector/src/main/res/values-fi/strings.xml @@ -906,7 +906,6 @@ 1 käyttäjä on lukenut %d käyttäjää on lukenut - Liitettä noudettaessa tapahtui virhe. Tiedosto Kamera Galleria @@ -2123,4 +2122,4 @@ %1$s muutti tämän huoneen vaihtoehtoisia osoitteita. Alkusynkronointipyyntö Poista tämän osoitteen julkaisu - \ No newline at end of file + diff --git a/vector/src/main/res/values-fr-rCA/strings.xml b/vector/src/main/res/values-fr-rCA/strings.xml index 3567b8e1c0..2ce845a632 100644 --- a/vector/src/main/res/values-fr-rCA/strings.xml +++ b/vector/src/main/res/values-fr-rCA/strings.xml @@ -254,7 +254,6 @@ Contact Fichier Ajouter une image à partir de - Une erreur est survenue pendant la récupération de la pièce jointe. %s a lu %1$s et %2$s ont lu %1$s, %2$s et %3$s ont lu @@ -2076,4 +2075,4 @@ \n \nCette action va redémarrer l’application et pourra prendre du temps. Requête de synchronisation initiale - \ No newline at end of file + diff --git a/vector/src/main/res/values-fr/strings.xml b/vector/src/main/res/values-fr/strings.xml index ca75fb5b0d..01852278ef 100644 --- a/vector/src/main/res/values-fr/strings.xml +++ b/vector/src/main/res/values-fr/strings.xml @@ -971,7 +971,6 @@ %d utilisateur a lu %d utilisateurs ont lu - Une erreur est survenue pendant la récupération de la pièce jointe. Fichier Contact Appareil photo @@ -2530,4 +2529,4 @@ Le point de connexion a été correctement enregistré sur le serveur d’accueil. Enregistrement du point de connexion Suivant - \ No newline at end of file + diff --git a/vector/src/main/res/values-fy/strings.xml b/vector/src/main/res/values-fy/strings.xml index d16b81d39b..d218203739 100644 --- a/vector/src/main/res/values-fy/strings.xml +++ b/vector/src/main/res/values-fy/strings.xml @@ -347,7 +347,6 @@ Kontakt Bestân Ofbylding tafoegje út - Der is in flater bard wylst de bylage ophelle waard. Spring nei it ein Ofbylding Nije keamer oanmeitsje @@ -992,4 +991,4 @@ - Beskate brûkers binne net mear negearre Inisjele syngronisaasje oanfreegje It is jo net tastien dizze keamer binnen te gean - \ No newline at end of file + diff --git a/vector/src/main/res/values-hu/strings.xml b/vector/src/main/res/values-hu/strings.xml index 1083de08e3..99caed9211 100644 --- a/vector/src/main/res/values-hu/strings.xml +++ b/vector/src/main/res/values-hu/strings.xml @@ -930,7 +930,6 @@ A Visszaállítási Kulcsot tartsd biztonságos helyen, mint pl. egy jelszókeze %d felhasználó olvasta %d felhasználó olvasta - A csatolmány letöltésénél hiba történt. Fájl Névjegy Kamera diff --git a/vector/src/main/res/values-in/strings.xml b/vector/src/main/res/values-in/strings.xml index 0e8e32fcb9..104203bf32 100644 --- a/vector/src/main/res/values-in/strings.xml +++ b/vector/src/main/res/values-in/strings.xml @@ -1145,7 +1145,6 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Galeri Kamera Kontak - Ada kesalahan terjadi saat menerima lampiran. Tambahkan gambar dari File +%d @@ -2484,4 +2483,4 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Endpoint berhasil terdaftar ke homeserver. Pendaftaran Endpoint Lanjut - \ No newline at end of file + diff --git a/vector/src/main/res/values-is/strings.xml b/vector/src/main/res/values-is/strings.xml index 8afc31eb12..88234a6364 100644 --- a/vector/src/main/res/values-is/strings.xml +++ b/vector/src/main/res/values-is/strings.xml @@ -1637,7 +1637,6 @@ Bæta í lítinn forgang HUNSA NOTANDA Tókst ekki að meðhöndla deiligögn - Villa kom upp þegar reynt var að sækja viðhengið. Skráin er of stór til að senda hana inn. %d notandi las diff --git a/vector/src/main/res/values-it/strings.xml b/vector/src/main/res/values-it/strings.xml index 5dfdc9f3ec..3879e5a13c 100644 --- a/vector/src/main/res/values-it/strings.xml +++ b/vector/src/main/res/values-it/strings.xml @@ -992,7 +992,6 @@ %d utente ha letto %d utenti hanno letto - Si è verificato un errore nella ricezione dell\'allegato. File Contatto Fotocamera @@ -2521,4 +2520,4 @@ Endpoint registrato con successo sull\'homeserver. Registrazione endpoint Avanti - \ No newline at end of file + diff --git a/vector/src/main/res/values-iw/strings.xml b/vector/src/main/res/values-iw/strings.xml index bf2fb977df..be02a1e772 100644 --- a/vector/src/main/res/values-iw/strings.xml +++ b/vector/src/main/res/values-iw/strings.xml @@ -1004,7 +1004,6 @@ איש קשר קובץ הוסף תמונה מ - אירעה שגיאה בעת אחזור הקובץ המצורף. %s נקרא %1$s ו- %2$s נקראו %1$s, %2$s ו- %3$s נקראו diff --git a/vector/src/main/res/values-ja/strings.xml b/vector/src/main/res/values-ja/strings.xml index 5866643759..0aef5124c9 100644 --- a/vector/src/main/res/values-ja/strings.xml +++ b/vector/src/main/res/values-ja/strings.xml @@ -1595,7 +1595,6 @@ このルームへの参加は許可されていません "トピック: " トラブルシューティング - 添付ファイルの取得中にエラーが発生しました。 鍵のバックアップのバナーを閉じる キーワードに「%s」を含めることはできません %sへのメール通知を有効にする diff --git a/vector/src/main/res/values-kab/strings.xml b/vector/src/main/res/values-kab/strings.xml index 636a624760..15b96813c8 100644 --- a/vector/src/main/res/values-kab/strings.xml +++ b/vector/src/main/res/values-kab/strings.xml @@ -744,7 +744,6 @@ 1 useqdac yeɣra %d yiseqdacen ɣran - Tuccḍa deg tuqqna lawan n uneɛruḍ n uceqquf yeddan. Astiker Ur yezmir ara ad ttusqedcen deg yisefka n beṭṭu AMIDYA diff --git a/vector/src/main/res/values-ko/strings.xml b/vector/src/main/res/values-ko/strings.xml index 1f6585ad52..5d07800726 100644 --- a/vector/src/main/res/values-ko/strings.xml +++ b/vector/src/main/res/values-ko/strings.xml @@ -815,7 +815,6 @@ %d명이 읽음 - 첨부 파일을 검색하는 중 오류가 발생했습니다. 파일 연락처 카메라 diff --git a/vector/src/main/res/values-lo/strings.xml b/vector/src/main/res/values-lo/strings.xml index d87ed0d604..5af621359f 100644 --- a/vector/src/main/res/values-lo/strings.xml +++ b/vector/src/main/res/values-lo/strings.xml @@ -1106,7 +1106,6 @@ ຕິດຕໍ່ ໄຟລ໌ ເພີ່ມຮູບພາບຈາກ - ເກີດຄວາມຜິດພາດຂຶ້ນໃນຂະນະທີ່ກຳລັງດຶງໄຟລ໌ແນບມາ. ໄຟລ໌ໃຫຍ່ເກີນທີ່ຈະອັບໂຫລດ. %d ຜູ້ໃຊ້ອ່ານແລ້ວ diff --git a/vector/src/main/res/values-lv/strings.xml b/vector/src/main/res/values-lv/strings.xml index 0b5ad6bdaa..f16e61980e 100644 --- a/vector/src/main/res/values-lv/strings.xml +++ b/vector/src/main/res/values-lv/strings.xml @@ -1957,7 +1957,6 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka. Šajā istabā nav multivides Multivide Nevarēja apstrādāt kopīgošanas datus - Iegūstot pielikumu, radās kļūda. Fails ir pārāk liels, lai tos augšupielādētu. %1$s, %2$s un %3$d citi lasīja diff --git a/vector/src/main/res/values-nb-rNO/strings.xml b/vector/src/main/res/values-nb-rNO/strings.xml index 16c05de8b2..683961e590 100644 --- a/vector/src/main/res/values-nb-rNO/strings.xml +++ b/vector/src/main/res/values-nb-rNO/strings.xml @@ -836,7 +836,6 @@ Lukk menyen for opprett rom… Lag en ny direkte samtale Gå til bunnen - Det oppstod en feil under henting av vedlegget. Legg til bilde fra Roter og beskjær Kunne ikke håndtere delingsdata diff --git a/vector/src/main/res/values-nl/strings.xml b/vector/src/main/res/values-nl/strings.xml index 3c561a4bad..9b5591d8d0 100644 --- a/vector/src/main/res/values-nl/strings.xml +++ b/vector/src/main/res/values-nl/strings.xml @@ -1380,7 +1380,6 @@ Roteren en bijsnijden Opiniepeiling Afbeelding toevoegen van - Er is een fout opgetreden bij het ophalen van de bijlage. Het bestand is te groot om te uploaden. %d persoon gelezen @@ -2530,4 +2529,4 @@ Eindpunt succesvol geregistreerd bij server. Registratie van eindpunt Volgende - \ No newline at end of file + diff --git a/vector/src/main/res/values-pl/strings.xml b/vector/src/main/res/values-pl/strings.xml index f081475e9c..26e85f2473 100644 --- a/vector/src/main/res/values-pl/strings.xml +++ b/vector/src/main/res/values-pl/strings.xml @@ -890,7 +890,6 @@ %d użytkowników odczytało %d użytkowników odczytało - Wystąpił błąd poczas otrzymywania załącznika. Nie można obsłużyć otrzymanych danych Zgłoszono jako nieodpowiedni Zawartość została zgłoszona jako niewłaściwa. @@ -2606,4 +2605,4 @@ Dostępni dostawcy Dostawca powiadomień Wybierz, którego dostawcy powiadomień push chcesz używać - \ No newline at end of file + diff --git a/vector/src/main/res/values-pt-rBR/strings.xml b/vector/src/main/res/values-pt-rBR/strings.xml index caa06db7f4..00651ada32 100644 --- a/vector/src/main/res/values-pt-rBR/strings.xml +++ b/vector/src/main/res/values-pt-rBR/strings.xml @@ -1092,7 +1092,6 @@ %d usuária(o) leu %d usuárias(os) leram - Um erro ocorreu enquando recuperando o anexo. Arquivo Contato Câmera @@ -2530,4 +2529,4 @@ Endpoint registrado com sucesso ao servidor casa. Registro de Endpoint Próximo - \ No newline at end of file + diff --git a/vector/src/main/res/values-ru/strings.xml b/vector/src/main/res/values-ru/strings.xml index 2d7e700b06..55c5ab0127 100644 --- a/vector/src/main/res/values-ru/strings.xml +++ b/vector/src/main/res/values-ru/strings.xml @@ -1255,7 +1255,6 @@ Создать новый диалог %1$s, %2$s и %3$s прочли %1$s и %2$s прочли - Произошла ошибка при загрузке вложения. %1$s %2$s Жалоба отправлена Жалоба на контент отправлена. @@ -2610,4 +2609,4 @@ Текущая конечная точка: %s Конечная точка Вещи в этом пространстве - \ No newline at end of file + diff --git a/vector/src/main/res/values-sk/strings.xml b/vector/src/main/res/values-sk/strings.xml index 5581d48393..edc4163d0c 100644 --- a/vector/src/main/res/values-sk/strings.xml +++ b/vector/src/main/res/values-sk/strings.xml @@ -1602,7 +1602,6 @@ V tejto miestnosti nie sú žiadne súbory MÉDIÁ V tejto miestnosti nie sú žiadne médiá - Pri načítavaní prílohy došlo k chybe. Prejsť na spodok Vytvoriť novú miestnosť Vytvoriť novú priamu konverzáciu @@ -2578,4 +2577,4 @@ Koncové zariadenie sa úspešne zaregistrovalo na domovský server. Registrácia koncového bodu Ďalej - \ No newline at end of file + diff --git a/vector/src/main/res/values-sq/strings.xml b/vector/src/main/res/values-sq/strings.xml index 82426710b1..80b6b27793 100644 --- a/vector/src/main/res/values-sq/strings.xml +++ b/vector/src/main/res/values-sq/strings.xml @@ -986,7 +986,6 @@ %d përdorues lexoi %d përdorues lexuan - Ndodhi një gabim gjatë marrjes së bashkëngjitjes. Kartelë Kontakt Kamerë diff --git a/vector/src/main/res/values-sv/strings.xml b/vector/src/main/res/values-sv/strings.xml index 857f3b66ad..84e90da44b 100644 --- a/vector/src/main/res/values-sv/strings.xml +++ b/vector/src/main/res/values-sv/strings.xml @@ -1348,7 +1348,6 @@ %d användare läste %d användare läste - Ett fel inträffade vid hämtning av bilagan. Kunde inte hantera delningsdata %1$s vid %2$s Det är skräppost @@ -2530,4 +2529,4 @@ \n%1$s Lyckades registrera ändpunkten hos hemservern. Ändpunktsregistrering - \ No newline at end of file + diff --git a/vector/src/main/res/values-tr/strings.xml b/vector/src/main/res/values-tr/strings.xml index b4fec54025..b3c2895b9a 100644 --- a/vector/src/main/res/values-tr/strings.xml +++ b/vector/src/main/res/values-tr/strings.xml @@ -1046,7 +1046,6 @@ Bu odada medya yok Döndür ve kırp Şuradan resim ekle - Ek alınırken bir hata oluştu. Aşağıya git Yeni bir oda oluşturun Yeni bir direkt sohbet oluşturun diff --git a/vector/src/main/res/values-uk/strings.xml b/vector/src/main/res/values-uk/strings.xml index 957d759bc9..a5b9571748 100644 --- a/vector/src/main/res/values-uk/strings.xml +++ b/vector/src/main/res/values-uk/strings.xml @@ -1930,7 +1930,6 @@ Вилучити з обраних Додати до обраних Не вдалося обробити спільні дані - Сталася помилка завантаження вкладення. Прочитано %d користувачем Прочитали %d користувачі @@ -2624,4 +2623,4 @@ Кінцеву точку успішно зареєстровано на домашньому сервері. Реєстрація кінцевої точки Далі - \ No newline at end of file + diff --git a/vector/src/main/res/values-vi/strings.xml b/vector/src/main/res/values-vi/strings.xml index 7b4bc246b5..8b15f779d1 100644 --- a/vector/src/main/res/values-vi/strings.xml +++ b/vector/src/main/res/values-vi/strings.xml @@ -736,7 +736,6 @@ Liên hệ Tệp Thêm hình từ - Lỗi xảy ra khi hiển thị tệp đính kèm. Tệp quá lớn để tải lên. %d người dùng đã đọc diff --git a/vector/src/main/res/values-zh-rCN/strings.xml b/vector/src/main/res/values-zh-rCN/strings.xml index 36292ff61d..7227da69d8 100644 --- a/vector/src/main/res/values-zh-rCN/strings.xml +++ b/vector/src/main/res/values-zh-rCN/strings.xml @@ -1033,7 +1033,6 @@ %d 个用户已读 - 获取附件时出错。 文件 联系人 相机 diff --git a/vector/src/main/res/values-zh-rTW/strings.xml b/vector/src/main/res/values-zh-rTW/strings.xml index cac37b9b64..89b2a723e1 100644 --- a/vector/src/main/res/values-zh-rTW/strings.xml +++ b/vector/src/main/res/values-zh-rTW/strings.xml @@ -974,7 +974,6 @@ %d 個使用者已閱讀 - 在擷取附件時遇到錯誤。 檔案 聯絡人 相機 @@ -2482,4 +2481,4 @@ 端點成功註冊至家伺服器。 端點註冊 下一步 - \ No newline at end of file + diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 778acf3096..3b094ed7c2 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -1815,9 +1815,6 @@ "The file is too large to upload." - - - "An error occurred while retrieving the attachment." "Add image from" "File" "Contact" From 4c31bd0639d0657d9edc7e089c84df3a53cb2f8c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 13 Jul 2022 11:40:18 +0200 Subject: [PATCH 115/131] Reduce title length. --- fastlane/metadata/android/hu-HU/title.txt | 2 +- fastlane/metadata/android/ta-IN/title.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fastlane/metadata/android/hu-HU/title.txt b/fastlane/metadata/android/hu-HU/title.txt index c463dea393..907f907f99 100644 --- a/fastlane/metadata/android/hu-HU/title.txt +++ b/fastlane/metadata/android/hu-HU/title.txt @@ -1 +1 @@ -Element - Biztonságos üzenetküldő +Element diff --git a/fastlane/metadata/android/ta-IN/title.txt b/fastlane/metadata/android/ta-IN/title.txt index ecb9a01c06..907f907f99 100644 --- a/fastlane/metadata/android/ta-IN/title.txt +++ b/fastlane/metadata/android/ta-IN/title.txt @@ -1 +1 @@ -Element - பாதுகாப்பான தூதுரை சேவை +Element From 384f95a1802183219341e4b5666a18d88015c420 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 13 Jul 2022 11:40:53 +0200 Subject: [PATCH 116/131] Generated file by fastlane --- fastlane/README.md | 53 +++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/fastlane/README.md b/fastlane/README.md index dc33f422d6..7fea7afdd5 100644 --- a/fastlane/README.md +++ b/fastlane/README.md @@ -1,49 +1,64 @@ fastlane documentation -================ +---- + # Installation Make sure you have the latest version of the Xcode command line tools installed: -``` +```sh xcode-select --install ``` -Install _fastlane_ using -``` -[sudo] gem install fastlane -NV -``` -or alternatively using `brew install fastlane` +For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane) # Available Actions + ## Android + ### android test + +```sh +[bundle exec] fastlane android test ``` -fastlane android test -``` + Runs all the tests + ### android beta + +```sh +[bundle exec] fastlane android beta ``` -fastlane android beta -``` + Submit a new Beta Build to Crashlytics Beta + ### android deploy + +```sh +[bundle exec] fastlane android deploy ``` -fastlane android deploy -``` + Deploy a new version to the Google Play + ### android deployMeta + +```sh +[bundle exec] fastlane android deployMeta ``` -fastlane android deployMeta -``` + Deploy Google Play metadata + ### android getVersionCode + +```sh +[bundle exec] fastlane android getVersionCode ``` -fastlane android getVersionCode -``` + Get version code ---- This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run. -More information about fastlane can be found on [fastlane.tools](https://fastlane.tools). -The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools). + +More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools). + +The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools). From a85ebbfc34a1ad939aa25335a54337e91adb84ea Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 13 Jul 2022 12:42:00 +0200 Subject: [PATCH 117/131] Run towncrier --- CHANGES.md | 39 +++++++++++++++++++++++++++++++++++++++ changelog.d/4777.bugfix | 1 - changelog.d/5284.wip | 1 - changelog.d/5398.bugfix | 1 - changelog.d/5525.wip | 1 - changelog.d/5853.feature | 1 - changelog.d/6288.bugfix | 1 - changelog.d/6389.misc | 1 - changelog.d/6392.misc | 1 - changelog.d/6401.feature | 1 - changelog.d/6413.feature | 1 - changelog.d/6423.misc | 1 - changelog.d/6429.misc | 1 - changelog.d/6430.bugfix | 1 - changelog.d/6434.misc | 1 - changelog.d/6436.misc | 1 - changelog.d/6442.bugfix | 1 - changelog.d/6450.bugfix | 1 - changelog.d/6451.bugfix | 1 - changelog.d/6458.misc | 1 - changelog.d/6461.bugfix | 1 - changelog.d/6463.bugfix | 1 - changelog.d/6469.bugfix | 1 - changelog.d/6510.bugfix | 1 - 24 files changed, 39 insertions(+), 23 deletions(-) delete mode 100644 changelog.d/4777.bugfix delete mode 100644 changelog.d/5284.wip delete mode 100644 changelog.d/5398.bugfix delete mode 100644 changelog.d/5525.wip delete mode 100644 changelog.d/5853.feature delete mode 100644 changelog.d/6288.bugfix delete mode 100644 changelog.d/6389.misc delete mode 100644 changelog.d/6392.misc delete mode 100644 changelog.d/6401.feature delete mode 100644 changelog.d/6413.feature delete mode 100644 changelog.d/6423.misc delete mode 100644 changelog.d/6429.misc delete mode 100644 changelog.d/6430.bugfix delete mode 100644 changelog.d/6434.misc delete mode 100644 changelog.d/6436.misc delete mode 100644 changelog.d/6442.bugfix delete mode 100644 changelog.d/6450.bugfix delete mode 100644 changelog.d/6451.bugfix delete mode 100644 changelog.d/6458.misc delete mode 100644 changelog.d/6461.bugfix delete mode 100644 changelog.d/6463.bugfix delete mode 100644 changelog.d/6469.bugfix delete mode 100644 changelog.d/6510.bugfix diff --git a/CHANGES.md b/CHANGES.md index b66e567f5b..fd78aa0f96 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,42 @@ +Changes in Element v1.4.28 (2022-07-13) +======================================= + +Features ✨ +---------- + - Improve user experience when he is first invited to a room. Users will be able to decrypt and view previous messages ([#5853](https://github.com/vector-im/element-android/issues/5853)) + - [Location sharing] - Reply action on a live message ([#6401](https://github.com/vector-im/element-android/issues/6401)) + - Show a loader if all the Room Members are not yet loaded. ([#6413](https://github.com/vector-im/element-android/issues/6413)) + +Bugfixes 🐛 +---------- + - Fixes numbered lists always starting from 1 ([#4777](https://github.com/vector-im/element-android/issues/4777)) + - Adds LoginType to SessionParams to fix soft logout form not showing for SSO and Password type ([#5398](https://github.com/vector-im/element-android/issues/5398)) + - Use stable endpoint for alias management instead of MSC2432. Contributed by Nico. ([#6288](https://github.com/vector-im/element-android/issues/6288)) + - [Poll] Fixes visible and wrong votes in closed poll after removing 2 previous polls ([#6430](https://github.com/vector-im/element-android/issues/6430)) + - Fix HTML entities being displayed in messages ([#6442](https://github.com/vector-im/element-android/issues/6442)) + - Gallery picker can pick external images ([#6450](https://github.com/vector-im/element-android/issues/6450)) + - Fixes crash when sharing plain text, such as a url ([#6451](https://github.com/vector-im/element-android/issues/6451)) + - Fix crashes on Timeline [Thread] due to range validation ([#6461](https://github.com/vector-im/element-android/issues/6461)) + - Fix crashes when opening Thread ([#6463](https://github.com/vector-im/element-android/issues/6463)) + - Fix ConcurrentModificationException on BackgroundDetectionObserver ([#6469](https://github.com/vector-im/element-android/issues/6469)) + - Fixes inconsistency with rooms within spaces showing or disappearing from home ([#6510](https://github.com/vector-im/element-android/issues/6510)) + +In development 🚧 +---------------- + - FTUE - Adds support for resetting the password during the FTUE onboarding journey ([#5284](https://github.com/vector-im/element-android/issues/5284)) + - Create DM room only on first message - Design implementation & debug feature flag ([#5525](https://github.com/vector-im/element-android/issues/5525)) + +Other changes +------------- + - Replacing Epoxy annotation layout id references with getDefaultLayoutId ([#6389](https://github.com/vector-im/element-android/issues/6389)) + - Ensure `RealmList.clearWith()` extension is correctly used. ([#6392](https://github.com/vector-im/element-android/issues/6392)) + - [Poll] - Add a description under undisclosed poll when not ended ([#6423](https://github.com/vector-im/element-android/issues/6423)) + - Add `android:hasFragileUserData="true"` in the manifest ([#6429](https://github.com/vector-im/element-android/issues/6429)) + - Add code check to prevent modification of frozen class ([#6434](https://github.com/vector-im/element-android/issues/6434)) + - Let your Activity or Fragment implement `VectorMenuProvider` if they provide a menu. ([#6436](https://github.com/vector-im/element-android/issues/6436)) + - Rename Android Service to use `AndroidService` suffix ([#6458](https://github.com/vector-im/element-android/issues/6458)) + + Changes in Element v1.4.27 (2022-07-06) ======================================= diff --git a/changelog.d/4777.bugfix b/changelog.d/4777.bugfix deleted file mode 100644 index 428101f649..0000000000 --- a/changelog.d/4777.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixes numbered lists always starting from 1 diff --git a/changelog.d/5284.wip b/changelog.d/5284.wip deleted file mode 100644 index a296de24af..0000000000 --- a/changelog.d/5284.wip +++ /dev/null @@ -1 +0,0 @@ -FTUE - Adds support for resetting the password during the FTUE onboarding journey diff --git a/changelog.d/5398.bugfix b/changelog.d/5398.bugfix deleted file mode 100644 index 24da1952b3..0000000000 --- a/changelog.d/5398.bugfix +++ /dev/null @@ -1 +0,0 @@ -Adds LoginType to SessionParams to fix soft logout form not showing for SSO and Password type diff --git a/changelog.d/5525.wip b/changelog.d/5525.wip deleted file mode 100644 index c4ac0ff008..0000000000 --- a/changelog.d/5525.wip +++ /dev/null @@ -1 +0,0 @@ -Create DM room only on first message - Design implementation & debug feature flag diff --git a/changelog.d/5853.feature b/changelog.d/5853.feature deleted file mode 100644 index 2a399e76aa..0000000000 --- a/changelog.d/5853.feature +++ /dev/null @@ -1 +0,0 @@ -Improve user experience when he is first invited to a room. Users will be able to decrypt and view previous messages diff --git a/changelog.d/6288.bugfix b/changelog.d/6288.bugfix deleted file mode 100644 index fc01597ed8..0000000000 --- a/changelog.d/6288.bugfix +++ /dev/null @@ -1 +0,0 @@ -Use stable endpoint for alias management instead of MSC2432. Contributed by Nico. diff --git a/changelog.d/6389.misc b/changelog.d/6389.misc deleted file mode 100644 index fcf9b42c47..0000000000 --- a/changelog.d/6389.misc +++ /dev/null @@ -1 +0,0 @@ -Replacing Epoxy annotation layout id references with getDefaultLayoutId diff --git a/changelog.d/6392.misc b/changelog.d/6392.misc deleted file mode 100644 index c7b95917c3..0000000000 --- a/changelog.d/6392.misc +++ /dev/null @@ -1 +0,0 @@ -Ensure `RealmList.clearWith()` extension is correctly used. diff --git a/changelog.d/6401.feature b/changelog.d/6401.feature deleted file mode 100644 index 67ded427d6..0000000000 --- a/changelog.d/6401.feature +++ /dev/null @@ -1 +0,0 @@ -[Location sharing] - Reply action on a live message diff --git a/changelog.d/6413.feature b/changelog.d/6413.feature deleted file mode 100644 index d1dba78fb9..0000000000 --- a/changelog.d/6413.feature +++ /dev/null @@ -1 +0,0 @@ -Show a loader if all the Room Members are not yet loaded. diff --git a/changelog.d/6423.misc b/changelog.d/6423.misc deleted file mode 100644 index 26c1e84830..0000000000 --- a/changelog.d/6423.misc +++ /dev/null @@ -1 +0,0 @@ -[Poll] - Add a description under undisclosed poll when not ended diff --git a/changelog.d/6429.misc b/changelog.d/6429.misc deleted file mode 100644 index 4c748f652c..0000000000 --- a/changelog.d/6429.misc +++ /dev/null @@ -1 +0,0 @@ -Add `android:hasFragileUserData="true"` in the manifest diff --git a/changelog.d/6430.bugfix b/changelog.d/6430.bugfix deleted file mode 100644 index 99b1cb836d..0000000000 --- a/changelog.d/6430.bugfix +++ /dev/null @@ -1 +0,0 @@ -[Poll] Fixes visible and wrong votes in closed poll after removing 2 previous polls diff --git a/changelog.d/6434.misc b/changelog.d/6434.misc deleted file mode 100644 index faef5bc040..0000000000 --- a/changelog.d/6434.misc +++ /dev/null @@ -1 +0,0 @@ -Add code check to prevent modification of frozen class diff --git a/changelog.d/6436.misc b/changelog.d/6436.misc deleted file mode 100644 index a170b624ce..0000000000 --- a/changelog.d/6436.misc +++ /dev/null @@ -1 +0,0 @@ -Let your Activity or Fragment implement `VectorMenuProvider` if they provide a menu. diff --git a/changelog.d/6442.bugfix b/changelog.d/6442.bugfix deleted file mode 100644 index 070ff94bee..0000000000 --- a/changelog.d/6442.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix HTML entities being displayed in messages diff --git a/changelog.d/6450.bugfix b/changelog.d/6450.bugfix deleted file mode 100644 index 212d835f20..0000000000 --- a/changelog.d/6450.bugfix +++ /dev/null @@ -1 +0,0 @@ -Gallery picker can pick external images diff --git a/changelog.d/6451.bugfix b/changelog.d/6451.bugfix deleted file mode 100644 index ed4a2df7e8..0000000000 --- a/changelog.d/6451.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixes crash when sharing plain text, such as a url diff --git a/changelog.d/6458.misc b/changelog.d/6458.misc deleted file mode 100644 index a9a0fcd702..0000000000 --- a/changelog.d/6458.misc +++ /dev/null @@ -1 +0,0 @@ -Rename Android Service to use `AndroidService` suffix diff --git a/changelog.d/6461.bugfix b/changelog.d/6461.bugfix deleted file mode 100644 index 1d3e4e14c5..0000000000 --- a/changelog.d/6461.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix crashes on Timeline [Thread] due to range validation diff --git a/changelog.d/6463.bugfix b/changelog.d/6463.bugfix deleted file mode 100644 index 63d66d018e..0000000000 --- a/changelog.d/6463.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix crashes when opening Thread diff --git a/changelog.d/6469.bugfix b/changelog.d/6469.bugfix deleted file mode 100644 index 5a9cb4022e..0000000000 --- a/changelog.d/6469.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix ConcurrentModificationException on BackgroundDetectionObserver diff --git a/changelog.d/6510.bugfix b/changelog.d/6510.bugfix deleted file mode 100644 index bd21b5c498..0000000000 --- a/changelog.d/6510.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixes inconsistency with rooms within spaces showing or disappearing from home From 9b60bc0ad48c3be028ab0d9eeb225992e1bf8dab Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 13 Jul 2022 12:38:31 +0200 Subject: [PATCH 118/131] Command changed with towncrier 21.9.0 --- .github/ISSUE_TEMPLATE/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/release.yml b/.github/ISSUE_TEMPLATE/release.yml index e663a49fdb..b063c93530 100644 --- a/.github/ISSUE_TEMPLATE/release.yml +++ b/.github/ISSUE_TEMPLATE/release.yml @@ -29,7 +29,7 @@ body: - [ ] Check the rageshake with the current dev version: https://github.com/matrix-org/element-android-rageshakes/labels/1.2.3-dev - [ ] Run the integration test, and especially `UiAllScreensSanityTest.allScreensTest()` - [ ] Create an account on matrix.org and do some smoke tests that the sanity test does not cover like: 1-1 call, 1-1 video call, Jitsi call for instance - - [ ] Run towncrier: `towncrier --version v1.2.3 --draft` (remove `--draft` do write the file CHANGES.md) + - [ ] Run towncrier: `towncrier build --version v1.2.3 --draft` (remove `--draft` do write the file CHANGES.md) - [ ] Check that the folder `changelog.d` is empty. It can happen that some remaining files stay here - [ ] Check the file CHANGES.md consistency. It's possible to reorder items (most important changes first) or change their section if relevant. Also an opportunity to fix some typo, or rewrite things - [ ] Add file for fastlane under ./fastlane/metadata/android/en-US/changelogs From f117d41374a60caa3a9bac15620f4220eb9ee95a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 13 Jul 2022 12:43:25 +0200 Subject: [PATCH 119/131] fastlane file --- fastlane/metadata/android/en-US/changelogs/40104280.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/40104280.txt diff --git a/fastlane/metadata/android/en-US/changelogs/40104280.txt b/fastlane/metadata/android/en-US/changelogs/40104280.txt new file mode 100644 index 0000000000..61db61727a --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40104280.txt @@ -0,0 +1,2 @@ +Main changes in this version: Various bug fixes and stability improvements. +Full changelog: https://github.com/vector-im/element-android/releases From 4c496bb148d8809902812d1d7c42fbd6fe862a43 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 13 Jul 2022 12:46:32 +0200 Subject: [PATCH 120/131] Version++ --- matrix-sdk-android/build.gradle | 2 +- vector/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index ddd4cba1e0..6f1646ec53 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -60,7 +60,7 @@ android { // that the app's state is completely cleared between tests. testInstrumentationRunnerArguments clearPackageData: 'true' - buildConfigField "String", "SDK_VERSION", "\"1.4.28\"" + buildConfigField "String", "SDK_VERSION", "\"1.4.30\"" buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\"" buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\"" diff --git a/vector/build.gradle b/vector/build.gradle index 3ca843309b..48fd3d99d5 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -35,7 +35,7 @@ ext.versionMinor = 4 // 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 = 28 +ext.versionPatch = 30 static def getGitTimestamp() { def cmd = 'git show -s --format=%ct' From 2c106782636d53643e7ac452321f3868b4b37ba0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 13 Jul 2022 22:19:34 +0200 Subject: [PATCH 121/131] Just go back to the timeline if the user is already viewing the DM with the other user. Fix #6514 --- .../features/home/room/detail/RoomDetailPendingAction.kt | 1 + .../app/features/home/room/detail/TimelineFragment.kt | 1 + .../features/roommemberprofile/RoomMemberProfileFragment.kt | 6 ++++++ .../roommemberprofile/RoomMemberProfileViewEvents.kt | 1 + .../roommemberprofile/RoomMemberProfileViewModel.kt | 3 +++ 5 files changed, 12 insertions(+) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailPendingAction.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailPendingAction.kt index b42f551ba0..79328b6272 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailPendingAction.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailPendingAction.kt @@ -17,6 +17,7 @@ package im.vector.app.features.home.room.detail sealed class RoomDetailPendingAction { + object DoNothing : RoomDetailPendingAction() data class JumpToReadReceipt(val userId: String) : RoomDetailPendingAction() data class MentionUser(val userId: String) : RoomDetailPendingAction() data class OpenRoom(val roomId: String, val closeCurrentRoom: Boolean = false) : RoomDetailPendingAction() diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt index 972b5ea898..e86a7fe227 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt @@ -1323,6 +1323,7 @@ class TimelineFragment @Inject constructor( private fun handlePendingAction(roomDetailPendingAction: RoomDetailPendingAction) { when (roomDetailPendingAction) { + RoomDetailPendingAction.DoNothing -> Unit is RoomDetailPendingAction.JumpToReadReceipt -> timelineViewModel.handle(RoomDetailAction.JumpToReadReceipt(roomDetailPendingAction.userId)) is RoomDetailPendingAction.MentionUser -> diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt index 88a27f246c..d050b0d561 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt @@ -136,6 +136,7 @@ class RoomMemberProfileFragment @Inject constructor( is RoomMemberProfileViewEvents.OnBanActionSuccess -> Unit is RoomMemberProfileViewEvents.OnIgnoreActionSuccess -> Unit is RoomMemberProfileViewEvents.OnInviteActionSuccess -> Unit + RoomMemberProfileViewEvents.GoBack -> handleGoBack() } } setupLongClicks() @@ -309,6 +310,11 @@ class RoomMemberProfileFragment @Inject constructor( viewModel.handle(RoomMemberProfileAction.OpenOrCreateDm(fragmentArgs.userId)) } + private fun handleGoBack() { + roomDetailPendingActionStore.data = RoomDetailPendingAction.DoNothing + vectorBaseActivity.finish() + } + override fun onJumpToReadReceiptClicked() { roomDetailPendingActionStore.data = RoomDetailPendingAction.JumpToReadReceipt(fragmentArgs.userId) vectorBaseActivity.finish() diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewEvents.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewEvents.kt index 46983b52a4..d04de8b936 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewEvents.kt @@ -40,4 +40,5 @@ sealed class RoomMemberProfileViewEvents : VectorViewEvents { data class ShareRoomMemberProfile(val permalink: String) : RoomMemberProfileViewEvents() data class OpenRoom(val roomId: String) : RoomMemberProfileViewEvents() + object GoBack : RoomMemberProfileViewEvents() } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt index bf79021fa6..2c30555696 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt @@ -183,6 +183,9 @@ class RoomMemberProfileViewModel @AssistedInject constructor( } if (roomId != initialState.roomId) { _viewEvents.post(RoomMemberProfileViewEvents.OpenRoom(roomId = roomId)) + } else { + // Just go back to the previous screen (timeline) + _viewEvents.post(RoomMemberProfileViewEvents.GoBack) } } } From d10d8d740fb5a764cb6914dfb4c7ab7034ba4593 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 13 Jul 2022 22:48:58 +0200 Subject: [PATCH 122/131] Changelog --- changelog.d/6549.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6549.bugfix diff --git a/changelog.d/6549.bugfix b/changelog.d/6549.bugfix new file mode 100644 index 0000000000..eb6e5bcfb7 --- /dev/null +++ b/changelog.d/6549.bugfix @@ -0,0 +1 @@ +Fix infinite loading when opening a DM when the current room is the same DM. From 50f8d0a6671bcbfe0812deda0eb6a28f314843af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 14 Jul 2022 14:28:49 +0200 Subject: [PATCH 123/131] Ignore `forwardPaginationTest` to unblock the CI --- .../sdk/session/room/timeline/TimelineForwardPaginationTest.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt index 3dbf206e08..2e5c69b048 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt @@ -22,6 +22,7 @@ import org.amshove.kluent.internal.assertEquals import org.amshove.kluent.shouldBeFalse import org.amshove.kluent.shouldBeTrue import org.junit.FixMethodOrder +import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 @@ -52,6 +53,7 @@ class TimelineForwardPaginationTest : InstrumentedTest { * This test ensure that if we click to permalink, we will be able to go back to the live */ @Test + @Ignore("Ignoring this test until it's fixed since it blocks the CI.") fun forwardPaginationTest() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper -> val numberOfMessagesToSend = 90 val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(false) From 6c1016caffcb437f6bcd3b2bbcf4d52ae2b8c345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 14 Jul 2022 13:18:48 +0200 Subject: [PATCH 124/131] Fixes wrong voice message being displayed and played on the timeline. --- changelog.d/6213.bugfix | 1 + .../home/room/detail/timeline/item/MessageVoiceItem.kt | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 changelog.d/6213.bugfix diff --git a/changelog.d/6213.bugfix b/changelog.d/6213.bugfix new file mode 100644 index 0000000000..af0ec928d7 --- /dev/null +++ b/changelog.d/6213.bugfix @@ -0,0 +1 @@ +Fixes wrong voice message being displayed and played on the timeline. diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt index e98d8115e6..72a00d704b 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt @@ -24,7 +24,7 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageButton import android.widget.TextView -import androidx.core.view.doOnLayout +import androidx.core.view.doOnPreDraw import androidx.core.view.isVisible import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass @@ -84,7 +84,7 @@ abstract class MessageVoiceItem : AbsMessageItem() { holder.progressLayout.isVisible = false } - holder.voicePlaybackWaveform.doOnLayout { + holder.voicePlaybackWaveform.doOnPreDraw { onWaveformViewReady(holder) } From 92801f625d4a5aa88664cbb372a0303e5d642653 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Jul 2022 13:44:59 +0000 Subject: [PATCH 125/131] Bump opusencoder from 1.0.3 to 1.0.4 Bumps [opusencoder](https://github.com/vector-im/libopusencoder-android) from 1.0.3 to 1.0.4. - [Release notes](https://github.com/vector-im/libopusencoder-android/releases) - [Commits](https://github.com/vector-im/libopusencoder-android/compare/v1.0.3...v1.0.4) --- updated-dependencies: - dependency-name: io.element.android:opusencoder dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 87031dec37..d783817fef 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -97,7 +97,7 @@ ext.libs = [ 'flipperNetworkPlugin' : "com.facebook.flipper:flipper-network-plugin:$flipper", ], element : [ - 'opusencoder' : "io.element.android:opusencoder:1.0.3", + 'opusencoder' : "io.element.android:opusencoder:1.0.4", ], squareup : [ 'moshi' : "com.squareup.moshi:moshi:$moshi", From c7b54b8d3d23e202877044107694d1e963d8f426 Mon Sep 17 00:00:00 2001 From: Nikita Fedrunov <66663241+fedrunov@users.noreply.github.com> Date: Fri, 15 Jul 2022 12:25:10 +0200 Subject: [PATCH 126/131] legacy groups removal (#6268) --- changelog.d/5733.misc | 1 + changelog.d/5733.sdk | 1 + .../matrix/android/sdk/flow/FlowSession.kt | 9 - .../matrix/android/sdk/api/session/Session.kt | 6 - .../android/sdk/api/session/group/Group.kt | 31 -- .../sdk/api/session/group/GroupService.kt | 51 -- .../session/group/GroupSummaryQueryParams.kt | 44 -- .../api/session/group/model/GroupSummary.kt | 33 -- .../api/session/permalinks/PermalinkData.kt | 4 +- .../api/session/permalinks/PermalinkParser.kt | 22 +- .../session/room/RoomSummaryQueryParams.kt | 6 - .../sdk/api/session/sync/InitialSyncStep.kt | 1 - .../session/sync/model/GroupSyncProfile.kt | 33 -- .../session/sync/model/GroupsSyncResponse.kt | 38 -- .../session/sync/model/InvitedGroupSync.kt | 33 -- .../api/session/sync/model/SyncResponse.kt | 6 - .../matrix/android/sdk/api/util/MatrixItem.kt | 17 - .../database/RealmSessionStoreMigration.kt | 4 +- .../database/mapper/GroupSummaryMapper.kt | 39 -- .../database/migration/MigrateSessionTo010.kt | 2 +- .../migration/MigrateSessionTo032.kt} | 22 +- .../internal/database/model/GroupEntity.kt | 40 -- .../database/model/GroupSummaryEntity.kt | 43 -- .../database/model/RoomSummaryEntity.kt | 5 - .../database/model/SessionRealmModule.kt | 2 - .../database/query/GroupEntityQueries.kt | 34 -- .../query/GroupSummaryEntityQueries.kt | 41 -- .../sdk/internal/session/DefaultSession.kt | 3 - .../sdk/internal/session/SessionComponent.kt | 6 - .../displayname/DisplayNameResolver.kt | 2 +- .../internal/session/group/DefaultGroup.kt | 30 -- .../session/group/DefaultGroupService.kt | 80 --- .../session/group/GetGroupDataTask.kt | 110 ----- .../session/group/GetGroupDataWorker.kt | 59 --- .../sdk/internal/session/group/GroupAPI.kt | 51 -- .../internal/session/group/GroupFactory.kt | 37 -- .../sdk/internal/session/group/GroupModule.kt | 47 -- .../session/group/model/GroupProfile.kt | 49 -- .../internal/session/group/model/GroupRoom.kt | 35 -- .../group/model/GroupSummaryResponse.kt | 46 -- .../group/model/GroupSummaryRoomsSection.kt | 34 -- .../session/group/model/GroupSummaryUser.kt | 37 -- .../group/model/GroupSummaryUsersSection.kt | 35 -- .../internal/session/group/model/GroupUser.kt | 29 -- .../session/group/model/GroupUsers.kt | 26 - .../session/permalinks/PermalinkFactory.kt | 1 - .../room/summary/RoomSummaryDataSource.kt | 3 - .../room/summary/RoomSummaryUpdater.kt | 33 -- .../session/sync/SyncResponseHandler.kt | 52 +- .../session/sync/handler/GroupSyncHandler.kt | 104 ---- .../internal/worker/MatrixWorkerFactory.kt | 3 - .../java/im/vector/app/AppStateHandler.kt | 76 +-- .../analytics/extensions/ViewRoomExt.kt | 10 +- .../group/AutocompleteGroupController.kt | 47 -- .../group/AutocompleteGroupPresenter.kt | 64 --- .../app/features/displayname/Extension.kt | 2 +- .../features/grouplist/GroupSummaryItem.kt | 54 --- .../vector/app/features/home/HomeActivity.kt | 16 +- .../features/home/HomeActivitySharedAction.kt | 3 +- .../app/features/home/HomeDetailFragment.kt | 57 +-- .../app/features/home/HomeDetailViewModel.kt | 105 ++-- .../app/features/home/HomeDetailViewState.kt | 3 +- .../features/home/InitSyncStepFormatter.kt | 1 - .../home/UnreadMessagesSharedViewModel.kt | 120 ++--- .../home/room/detail/AutoCompleter.kt | 24 - .../home/room/detail/TimelineViewModel.kt | 3 +- .../room/list/RoomListFooterController.kt | 3 +- .../home/room/list/RoomListSectionBuilder.kt | 439 ++++++++++++++++- .../room/list/RoomListSectionBuilderGroup.kt | 290 ----------- .../room/list/RoomListSectionBuilderSpace.kt | 459 ------------------ .../home/room/list/RoomListViewModel.kt | 19 +- .../home/room/list/RoomListViewState.kt | 4 +- .../app/features/html/PillsPostProcessor.kt | 6 - .../features/matrixto/MatrixToBottomSheet.kt | 3 +- .../matrixto/MatrixToBottomSheetViewModel.kt | 13 +- .../features/navigation/DefaultNavigator.kt | 103 ++-- .../app/features/navigation/Navigator.kt | 2 +- .../features/permalink/PermalinkHandler.kt | 119 +++-- .../InviteRoomSpaceChooserBottomSheet.kt | 26 +- .../app/features/spaces/SpaceListAction.kt | 3 - .../app/features/spaces/SpaceListFragment.kt | 12 +- .../features/spaces/SpaceListViewEvents.kt | 3 +- .../app/features/spaces/SpaceListViewModel.kt | 36 +- .../app/features/spaces/SpaceListViewState.kt | 5 +- .../features/spaces/SpaceSummaryController.kt | 68 +-- .../ui/SharedPreferencesUiStateRepository.kt | 22 - .../app/features/ui/UiStateRepository.kt | 6 - .../usercode/UserCodeSharedViewModel.kt | 8 +- vector/src/main/res/layout/item_group.xml | 66 --- vector/src/main/res/values/strings.xml | 10 +- 90 files changed, 751 insertions(+), 3039 deletions(-) create mode 100644 changelog.d/5733.misc create mode 100644 changelog.d/5733.sdk delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/Group.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/GroupService.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/GroupSummaryQueryParams.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/model/GroupSummary.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/GroupSyncProfile.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/GroupsSyncResponse.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/InvitedGroupSync.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/GroupSummaryMapper.kt rename matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/{session/group/model/GroupRooms.kt => database/migration/MigrateSessionTo032.kt} (51%) delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/GroupEntity.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/GroupSummaryEntity.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/GroupEntityQueries.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/GroupSummaryEntityQueries.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/DefaultGroup.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/DefaultGroupService.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GetGroupDataTask.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GetGroupDataWorker.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GroupAPI.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GroupFactory.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GroupModule.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupProfile.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupRoom.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryResponse.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryRoomsSection.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryUser.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryUsersSection.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupUser.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupUsers.kt delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/GroupSyncHandler.kt delete mode 100644 vector/src/main/java/im/vector/app/features/autocomplete/group/AutocompleteGroupController.kt delete mode 100644 vector/src/main/java/im/vector/app/features/autocomplete/group/AutocompleteGroupPresenter.kt delete mode 100644 vector/src/main/java/im/vector/app/features/grouplist/GroupSummaryItem.kt delete mode 100644 vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderGroup.kt delete mode 100644 vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderSpace.kt delete mode 100644 vector/src/main/res/layout/item_group.xml diff --git a/changelog.d/5733.misc b/changelog.d/5733.misc new file mode 100644 index 0000000000..0dc1ef881c --- /dev/null +++ b/changelog.d/5733.misc @@ -0,0 +1 @@ +Communities/Groups are removed completely diff --git a/changelog.d/5733.sdk b/changelog.d/5733.sdk new file mode 100644 index 0000000000..0dc1ef881c --- /dev/null +++ b/changelog.d/5733.sdk @@ -0,0 +1 @@ +Communities/Groups are removed completely diff --git a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt index cc73e099b6..f22cfa369a 100644 --- a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt +++ b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt @@ -26,8 +26,6 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo import org.matrix.android.sdk.api.session.crypto.crosssigning.PrivateKeysInfo import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo -import org.matrix.android.sdk.api.session.group.GroupSummaryQueryParams -import org.matrix.android.sdk.api.session.group.model.GroupSummary import org.matrix.android.sdk.api.session.identity.ThreePid import org.matrix.android.sdk.api.session.pushers.Pusher import org.matrix.android.sdk.api.session.room.RoomSortOrder @@ -59,13 +57,6 @@ class FlowSession(private val session: Session) { } } - fun liveGroupSummaries(queryParams: GroupSummaryQueryParams): Flow> { - return session.groupService().getGroupSummariesLive(queryParams).asFlow() - .startWith(session.coroutineDispatchers.io) { - session.groupService().getGroupSummaries(queryParams) - } - } - fun liveSpaceSummaries(queryParams: SpaceSummaryQueryParams): Flow> { return session.spaceService().getSpaceSummariesLive(queryParams).asFlow() .startWith(session.coroutineDispatchers.io) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt index 1b01239de5..63c1c25130 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt @@ -33,7 +33,6 @@ import org.matrix.android.sdk.api.session.crypto.CryptoService import org.matrix.android.sdk.api.session.events.EventService import org.matrix.android.sdk.api.session.file.ContentDownloadStateTracker import org.matrix.android.sdk.api.session.file.FileService -import org.matrix.android.sdk.api.session.group.GroupService import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService import org.matrix.android.sdk.api.session.identity.IdentityService import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService @@ -154,11 +153,6 @@ interface Session { */ fun roomDirectoryService(): RoomDirectoryService - /** - * Returns the GroupService associated with the session. - */ - fun groupService(): GroupService - /** * Returns the UserService associated with the session. */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/Group.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/Group.kt deleted file mode 100644 index 25c69e5025..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/Group.kt +++ /dev/null @@ -1,31 +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.api.session.group - -/** - * This interface defines methods to interact within a group. - */ -interface Group { - val groupId: String - - /** - * This methods allows you to refresh data about this group. It will be reflected on the GroupSummary. - * The SDK also takes care of refreshing group data every hour. - * @return a Cancelable to be able to cancel requests. - */ - suspend fun fetchGroupData() -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/GroupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/GroupService.kt deleted file mode 100644 index 1968af222a..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/GroupService.kt +++ /dev/null @@ -1,51 +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.api.session.group - -import androidx.lifecycle.LiveData -import org.matrix.android.sdk.api.session.group.model.GroupSummary - -/** - * This interface defines methods to get groups. It's implemented at the session level. - */ -interface GroupService { - /** - * Get a group from a groupId. - * @param groupId the groupId to look for. - * @return the group with groupId or null - */ - fun getGroup(groupId: String): Group? - - /** - * Get a groupSummary from a groupId. - * @param groupId the groupId to look for. - * @return the groupSummary with groupId or null - */ - fun getGroupSummary(groupId: String): GroupSummary? - - /** - * Get a list of group summaries. This list is a snapshot of the data. - * @return the list of [GroupSummary] - */ - fun getGroupSummaries(groupSummaryQueryParams: GroupSummaryQueryParams): List - - /** - * Get a live list of group summaries. This list is refreshed as soon as the data changes. - * @return the [LiveData] of [GroupSummary] - */ - fun getGroupSummariesLive(groupSummaryQueryParams: GroupSummaryQueryParams): LiveData> -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/GroupSummaryQueryParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/GroupSummaryQueryParams.kt deleted file mode 100644 index 5104b3ee53..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/GroupSummaryQueryParams.kt +++ /dev/null @@ -1,44 +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.api.session.group - -import org.matrix.android.sdk.api.query.QueryStringValue -import org.matrix.android.sdk.api.session.room.model.Membership - -fun groupSummaryQueryParams(init: (GroupSummaryQueryParams.Builder.() -> Unit) = {}): GroupSummaryQueryParams { - return GroupSummaryQueryParams.Builder().apply(init).build() -} - -/** - * This class can be used to filter group summaries. - */ -data class GroupSummaryQueryParams( - val displayName: QueryStringValue, - val memberships: List -) { - - class Builder { - - var displayName: QueryStringValue = QueryStringValue.IsNotEmpty - var memberships: List = Membership.all() - - fun build() = GroupSummaryQueryParams( - displayName = displayName, - memberships = memberships - ) - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/model/GroupSummary.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/model/GroupSummary.kt deleted file mode 100644 index ef50fce82f..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/model/GroupSummary.kt +++ /dev/null @@ -1,33 +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.api.session.group.model - -import org.matrix.android.sdk.api.session.room.model.Membership - -/** - * This class holds some data of a group. - * It can be retrieved through [org.matrix.android.sdk.api.session.group.GroupService] - */ -data class GroupSummary( - val groupId: String, - val membership: Membership, - val displayName: String = "", - val shortDescription: String = "", - val avatarUrl: String = "", - val roomIds: List = emptyList(), - val userIds: List = emptyList() -) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkData.kt index e8d9c89b54..fc46c92117 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkData.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkData.kt @@ -54,7 +54,5 @@ sealed class PermalinkData { data class UserLink(val userId: String) : PermalinkData() - data class GroupLink(val groupId: String) : PermalinkData() - - data class FallbackLink(val uri: Uri) : PermalinkData() + data class FallbackLink(val uri: Uri, val isLegacyGroupLink: Boolean = false) : PermalinkData() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkParser.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkParser.kt index 0168b7ac3a..3dccc3fbf2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkParser.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkParser.kt @@ -61,27 +61,29 @@ object PermalinkParser { val params = safeFragment .split(MatrixPatterns.SEP_REGEX) .filter { it.isNotEmpty() } - .map { URLDecoder.decode(it, "UTF-8") } .take(2) + val decodedParams = params + .map { URLDecoder.decode(it, "UTF-8") } + val identifier = params.getOrNull(0) - val extraParameter = params.getOrNull(1) + val decodedIdentifier = decodedParams.getOrNull(0) + val extraParameter = decodedParams.getOrNull(1) return when { - identifier.isNullOrEmpty() -> PermalinkData.FallbackLink(uri) - MatrixPatterns.isUserId(identifier) -> PermalinkData.UserLink(userId = identifier) - MatrixPatterns.isGroupId(identifier) -> PermalinkData.GroupLink(groupId = identifier) - MatrixPatterns.isRoomId(identifier) -> { - handleRoomIdCase(fragment, identifier, matrixToUri, extraParameter, viaQueryParameters) + identifier.isNullOrEmpty() || decodedIdentifier.isNullOrEmpty() -> PermalinkData.FallbackLink(uri) + MatrixPatterns.isUserId(decodedIdentifier) -> PermalinkData.UserLink(userId = decodedIdentifier) + MatrixPatterns.isRoomId(decodedIdentifier) -> { + handleRoomIdCase(fragment, decodedIdentifier, matrixToUri, extraParameter, viaQueryParameters) } - MatrixPatterns.isRoomAlias(identifier) -> { + MatrixPatterns.isRoomAlias(decodedIdentifier) -> { PermalinkData.RoomLink( - roomIdOrAlias = identifier, + roomIdOrAlias = decodedIdentifier, isRoomAlias = true, eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) }, viaParameters = viaQueryParameters ) } - else -> PermalinkData.FallbackLink(uri) + else -> PermalinkData.FallbackLink(uri, MatrixPatterns.isGroupId(identifier)) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSummaryQueryParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSummaryQueryParams.kt index 3d943473e4..00c6da00b7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSummaryQueryParams.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSummaryQueryParams.kt @@ -87,10 +87,6 @@ data class RoomSummaryQueryParams( * Used to filter room using the current space. */ val spaceFilter: SpaceFilter?, - /** - * Used to filter room using the current group. - */ - val activeGroupId: String? = null ) { /** @@ -106,7 +102,6 @@ data class RoomSummaryQueryParams( var excludeType: List? = listOf(RoomType.SPACE) var includeType: List? = null var spaceFilter: SpaceFilter? = null - var activeGroupId: String? = null fun build() = RoomSummaryQueryParams( displayName = displayName, @@ -117,7 +112,6 @@ data class RoomSummaryQueryParams( excludeType = excludeType, includeType = includeType, spaceFilter = spaceFilter, - activeGroupId = activeGroupId ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/InitialSyncStep.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/InitialSyncStep.kt index 407585b003..c4a3638ac4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/InitialSyncStep.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/InitialSyncStep.kt @@ -22,7 +22,6 @@ enum class InitialSyncStep { ImportingAccount, ImportingAccountCrypto, ImportingAccountRoom, - ImportingAccountGroups, ImportingAccountData, ImportingAccountJoinedRooms, ImportingAccountInvitedRooms, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/GroupSyncProfile.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/GroupSyncProfile.kt deleted file mode 100644 index 581e6824ee..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/GroupSyncProfile.kt +++ /dev/null @@ -1,33 +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.api.session.sync.model - -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass - -@JsonClass(generateAdapter = true) -data class GroupSyncProfile( - /** - * The name of the group, if any. May be nil. - */ - @Json(name = "name") val name: String? = null, - - /** - * The URL for the group's avatar. May be nil. - */ - @Json(name = "avatar_url") val avatarUrl: String? = null -) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/GroupsSyncResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/GroupsSyncResponse.kt deleted file mode 100644 index fd8710bbda..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/GroupsSyncResponse.kt +++ /dev/null @@ -1,38 +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.api.session.sync.model - -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass - -@JsonClass(generateAdapter = true) -data class GroupsSyncResponse( - /** - * Joined groups: An array of groups ids. - */ - @Json(name = "join") val join: Map = emptyMap(), - - /** - * Invitations. The groups that the user has been invited to: keys are groups ids. - */ - @Json(name = "invite") val invite: Map = emptyMap(), - - /** - * Left groups. An array of groups ids: the groups that the user has left or been banned from. - */ - @Json(name = "leave") val leave: Map = emptyMap() -) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/InvitedGroupSync.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/InvitedGroupSync.kt deleted file mode 100644 index d41df9f0f6..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/InvitedGroupSync.kt +++ /dev/null @@ -1,33 +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.api.session.sync.model - -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass - -@JsonClass(generateAdapter = true) -data class InvitedGroupSync( - /** - * The identifier of the inviter. - */ - @Json(name = "inviter") val inviter: String? = null, - - /** - * The group profile. - */ - @Json(name = "profile") val profile: GroupSyncProfile? = null -) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/SyncResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/SyncResponse.kt index c70964a513..382d8a1740 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/SyncResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/SyncResponse.kt @@ -65,10 +65,4 @@ data class SyncResponse( */ @Json(name = "org.matrix.msc2732.device_unused_fallback_key_types") val deviceUnusedFallbackKeyTypes: List? = null, - - /** - * List of groups. - */ - @Json(name = "groups") val groups: GroupsSyncResponse? = null - ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt index 26dd31dc2d..974f1cfcbe 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt @@ -18,7 +18,6 @@ package org.matrix.android.sdk.api.util import org.matrix.android.sdk.BuildConfig import org.matrix.android.sdk.api.extensions.tryOrNull -import org.matrix.android.sdk.api.session.group.model.GroupSummary import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.RoomType @@ -113,19 +112,6 @@ sealed class MatrixItem( override fun updateAvatar(newAvatar: String?) = copy(avatarUrl = newAvatar) } - data class GroupItem( - override val id: String, - override val displayName: String? = null, - override val avatarUrl: String? = null - ) : - MatrixItem(id, displayName, avatarUrl) { - init { - if (BuildConfig.DEBUG) checkId() - } - - override fun updateAvatar(newAvatar: String?) = copy(avatarUrl = newAvatar) - } - protected fun checkId() { if (!id.startsWith(getIdPrefix())) { error("Wrong usage of MatrixItem: check the id $id should start with ${getIdPrefix()}") @@ -144,7 +130,6 @@ sealed class MatrixItem( is RoomItem, is EveryoneInRoomItem -> '!' is RoomAliasItem -> '#' - is GroupItem -> '+' } fun firstLetterOfDisplayName(): String { @@ -196,8 +181,6 @@ sealed class MatrixItem( fun User.toMatrixItem() = MatrixItem.UserItem(userId, displayName, avatarUrl) -fun GroupSummary.toMatrixItem() = MatrixItem.GroupItem(groupId, displayName, avatarUrl) - fun RoomSummary.toMatrixItem() = if (roomType == RoomType.SPACE) { MatrixItem.SpaceItem(roomId, displayName, avatarUrl) } else { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt index 665567bf2a..9be1717f32 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt @@ -49,6 +49,7 @@ import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo028 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo029 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo030 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo031 +import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo032 import org.matrix.android.sdk.internal.util.Normalizer import timber.log.Timber import javax.inject.Inject @@ -63,7 +64,7 @@ internal class RealmSessionStoreMigration @Inject constructor( override fun equals(other: Any?) = other is RealmSessionStoreMigration override fun hashCode() = 1000 - val schemaVersion = 31L + val schemaVersion = 32L override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) { Timber.d("Migrating Realm Session from $oldVersion to $newVersion") @@ -99,5 +100,6 @@ internal class RealmSessionStoreMigration @Inject constructor( if (oldVersion < 29) MigrateSessionTo029(realm).perform() if (oldVersion < 30) MigrateSessionTo030(realm).perform() if (oldVersion < 31) MigrateSessionTo031(realm).perform() + if (oldVersion < 32) MigrateSessionTo032(realm).perform() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/GroupSummaryMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/GroupSummaryMapper.kt deleted file mode 100644 index 13c3a796c4..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/GroupSummaryMapper.kt +++ /dev/null @@ -1,39 +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.database.mapper - -import org.matrix.android.sdk.api.session.group.model.GroupSummary -import org.matrix.android.sdk.internal.database.model.GroupSummaryEntity - -internal object GroupSummaryMapper { - - fun map(groupSummaryEntity: GroupSummaryEntity): GroupSummary { - return GroupSummary( - groupSummaryEntity.groupId, - groupSummaryEntity.membership, - groupSummaryEntity.displayName, - groupSummaryEntity.shortDescription, - groupSummaryEntity.avatarUrl, - groupSummaryEntity.roomIds.toList(), - groupSummaryEntity.userIds.toList() - ) - } -} - -internal fun GroupSummaryEntity.asDomain(): GroupSummary { - return GroupSummaryMapper.map(this) -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo010.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo010.kt index aae80423ac..27423a9dca 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo010.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo010.kt @@ -49,7 +49,7 @@ internal class MigrateSessionTo010(realm: DynamicRealm) : RealmMigrator(realm, 1 realm.schema.get("RoomSummaryEntity") ?.addField(RoomSummaryEntityFields.ROOM_TYPE, String::class.java) ?.addField(RoomSummaryEntityFields.FLATTEN_PARENT_IDS, String::class.java) - ?.addField(RoomSummaryEntityFields.GROUP_IDS, String::class.java) + ?.addField("groupIds", String::class.java) ?.transform { obj -> val creationEvent = realm.where("CurrentStateEventEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupRooms.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo032.kt similarity index 51% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupRooms.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo032.kt index 9e5d18225b..1506b8c8b3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupRooms.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo032.kt @@ -1,11 +1,11 @@ /* - * 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. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -14,15 +14,15 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.session.group.model +package org.matrix.android.sdk.internal.database.migration -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass +import io.realm.DynamicRealm +import org.matrix.android.sdk.internal.util.database.RealmMigrator -@JsonClass(generateAdapter = true) -internal data class GroupRooms( +internal class MigrateSessionTo032(realm: DynamicRealm) : RealmMigrator(realm, 32) { - @Json(name = "total_room_count_estimate") val totalRoomCountEstimate: Int? = null, - @Json(name = "chunk") val rooms: List = emptyList() - -) + override fun doMigrate(realm: DynamicRealm) { + realm.schema.get("RoomSummaryEntity") + ?.removeField("groupIds") + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/GroupEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/GroupEntity.kt deleted file mode 100644 index 0120bb91d3..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/GroupEntity.kt +++ /dev/null @@ -1,40 +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.database.model - -import io.realm.RealmObject -import io.realm.annotations.PrimaryKey -import org.matrix.android.sdk.api.session.room.model.Membership - -/** - * This class is used to store group info (groupId and membership) from the sync response. - * Then GetGroupDataTask is called regularly to fetch group information from the homeserver. - */ -internal open class GroupEntity(@PrimaryKey var groupId: String = "") : - RealmObject() { - - private var membershipStr: String = Membership.NONE.name - var membership: Membership - get() { - return Membership.valueOf(membershipStr) - } - set(value) { - membershipStr = value.name - } - - companion object -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/GroupSummaryEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/GroupSummaryEntity.kt deleted file mode 100644 index d965148559..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/GroupSummaryEntity.kt +++ /dev/null @@ -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.database.model - -import io.realm.RealmList -import io.realm.RealmObject -import io.realm.annotations.PrimaryKey -import org.matrix.android.sdk.api.session.room.model.Membership - -internal open class GroupSummaryEntity( - @PrimaryKey var groupId: String = "", - var displayName: String = "", - var shortDescription: String = "", - var avatarUrl: String = "", - var roomIds: RealmList = RealmList(), - var userIds: RealmList = RealmList() -) : RealmObject() { - - private var membershipStr: String = Membership.NONE.name - var membership: Membership - get() { - return Membership.valueOf(membershipStr) - } - set(value) { - membershipStr = value.name - } - - companion object -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomSummaryEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomSummaryEntity.kt index cd755590be..5fb4c3f3d8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomSummaryEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomSummaryEntity.kt @@ -240,11 +240,6 @@ internal open class RoomSummaryEntity( if (value != field) field = value } - var groupIds: String? = null - set(value) { - if (value != field) field = value - } - @Index private var membershipStr: String = Membership.NONE.name diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/SessionRealmModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/SessionRealmModule.kt index 890c2300f8..d131589dd1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/SessionRealmModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/SessionRealmModule.kt @@ -32,8 +32,6 @@ import org.matrix.android.sdk.internal.database.model.threads.ThreadSummaryEntit EventInsertEntity::class, TimelineEventEntity::class, FilterEntity::class, - GroupEntity::class, - GroupSummaryEntity::class, ReadReceiptEntity::class, RoomEntity::class, RoomSummaryEntity::class, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/GroupEntityQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/GroupEntityQueries.kt deleted file mode 100644 index 020592d1dd..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/GroupEntityQueries.kt +++ /dev/null @@ -1,34 +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.database.query - -import io.realm.Realm -import io.realm.RealmQuery -import io.realm.kotlin.where -import org.matrix.android.sdk.api.session.room.model.Membership -import org.matrix.android.sdk.internal.database.model.GroupEntity -import org.matrix.android.sdk.internal.database.model.GroupEntityFields -import org.matrix.android.sdk.internal.query.process - -internal fun GroupEntity.Companion.where(realm: Realm, groupId: String): RealmQuery { - return realm.where() - .equalTo(GroupEntityFields.GROUP_ID, groupId) -} - -internal fun GroupEntity.Companion.where(realm: Realm, memberships: List): RealmQuery { - return realm.where().process(GroupEntityFields.MEMBERSHIP_STR, memberships) -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/GroupSummaryEntityQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/GroupSummaryEntityQueries.kt deleted file mode 100644 index 8131598d95..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/GroupSummaryEntityQueries.kt +++ /dev/null @@ -1,41 +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.database.query - -import io.realm.Realm -import io.realm.RealmQuery -import io.realm.kotlin.createObject -import io.realm.kotlin.where -import org.matrix.android.sdk.internal.database.model.GroupSummaryEntity -import org.matrix.android.sdk.internal.database.model.GroupSummaryEntityFields - -internal fun GroupSummaryEntity.Companion.where(realm: Realm, groupId: String? = null): RealmQuery { - val query = realm.where() - if (groupId != null) { - query.equalTo(GroupSummaryEntityFields.GROUP_ID, groupId) - } - return query -} - -internal fun GroupSummaryEntity.Companion.where(realm: Realm, groupIds: List): RealmQuery { - return realm.where() - .`in`(GroupSummaryEntityFields.GROUP_ID, groupIds.toTypedArray()) -} - -internal fun GroupSummaryEntity.Companion.getOrCreate(realm: Realm, groupId: String): GroupSummaryEntity { - return where(realm, groupId).findFirst() ?: realm.createObject(groupId) -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt index 7c50a0ff84..57db187bdc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt @@ -41,7 +41,6 @@ import org.matrix.android.sdk.api.session.crypto.CryptoService import org.matrix.android.sdk.api.session.events.EventService import org.matrix.android.sdk.api.session.file.ContentDownloadStateTracker import org.matrix.android.sdk.api.session.file.FileService -import org.matrix.android.sdk.api.session.group.GroupService import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService import org.matrix.android.sdk.api.session.identity.IdentityService import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService @@ -97,7 +96,6 @@ internal class DefaultSession @Inject constructor( private val sessionListeners: SessionListeners, private val roomService: Lazy, private val roomDirectoryService: Lazy, - private val groupService: Lazy, private val userService: Lazy, private val filterService: Lazy, private val federationService: Lazy, @@ -209,7 +207,6 @@ internal class DefaultSession @Inject constructor( override fun homeServerCapabilitiesService(): HomeServerCapabilitiesService = homeServerCapabilitiesService.get() override fun roomService(): RoomService = roomService.get() override fun roomDirectoryService(): RoomDirectoryService = roomDirectoryService.get() - override fun groupService(): GroupService = groupService.get() override fun userService(): UserService = userService.get() override fun signOutService(): SignOutService = signOutService.get() override fun filterService(): FilterService = filterService.get() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionComponent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionComponent.kt index d3cae3ac2d..a79f35bcb6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionComponent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionComponent.kt @@ -35,8 +35,6 @@ import org.matrix.android.sdk.internal.session.content.ContentModule import org.matrix.android.sdk.internal.session.content.UploadContentWorker import org.matrix.android.sdk.internal.session.contentscanner.ContentScannerModule import org.matrix.android.sdk.internal.session.filter.FilterModule -import org.matrix.android.sdk.internal.session.group.GetGroupDataWorker -import org.matrix.android.sdk.internal.session.group.GroupModule import org.matrix.android.sdk.internal.session.homeserver.HomeServerCapabilitiesModule import org.matrix.android.sdk.internal.session.identity.IdentityModule import org.matrix.android.sdk.internal.session.integrationmanager.IntegrationManagerModule @@ -74,10 +72,8 @@ import org.matrix.android.sdk.internal.util.system.SystemModule SyncModule::class, HomeServerCapabilitiesModule::class, SignOutModule::class, - GroupModule::class, UserModule::class, FilterModule::class, - GroupModule::class, ContentModule::class, CacheModule::class, MediaModule::class, @@ -124,8 +120,6 @@ internal interface SessionComponent { fun inject(worker: RedactEventWorker) - fun inject(worker: GetGroupDataWorker) - fun inject(worker: UploadContentWorker) fun inject(worker: SyncWorker) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/displayname/DisplayNameResolver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/displayname/DisplayNameResolver.kt index 76d956f9a5..3b0799438e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/displayname/DisplayNameResolver.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/displayname/DisplayNameResolver.kt @@ -25,7 +25,7 @@ internal class DisplayNameResolver @Inject constructor( private val matrixConfiguration: MatrixConfiguration ) { fun getBestName(matrixItem: MatrixItem): String { - return if (matrixItem is MatrixItem.GroupItem || matrixItem is MatrixItem.RoomAliasItem) { + return if (matrixItem is MatrixItem.RoomAliasItem) { // Best name is the id, and we keep the displayName of the room for the case we need the first letter matrixItem.id } else { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/DefaultGroup.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/DefaultGroup.kt deleted file mode 100644 index 9c37d4db6c..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/DefaultGroup.kt +++ /dev/null @@ -1,30 +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.group - -import org.matrix.android.sdk.api.session.group.Group - -internal class DefaultGroup( - override val groupId: String, - private val getGroupDataTask: GetGroupDataTask -) : Group { - - override suspend fun fetchGroupData() { - val params = GetGroupDataTask.Params.FetchWithIds(listOf(groupId)) - getGroupDataTask.execute(params) - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/DefaultGroupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/DefaultGroupService.kt deleted file mode 100644 index 9334d09377..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/DefaultGroupService.kt +++ /dev/null @@ -1,80 +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.group - -import androidx.lifecycle.LiveData -import com.zhuinden.monarchy.Monarchy -import io.realm.Realm -import io.realm.RealmQuery -import org.matrix.android.sdk.api.session.group.Group -import org.matrix.android.sdk.api.session.group.GroupService -import org.matrix.android.sdk.api.session.group.GroupSummaryQueryParams -import org.matrix.android.sdk.api.session.group.model.GroupSummary -import org.matrix.android.sdk.internal.database.mapper.asDomain -import org.matrix.android.sdk.internal.database.model.GroupEntity -import org.matrix.android.sdk.internal.database.model.GroupSummaryEntity -import org.matrix.android.sdk.internal.database.model.GroupSummaryEntityFields -import org.matrix.android.sdk.internal.database.query.where -import org.matrix.android.sdk.internal.di.SessionDatabase -import org.matrix.android.sdk.internal.query.QueryStringValueProcessor -import org.matrix.android.sdk.internal.query.process -import org.matrix.android.sdk.internal.util.fetchCopyMap -import javax.inject.Inject - -internal class DefaultGroupService @Inject constructor( - @SessionDatabase private val monarchy: Monarchy, - private val groupFactory: GroupFactory, - private val queryStringValueProcessor: QueryStringValueProcessor, -) : GroupService { - - override fun getGroup(groupId: String): Group? { - return Realm.getInstance(monarchy.realmConfiguration).use { realm -> - GroupEntity.where(realm, groupId).findFirst()?.let { - groupFactory.create(groupId) - } - } - } - - override fun getGroupSummary(groupId: String): GroupSummary? { - return monarchy.fetchCopyMap( - { realm -> GroupSummaryEntity.where(realm, groupId).findFirst() }, - { it, _ -> it.asDomain() } - ) - } - - override fun getGroupSummaries(groupSummaryQueryParams: GroupSummaryQueryParams): List { - return monarchy.fetchAllMappedSync( - { groupSummariesQuery(it, groupSummaryQueryParams) }, - { it.asDomain() } - ) - } - - override fun getGroupSummariesLive(groupSummaryQueryParams: GroupSummaryQueryParams): LiveData> { - return monarchy.findAllMappedWithChanges( - { groupSummariesQuery(it, groupSummaryQueryParams) }, - { it.asDomain() } - ) - } - - private fun groupSummariesQuery(realm: Realm, queryParams: GroupSummaryQueryParams): RealmQuery { - return with(queryStringValueProcessor) { - GroupSummaryEntity.where(realm) - .process(GroupSummaryEntityFields.DISPLAY_NAME, queryParams.displayName) - .process(GroupSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships) - } - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GetGroupDataTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GetGroupDataTask.kt deleted file mode 100644 index 235291d061..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GetGroupDataTask.kt +++ /dev/null @@ -1,110 +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.group - -import com.zhuinden.monarchy.Monarchy -import org.matrix.android.sdk.api.session.room.model.Membership -import org.matrix.android.sdk.internal.database.model.GroupEntity -import org.matrix.android.sdk.internal.database.model.GroupSummaryEntity -import org.matrix.android.sdk.internal.database.query.getOrCreate -import org.matrix.android.sdk.internal.database.query.where -import org.matrix.android.sdk.internal.di.SessionDatabase -import org.matrix.android.sdk.internal.network.GlobalErrorReceiver -import org.matrix.android.sdk.internal.network.executeRequest -import org.matrix.android.sdk.internal.session.group.model.GroupRooms -import org.matrix.android.sdk.internal.session.group.model.GroupSummaryResponse -import org.matrix.android.sdk.internal.session.group.model.GroupUsers -import org.matrix.android.sdk.internal.task.Task -import org.matrix.android.sdk.internal.util.awaitTransaction -import timber.log.Timber -import javax.inject.Inject - -internal interface GetGroupDataTask : Task { - sealed class Params { - object FetchAllActive : Params() - data class FetchWithIds(val groupIds: List) : Params() - } -} - -internal class DefaultGetGroupDataTask @Inject constructor( - private val groupAPI: GroupAPI, - @SessionDatabase private val monarchy: Monarchy, - private val globalErrorReceiver: GlobalErrorReceiver -) : GetGroupDataTask { - - private data class GroupData( - val groupId: String, - val groupSummary: GroupSummaryResponse, - val groupRooms: GroupRooms, - val groupUsers: GroupUsers - ) - - override suspend fun execute(params: GetGroupDataTask.Params) { - val groupIds = when (params) { - is GetGroupDataTask.Params.FetchAllActive -> { - getActiveGroupIds() - } - is GetGroupDataTask.Params.FetchWithIds -> { - params.groupIds - } - } - Timber.v("Fetch data for group with ids: ${groupIds.joinToString(";")}") - val data = groupIds.map { groupId -> - val groupSummary = executeRequest(globalErrorReceiver) { - groupAPI.getSummary(groupId) - } - val groupRooms = executeRequest(globalErrorReceiver) { - groupAPI.getRooms(groupId) - } - val groupUsers = executeRequest(globalErrorReceiver) { - groupAPI.getUsers(groupId) - } - GroupData(groupId, groupSummary, groupRooms, groupUsers) - } - insertInDb(data) - } - - private fun getActiveGroupIds(): List { - return monarchy.fetchAllMappedSync( - { realm -> - GroupEntity.where(realm, Membership.activeMemberships()) - }, - { it.groupId } - ) - } - - private suspend fun insertInDb(groupDataList: List) { - monarchy - .awaitTransaction { realm -> - groupDataList.forEach { groupData -> - - val groupSummaryEntity = GroupSummaryEntity.getOrCreate(realm, groupData.groupId) - - groupSummaryEntity.avatarUrl = groupData.groupSummary.profile?.avatarUrl ?: "" - val name = groupData.groupSummary.profile?.name - groupSummaryEntity.displayName = if (name.isNullOrEmpty()) groupData.groupId else name - groupSummaryEntity.shortDescription = groupData.groupSummary.profile?.shortDescription ?: "" - - groupSummaryEntity.roomIds.clear() - groupData.groupRooms.rooms.mapTo(groupSummaryEntity.roomIds) { it.roomId } - - groupSummaryEntity.userIds.clear() - groupData.groupUsers.users.mapTo(groupSummaryEntity.userIds) { it.userId } - } - } - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GetGroupDataWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GetGroupDataWorker.kt deleted file mode 100644 index 21582cb4be..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GetGroupDataWorker.kt +++ /dev/null @@ -1,59 +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.group - -import android.content.Context -import androidx.work.WorkerParameters -import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.internal.SessionManager -import org.matrix.android.sdk.internal.session.SessionComponent -import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker -import org.matrix.android.sdk.internal.worker.SessionWorkerParams -import javax.inject.Inject - -/** - * Possible previous worker: None. - * Possible next worker : None. - */ -internal class GetGroupDataWorker(context: Context, params: WorkerParameters, sessionManager: SessionManager) : - SessionSafeCoroutineWorker(context, params, sessionManager, Params::class.java) { - - @JsonClass(generateAdapter = true) - internal data class Params( - override val sessionId: String, - override val lastFailureMessage: String? = null - ) : SessionWorkerParams - - @Inject lateinit var getGroupDataTask: GetGroupDataTask - - override fun injectWith(injector: SessionComponent) { - injector.inject(this) - } - - override suspend fun doSafeWork(params: Params): Result { - return runCatching { - getGroupDataTask.execute(GetGroupDataTask.Params.FetchAllActive) - }.fold( - { Result.success() }, - { Result.retry() } - ) - } - - override fun buildErrorParams(params: Params, message: String): Params { - return params.copy(lastFailureMessage = params.lastFailureMessage ?: message) - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GroupAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GroupAPI.kt deleted file mode 100644 index c9d25b9104..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GroupAPI.kt +++ /dev/null @@ -1,51 +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.group - -import org.matrix.android.sdk.internal.network.NetworkConstants -import org.matrix.android.sdk.internal.session.group.model.GroupRooms -import org.matrix.android.sdk.internal.session.group.model.GroupSummaryResponse -import org.matrix.android.sdk.internal.session.group.model.GroupUsers -import retrofit2.http.GET -import retrofit2.http.Path - -internal interface GroupAPI { - - /** - * Request a group summary. - * - * @param groupId the group id - */ - @GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "groups/{groupId}/summary") - suspend fun getSummary(@Path("groupId") groupId: String): GroupSummaryResponse - - /** - * Request the rooms list. - * - * @param groupId the group id - */ - @GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "groups/{groupId}/rooms") - suspend fun getRooms(@Path("groupId") groupId: String): GroupRooms - - /** - * Request the users list. - * - * @param groupId the group id - */ - @GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "groups/{groupId}/users") - suspend fun getUsers(@Path("groupId") groupId: String): GroupUsers -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GroupFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GroupFactory.kt deleted file mode 100644 index 653d2a6933..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GroupFactory.kt +++ /dev/null @@ -1,37 +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.group - -import org.matrix.android.sdk.api.session.group.Group -import org.matrix.android.sdk.internal.session.SessionScope -import javax.inject.Inject - -internal interface GroupFactory { - fun create(groupId: String): Group -} - -@SessionScope -internal class DefaultGroupFactory @Inject constructor(private val getGroupDataTask: GetGroupDataTask) : - GroupFactory { - - override fun create(groupId: String): Group { - return DefaultGroup( - groupId = groupId, - getGroupDataTask = getGroupDataTask - ) - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GroupModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GroupModule.kt deleted file mode 100644 index 4dd61aa914..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GroupModule.kt +++ /dev/null @@ -1,47 +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.group - -import dagger.Binds -import dagger.Module -import dagger.Provides -import org.matrix.android.sdk.api.session.group.GroupService -import org.matrix.android.sdk.internal.session.SessionScope -import retrofit2.Retrofit - -@Module -internal abstract class GroupModule { - - @Module - companion object { - @Provides - @JvmStatic - @SessionScope - fun providesGroupAPI(retrofit: Retrofit): GroupAPI { - return retrofit.create(GroupAPI::class.java) - } - } - - @Binds - abstract fun bindGroupFactory(factory: DefaultGroupFactory): GroupFactory - - @Binds - abstract fun bindGetGroupDataTask(task: DefaultGetGroupDataTask): GetGroupDataTask - - @Binds - abstract fun bindGroupService(service: DefaultGroupService): GroupService -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupProfile.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupProfile.kt deleted file mode 100644 index 30eeb74b2e..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupProfile.kt +++ /dev/null @@ -1,49 +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.group.model - -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass - -/** - * This class represents a community profile in the server responses. - */ -@JsonClass(generateAdapter = true) -internal data class GroupProfile( - - @Json(name = "short_description") val shortDescription: String? = null, - - /** - * Tell whether the group is public. - */ - @Json(name = "is_public") val isPublic: Boolean? = null, - - /** - * The URL for the group's avatar. May be nil. - */ - @Json(name = "avatar_url") val avatarUrl: String? = null, - - /** - * The group's name. - */ - @Json(name = "name") val name: String? = null, - - /** - * The optional HTML formatted string used to described the group. - */ - @Json(name = "long_description") val longDescription: String? = null -) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupRoom.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupRoom.kt deleted file mode 100644 index 86e64f6797..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupRoom.kt +++ /dev/null @@ -1,35 +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.group.model - -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass - -@JsonClass(generateAdapter = true) -internal data class GroupRoom( - - @Json(name = "aliases") val aliases: List = emptyList(), - @Json(name = "canonical_alias") val canonicalAlias: String? = null, - @Json(name = "name") val name: String? = null, - @Json(name = "num_joined_members") val numJoinedMembers: Int = 0, - @Json(name = "room_id") val roomId: String, - @Json(name = "topic") val topic: String? = null, - @Json(name = "world_readable") val worldReadable: Boolean = false, - @Json(name = "guest_can_join") val guestCanJoin: Boolean = false, - @Json(name = "avatar_url") val avatarUrl: String? = null - -) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryResponse.kt deleted file mode 100644 index bf287e982c..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryResponse.kt +++ /dev/null @@ -1,46 +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.group.model - -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass - -/** - * This class represents the summary of a community in the server response. - */ -@JsonClass(generateAdapter = true) -internal data class GroupSummaryResponse( - /** - * The group profile. - */ - @Json(name = "profile") val profile: GroupProfile? = null, - - /** - * The group users. - */ - @Json(name = "users_section") val usersSection: GroupSummaryUsersSection? = null, - - /** - * The current user status. - */ - @Json(name = "user") val user: GroupSummaryUser? = null, - - /** - * The rooms linked to the community. - */ - @Json(name = "rooms_section") val roomsSection: GroupSummaryRoomsSection? = null -) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryRoomsSection.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryRoomsSection.kt deleted file mode 100644 index 87d07167ce..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryRoomsSection.kt +++ /dev/null @@ -1,34 +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.group.model - -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass - -/** - * This class represents the community rooms in a group summary response. - */ -@JsonClass(generateAdapter = true) -internal data class GroupSummaryRoomsSection( - - @Json(name = "total_room_count_estimate") val totalRoomCountEstimate: Int? = null, - - @Json(name = "rooms") val rooms: List = emptyList() - - // TODO Check the meaning and the usage of these categories. This dictionary is empty FTM. - // public Map categories; -) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryUser.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryUser.kt deleted file mode 100644 index 121ae6fd7d..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryUser.kt +++ /dev/null @@ -1,37 +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.group.model - -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass - -/** - * This class represents the current user status in a group summary response. - */ -@JsonClass(generateAdapter = true) -internal data class GroupSummaryUser( - - /** - * The current user membership in this community. - */ - @Json(name = "membership") val membership: String? = null, - - /** - * Tell whether the user published this community on his profile. - */ - @Json(name = "is_publicised") val isPublicised: Boolean? = null -) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryUsersSection.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryUsersSection.kt deleted file mode 100644 index 63608c582a..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryUsersSection.kt +++ /dev/null @@ -1,35 +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.group.model - -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass - -/** - * This class represents the community members in a group summary response. - */ - -@JsonClass(generateAdapter = true) -internal data class GroupSummaryUsersSection( - - @Json(name = "total_user_count_estimate") val totalUserCountEstimate: Int, - - @Json(name = "users") val users: List = emptyList() - - // TODO Check the meaning and the usage of these roles. This dictionary is empty FTM. - // public Map roles; -) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupUser.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupUser.kt deleted file mode 100644 index a54c66535e..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupUser.kt +++ /dev/null @@ -1,29 +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.group.model - -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass - -@JsonClass(generateAdapter = true) -internal data class GroupUser( - @Json(name = "display_name") val displayName: String = "", - @Json(name = "user_id") val userId: String, - @Json(name = "is_privileged") val isPrivileged: Boolean = false, - @Json(name = "avatar_url") val avatarUrl: String? = "", - @Json(name = "is_public") val isPublic: Boolean = false -) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupUsers.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupUsers.kt deleted file mode 100644 index 9dd1339157..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupUsers.kt +++ /dev/null @@ -1,26 +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.group.model - -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass - -@JsonClass(generateAdapter = true) -internal data class GroupUsers( - @Json(name = "total_user_count_estimate") val totalUserCountEstimate: Int, - @Json(name = "chunk") val users: List = emptyList() -) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/PermalinkFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/PermalinkFactory.kt index 8e20199135..3ecd47787f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/PermalinkFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/PermalinkFactory.kt @@ -97,7 +97,6 @@ internal class PermalinkFactory @Inject constructor( url.startsWith(MATRIX_TO_URL_BASE) -> url.substring(MATRIX_TO_URL_BASE.length) clientBaseUrl != null && url.startsWith(clientBaseUrl) -> { when (PermalinkParser.parse(url)) { - is PermalinkData.GroupLink -> url.substring(clientBaseUrl.length + GROUP_PATH.length) is PermalinkData.RoomLink -> url.substring(clientBaseUrl.length + ROOM_PATH.length) is PermalinkData.UserLink -> url.substring(clientBaseUrl.length + USER_PATH.length) else -> null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt index cb7dc270e8..80e27a1415 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt @@ -328,9 +328,6 @@ internal class RoomSummaryDataSource @Inject constructor( null -> Unit // nop } - queryParams.activeGroupId?.let { activeGroupId -> - query.contains(RoomSummaryEntityFields.GROUP_IDS, activeGroupId) - } return query } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt index e4afe7aa49..a721aeb935 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt @@ -44,7 +44,6 @@ import org.matrix.android.sdk.internal.crypto.crosssigning.DefaultCrossSigningSe import org.matrix.android.sdk.internal.database.mapper.ContentMapper import org.matrix.android.sdk.internal.database.mapper.asDomain import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity -import org.matrix.android.sdk.internal.database.model.GroupSummaryEntity import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntityFields import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields @@ -438,38 +437,6 @@ internal class RoomSummaryUpdater @Inject constructor( space.notificationCount = notificationCount } // xxx invites?? - - // LEGACY GROUPS - // lets mark rooms that belongs to groups - val existingGroups = GroupSummaryEntity.where(realm).findAll() - - // For rooms - realm.where(RoomSummaryEntity::class.java) - .process(RoomSummaryEntityFields.MEMBERSHIP_STR, Membership.activeMemberships()) - .equalTo(RoomSummaryEntityFields.IS_DIRECT, false) - .findAll().forEach { room -> - val belongsTo = existingGroups.filter { it.roomIds.contains(room.roomId) } - room.groupIds = if (belongsTo.isEmpty()) { - null - } else { - "|${belongsTo.joinToString("|")}|" - } - } - - // For DMS - realm.where(RoomSummaryEntity::class.java) - .process(RoomSummaryEntityFields.MEMBERSHIP_STR, Membership.activeMemberships()) - .equalTo(RoomSummaryEntityFields.IS_DIRECT, true) - .findAll().forEach { room -> - val belongsTo = existingGroups.filter { - it.userIds.intersect(room.otherMemberIds).isNotEmpty() - } - room.groupIds = if (belongsTo.isEmpty()) { - null - } else { - "|${belongsTo.joinToString("|")}|" - } - } }.also { Timber.v("## SPACES: Finish checking room hierarchy in $it ms") } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponseHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponseHandler.kt index 9e5302222a..392c73bd83 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponseHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponseHandler.kt @@ -16,47 +16,36 @@ package org.matrix.android.sdk.internal.session.sync -import androidx.work.ExistingPeriodicWorkPolicy import com.zhuinden.monarchy.Monarchy import org.matrix.android.sdk.api.session.pushrules.PushRuleService import org.matrix.android.sdk.api.session.pushrules.RuleScope import org.matrix.android.sdk.api.session.sync.InitialSyncStep -import org.matrix.android.sdk.api.session.sync.model.GroupsSyncResponse import org.matrix.android.sdk.api.session.sync.model.RoomsSyncResponse import org.matrix.android.sdk.api.session.sync.model.SyncResponse import org.matrix.android.sdk.internal.SessionManager import org.matrix.android.sdk.internal.crypto.DefaultCryptoService import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.di.SessionId -import org.matrix.android.sdk.internal.di.WorkManagerProvider import org.matrix.android.sdk.internal.session.SessionListeners import org.matrix.android.sdk.internal.session.dispatchTo -import org.matrix.android.sdk.internal.session.group.GetGroupDataWorker import org.matrix.android.sdk.internal.session.pushrules.ProcessEventForPushTask import org.matrix.android.sdk.internal.session.sync.handler.CryptoSyncHandler -import org.matrix.android.sdk.internal.session.sync.handler.GroupSyncHandler import org.matrix.android.sdk.internal.session.sync.handler.PresenceSyncHandler import org.matrix.android.sdk.internal.session.sync.handler.SyncResponsePostTreatmentAggregatorHandler import org.matrix.android.sdk.internal.session.sync.handler.UserAccountDataSyncHandler import org.matrix.android.sdk.internal.session.sync.handler.room.RoomSyncHandler import org.matrix.android.sdk.internal.util.awaitTransaction -import org.matrix.android.sdk.internal.worker.WorkerParamsFactory import timber.log.Timber -import java.util.concurrent.TimeUnit import javax.inject.Inject import kotlin.system.measureTimeMillis -private const val GET_GROUP_DATA_WORKER = "GET_GROUP_DATA_WORKER" - internal class SyncResponseHandler @Inject constructor( @SessionDatabase private val monarchy: Monarchy, @SessionId private val sessionId: String, private val sessionManager: SessionManager, private val sessionListeners: SessionListeners, - private val workManagerProvider: WorkManagerProvider, private val roomSyncHandler: RoomSyncHandler, private val userAccountDataSyncHandler: UserAccountDataSyncHandler, - private val groupSyncHandler: GroupSyncHandler, private val cryptoSyncHandler: CryptoSyncHandler, private val aggregatorHandler: SyncResponsePostTreatmentAggregatorHandler, private val cryptoService: DefaultCryptoService, @@ -109,7 +98,7 @@ internal class SyncResponseHandler @Inject constructor( // IMPORTANT nothing should be suspend here as we are accessing the realm instance (thread local) measureTimeMillis { Timber.v("Handle rooms") - reportSubtask(reporter, InitialSyncStep.ImportingAccountRoom, 1, 0.7f) { + reportSubtask(reporter, InitialSyncStep.ImportingAccountRoom, 1, 0.8f) { if (syncResponse.rooms != null) { roomSyncHandler.handle(realm, syncResponse.rooms, isInitialSync, aggregator, reporter) } @@ -118,17 +107,6 @@ internal class SyncResponseHandler @Inject constructor( Timber.v("Finish handling rooms in $it ms") } - measureTimeMillis { - reportSubtask(reporter, InitialSyncStep.ImportingAccountGroups, 1, 0.1f) { - Timber.v("Handle groups") - if (syncResponse.groups != null) { - groupSyncHandler.handle(realm, syncResponse.groups, reporter) - } - } - }.also { - Timber.v("Finish handling groups in $it ms") - } - measureTimeMillis { reportSubtask(reporter, InitialSyncStep.ImportingAccountData, 1, 0.1f) { Timber.v("Handle accountData") @@ -155,9 +133,6 @@ internal class SyncResponseHandler @Inject constructor( userAccountDataSyncHandler.synchronizeWithServerIfNeeded(it.invite) dispatchInvitedRoom(it) } - syncResponse.groups?.let { - scheduleGroupDataFetchingIfNeeded(it) - } Timber.v("On sync completed") cryptoSyncHandler.onSyncCompleted(syncResponse) @@ -177,31 +152,6 @@ internal class SyncResponseHandler @Inject constructor( } } - /** - * At the moment we don't get any group data through the sync, so we poll where every hour. - * You can also force to refetch group data using [Group] API. - */ - private fun scheduleGroupDataFetchingIfNeeded(groupsSyncResponse: GroupsSyncResponse) { - val groupIds = ArrayList() - groupIds.addAll(groupsSyncResponse.join.keys) - groupIds.addAll(groupsSyncResponse.invite.keys) - if (groupIds.isEmpty()) { - Timber.v("No new groups to fetch data for.") - return - } - Timber.v("There are ${groupIds.size} new groups to fetch data for.") - val getGroupDataWorkerParams = GetGroupDataWorker.Params(sessionId) - val workData = WorkerParamsFactory.toData(getGroupDataWorkerParams) - - val getGroupWork = workManagerProvider.matrixPeriodicWorkRequestBuilder(1, TimeUnit.HOURS) - .setInputData(workData) - .setConstraints(WorkManagerProvider.workConstraints) - .build() - - workManagerProvider.workManager - .enqueueUniquePeriodicWork(GET_GROUP_DATA_WORKER, ExistingPeriodicWorkPolicy.REPLACE, getGroupWork) - } - private suspend fun checkPushRules(roomsSyncResponse: RoomsSyncResponse, isInitialSync: Boolean) { Timber.v("[PushRules] --> checkPushRules") if (isInitialSync) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/GroupSyncHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/GroupSyncHandler.kt deleted file mode 100644 index 1983d9f433..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/GroupSyncHandler.kt +++ /dev/null @@ -1,104 +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.sync.handler - -import io.realm.Realm -import org.matrix.android.sdk.api.session.room.model.Membership -import org.matrix.android.sdk.api.session.sync.InitialSyncStep -import org.matrix.android.sdk.api.session.sync.model.GroupsSyncResponse -import org.matrix.android.sdk.api.session.sync.model.InvitedGroupSync -import org.matrix.android.sdk.internal.database.model.GroupEntity -import org.matrix.android.sdk.internal.database.model.GroupSummaryEntity -import org.matrix.android.sdk.internal.database.query.getOrCreate -import org.matrix.android.sdk.internal.database.query.where -import org.matrix.android.sdk.internal.session.sync.ProgressReporter -import org.matrix.android.sdk.internal.session.sync.mapWithProgress -import javax.inject.Inject - -internal class GroupSyncHandler @Inject constructor() { - - sealed class HandlingStrategy { - data class JOINED(val data: Map) : HandlingStrategy() - data class INVITED(val data: Map) : HandlingStrategy() - data class LEFT(val data: Map) : HandlingStrategy() - } - - fun handle( - realm: Realm, - roomsSyncResponse: GroupsSyncResponse, - reporter: ProgressReporter? = null - ) { - handleGroupSync(realm, HandlingStrategy.JOINED(roomsSyncResponse.join), reporter) - handleGroupSync(realm, HandlingStrategy.INVITED(roomsSyncResponse.invite), reporter) - handleGroupSync(realm, HandlingStrategy.LEFT(roomsSyncResponse.leave), reporter) - } - - // PRIVATE METHODS ***************************************************************************** - - private fun handleGroupSync(realm: Realm, handlingStrategy: HandlingStrategy, reporter: ProgressReporter?) { - val groups = when (handlingStrategy) { - is HandlingStrategy.JOINED -> - handlingStrategy.data.mapWithProgress(reporter, InitialSyncStep.ImportingAccountGroups, 0.6f) { - handleJoinedGroup(realm, it.key) - } - - is HandlingStrategy.INVITED -> - handlingStrategy.data.mapWithProgress(reporter, InitialSyncStep.ImportingAccountGroups, 0.3f) { - handleInvitedGroup(realm, it.key) - } - - is HandlingStrategy.LEFT -> - handlingStrategy.data.mapWithProgress(reporter, InitialSyncStep.ImportingAccountGroups, 0.1f) { - handleLeftGroup(realm, it.key) - } - } - realm.insertOrUpdate(groups) - } - - private fun handleJoinedGroup( - realm: Realm, - groupId: String - ): GroupEntity { - val groupEntity = GroupEntity.where(realm, groupId).findFirst() ?: GroupEntity(groupId) - val groupSummaryEntity = GroupSummaryEntity.getOrCreate(realm, groupId) - groupEntity.membership = Membership.JOIN - groupSummaryEntity.membership = Membership.JOIN - return groupEntity - } - - private fun handleInvitedGroup( - realm: Realm, - groupId: String - ): GroupEntity { - val groupEntity = GroupEntity.where(realm, groupId).findFirst() ?: GroupEntity(groupId) - val groupSummaryEntity = GroupSummaryEntity.getOrCreate(realm, groupId) - groupEntity.membership = Membership.INVITE - groupSummaryEntity.membership = Membership.INVITE - return groupEntity - } - - private fun handleLeftGroup( - realm: Realm, - groupId: String - ): GroupEntity { - val groupEntity = GroupEntity.where(realm, groupId).findFirst() ?: GroupEntity(groupId) - val groupSummaryEntity = GroupSummaryEntity.getOrCreate(realm, groupId) - groupEntity.membership = Membership.LEAVE - groupSummaryEntity.membership = Membership.LEAVE - return groupEntity - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/MatrixWorkerFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/MatrixWorkerFactory.kt index 52146ef484..83f9532870 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/MatrixWorkerFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/MatrixWorkerFactory.kt @@ -25,7 +25,6 @@ import org.matrix.android.sdk.internal.SessionManager import org.matrix.android.sdk.internal.crypto.crosssigning.UpdateTrustWorker import org.matrix.android.sdk.internal.di.MatrixScope import org.matrix.android.sdk.internal.session.content.UploadContentWorker -import org.matrix.android.sdk.internal.session.group.GetGroupDataWorker import org.matrix.android.sdk.internal.session.pushers.AddPusherWorker import org.matrix.android.sdk.internal.session.room.aggregation.livelocation.DeactivateLiveLocationShareWorker import org.matrix.android.sdk.internal.session.room.send.MultipleEventSendingDispatcherWorker @@ -53,8 +52,6 @@ internal class MatrixWorkerFactory @Inject constructor(private val sessionManage CheckFactoryWorker(appContext, workerParameters, true) AddPusherWorker::class.java.name -> AddPusherWorker(appContext, workerParameters, sessionManager) - GetGroupDataWorker::class.java.name -> - GetGroupDataWorker(appContext, workerParameters, sessionManager) MultipleEventSendingDispatcherWorker::class.java.name -> MultipleEventSendingDispatcherWorker(appContext, workerParameters, sessionManager) RedactEventWorker::class.java.name -> diff --git a/vector/src/main/java/im/vector/app/AppStateHandler.kt b/vector/src/main/java/im/vector/app/AppStateHandler.kt index d366927d6d..e1b8bfc474 100644 --- a/vector/src/main/java/im/vector/app/AppStateHandler.kt +++ b/vector/src/main/java/im/vector/app/AppStateHandler.kt @@ -40,20 +40,11 @@ import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.getRoomSummary -import org.matrix.android.sdk.api.session.group.model.GroupSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.sync.SyncRequestState import javax.inject.Inject import javax.inject.Singleton -sealed class RoomGroupingMethod { - data class ByLegacyGroup(val groupSummary: GroupSummary?) : RoomGroupingMethod() - data class BySpace(val spaceSummary: RoomSummary?) : RoomGroupingMethod() -} - -fun RoomGroupingMethod.space() = (this as? RoomGroupingMethod.BySpace)?.spaceSummary -fun RoomGroupingMethod.group() = (this as? RoomGroupingMethod.ByLegacyGroup)?.groupSummary - /** * This class handles the global app state. * It requires to be added to ProcessLifecycleOwner.get().lifecycle @@ -68,29 +59,20 @@ class AppStateHandler @Inject constructor( ) : DefaultLifecycleObserver { private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main) - private val selectedSpaceDataSource = BehaviorDataSource>(Option.empty()) + private val selectedSpaceDataSource = BehaviorDataSource>(Option.empty()) - val selectedRoomGroupingFlow = selectedSpaceDataSource.stream() + val selectedSpaceFlow = selectedSpaceDataSource.stream() private val spaceBackstack = ArrayDeque() - fun getCurrentRoomGroupingMethod(): RoomGroupingMethod? { - // XXX we should somehow make it live :/ just a work around - // For example just after creating a space and switching to it the - // name in the app Bar could show Empty Room, and it will not update unless you - // switch space - return selectedSpaceDataSource.currentValue?.orNull()?.let { - if (it is RoomGroupingMethod.BySpace) { - // try to refresh sum? - it.spaceSummary?.roomId?.let { activeSessionHolder.getSafeActiveSession()?.roomService()?.getRoomSummary(it) }?.let { - RoomGroupingMethod.BySpace(it) - } ?: it - } else it + fun getCurrentSpace(): RoomSummary? { + return selectedSpaceDataSource.currentValue?.orNull()?.let { spaceSummary -> + activeSessionHolder.getSafeActiveSession()?.roomService()?.getRoomSummary(spaceSummary.roomId) } } fun setCurrentSpace(spaceId: String?, session: Session? = null, persistNow: Boolean = false, isForwardNavigation: Boolean = true) { - val currentSpace = (selectedSpaceDataSource.currentValue?.orNull() as? RoomGroupingMethod.BySpace)?.space() + val currentSpace = selectedSpaceDataSource.currentValue?.orNull() val uSession = session ?: activeSessionHolder.getSafeActiveSession() ?: return if (currentSpace != null && spaceId == currentSpace.roomId) return val spaceSum = spaceId?.let { uSession.getRoomSummary(spaceId) } @@ -100,11 +82,15 @@ class AppStateHandler @Inject constructor( } if (persistNow) { - uiStateRepository.storeGroupingMethod(true, uSession.sessionId) uiStateRepository.storeSelectedSpace(spaceSum?.roomId, uSession.sessionId) } - selectedSpaceDataSource.post(Option.just(RoomGroupingMethod.BySpace(spaceSum))) + if (spaceSum == null) { + selectedSpaceDataSource.post(Option.empty()) + } else { + selectedSpaceDataSource.post(Option.just(spaceSum)) + } + if (spaceId != null) { uSession.coroutineScope.launch(Dispatchers.IO) { tryOrNull { @@ -114,32 +100,13 @@ class AppStateHandler @Inject constructor( } } - fun setCurrentGroup(groupId: String?, session: Session? = null) { - val uSession = session ?: activeSessionHolder.getSafeActiveSession() ?: return - if (selectedSpaceDataSource.currentValue?.orNull() is RoomGroupingMethod.ByLegacyGroup && - groupId == selectedSpaceDataSource.currentValue?.orNull()?.group()?.groupId) return - val activeGroup = groupId?.let { uSession.groupService().getGroupSummary(groupId) } - selectedSpaceDataSource.post(Option.just(RoomGroupingMethod.ByLegacyGroup(activeGroup))) - if (groupId != null) { - uSession.coroutineScope.launch { - tryOrNull { - uSession.groupService().getGroup(groupId)?.fetchGroupData() - } - } - } - } - private fun observeActiveSession() { sessionDataSource.stream() .distinctUntilChanged() .onEach { // sessionDataSource could already return a session while activeSession holder still returns null it.orNull()?.let { session -> - if (uiStateRepository.isGroupingMethodSpace(session.sessionId)) { - setCurrentSpace(uiStateRepository.getSelectedSpace(session.sessionId), session) - } else { - setCurrentGroup(uiStateRepository.getSelectedGroup(session.sessionId), session) - } + setCurrentSpace(uiStateRepository.getSelectedSpace(session.sessionId), session) observeSyncStatus(session) } } @@ -160,11 +127,7 @@ class AppStateHandler @Inject constructor( fun getSpaceBackstack() = spaceBackstack fun safeActiveSpaceId(): String? { - return (selectedSpaceDataSource.currentValue?.orNull() as? RoomGroupingMethod.BySpace)?.spaceSummary?.roomId - } - - fun safeActiveGroupId(): String? { - return (selectedSpaceDataSource.currentValue?.orNull() as? RoomGroupingMethod.ByLegacyGroup)?.groupSummary?.groupId + return selectedSpaceDataSource.currentValue?.orNull()?.roomId } override fun onResume(owner: LifecycleOwner) { @@ -174,15 +137,6 @@ class AppStateHandler @Inject constructor( override fun onPause(owner: LifecycleOwner) { coroutineScope.coroutineContext.cancelChildren() val session = activeSessionHolder.getSafeActiveSession() ?: return - when (val currentMethod = selectedSpaceDataSource.currentValue?.orNull() ?: RoomGroupingMethod.BySpace(null)) { - is RoomGroupingMethod.BySpace -> { - uiStateRepository.storeGroupingMethod(true, session.sessionId) - uiStateRepository.storeSelectedSpace(currentMethod.spaceSummary?.roomId, session.sessionId) - } - is RoomGroupingMethod.ByLegacyGroup -> { - uiStateRepository.storeGroupingMethod(false, session.sessionId) - uiStateRepository.storeSelectedGroup(currentMethod.groupSummary?.groupId, session.sessionId) - } - } + uiStateRepository.storeSelectedSpace(selectedSpaceDataSource.currentValue?.orNull()?.roomId, session.sessionId) } } diff --git a/vector/src/main/java/im/vector/app/features/analytics/extensions/ViewRoomExt.kt b/vector/src/main/java/im/vector/app/features/analytics/extensions/ViewRoomExt.kt index b259477ebd..d8c3481eee 100644 --- a/vector/src/main/java/im/vector/app/features/analytics/extensions/ViewRoomExt.kt +++ b/vector/src/main/java/im/vector/app/features/analytics/extensions/ViewRoomExt.kt @@ -16,19 +16,13 @@ package im.vector.app.features.analytics.extensions -import im.vector.app.RoomGroupingMethod import im.vector.app.features.analytics.plan.ViewRoom import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.RoomType -fun RoomSummary?.toAnalyticsViewRoom(trigger: ViewRoom.Trigger?, groupingMethod: RoomGroupingMethod? = null, viaKeyboard: Boolean? = null): ViewRoom { - val activeSpace = groupingMethod?.let { - when (it) { - is RoomGroupingMethod.BySpace -> it.spaceSummary?.toActiveSpace() ?: ViewRoom.ActiveSpace.Home - else -> null - } - } +fun RoomSummary?.toAnalyticsViewRoom(trigger: ViewRoom.Trigger?, selectedSpace: RoomSummary? = null, viaKeyboard: Boolean? = null): ViewRoom { + val activeSpace = selectedSpace?.toActiveSpace() ?: ViewRoom.ActiveSpace.Home return ViewRoom( isDM = this?.isDirect.orFalse(), diff --git a/vector/src/main/java/im/vector/app/features/autocomplete/group/AutocompleteGroupController.kt b/vector/src/main/java/im/vector/app/features/autocomplete/group/AutocompleteGroupController.kt deleted file mode 100644 index 49987b69ea..0000000000 --- a/vector/src/main/java/im/vector/app/features/autocomplete/group/AutocompleteGroupController.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.app.features.autocomplete.group - -import com.airbnb.epoxy.TypedEpoxyController -import im.vector.app.features.autocomplete.AutocompleteClickListener -import im.vector.app.features.autocomplete.autocompleteMatrixItem -import im.vector.app.features.home.AvatarRenderer -import org.matrix.android.sdk.api.session.group.model.GroupSummary -import org.matrix.android.sdk.api.util.toMatrixItem -import javax.inject.Inject - -class AutocompleteGroupController @Inject constructor() : TypedEpoxyController>() { - - var listener: AutocompleteClickListener? = null - - @Inject lateinit var avatarRenderer: AvatarRenderer - - override fun buildModels(data: List?) { - if (data.isNullOrEmpty()) { - return - } - val host = this - data.forEach { groupSummary -> - autocompleteMatrixItem { - id(groupSummary.groupId) - matrixItem(groupSummary.toMatrixItem()) - avatarRenderer(host.avatarRenderer) - clickListener { host.listener?.onItemClick(groupSummary) } - } - } - } -} diff --git a/vector/src/main/java/im/vector/app/features/autocomplete/group/AutocompleteGroupPresenter.kt b/vector/src/main/java/im/vector/app/features/autocomplete/group/AutocompleteGroupPresenter.kt deleted file mode 100644 index 32a1bed1c6..0000000000 --- a/vector/src/main/java/im/vector/app/features/autocomplete/group/AutocompleteGroupPresenter.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.app.features.autocomplete.group - -import android.content.Context -import androidx.recyclerview.widget.RecyclerView -import im.vector.app.features.autocomplete.AutocompleteClickListener -import im.vector.app.features.autocomplete.RecyclerViewPresenter -import org.matrix.android.sdk.api.query.QueryStringValue -import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.api.session.group.groupSummaryQueryParams -import org.matrix.android.sdk.api.session.group.model.GroupSummary -import javax.inject.Inject - -class AutocompleteGroupPresenter @Inject constructor( - context: Context, - private val controller: AutocompleteGroupController, - private val session: Session -) : RecyclerViewPresenter(context), AutocompleteClickListener { - - init { - controller.listener = this - } - - fun clear() { - controller.listener = null - } - - override fun instantiateAdapter(): RecyclerView.Adapter<*> { - return controller.adapter - } - - override fun onItemClick(t: GroupSummary) { - dispatchClick(t) - } - - override fun onQuery(query: CharSequence?) { - val queryParams = groupSummaryQueryParams { - displayName = if (query.isNullOrBlank()) { - QueryStringValue.IsNotEmpty - } else { - QueryStringValue.Contains(query.toString(), QueryStringValue.Case.INSENSITIVE) - } - } - val groups = session.groupService().getGroupSummaries(queryParams) - .asSequence() - .sortedBy { it.displayName } - controller.setData(groups.toList()) - } -} diff --git a/vector/src/main/java/im/vector/app/features/displayname/Extension.kt b/vector/src/main/java/im/vector/app/features/displayname/Extension.kt index 6ca1d48464..71c1cbf27d 100644 --- a/vector/src/main/java/im/vector/app/features/displayname/Extension.kt +++ b/vector/src/main/java/im/vector/app/features/displayname/Extension.kt @@ -20,7 +20,7 @@ import org.matrix.android.sdk.api.util.MatrixItem fun MatrixItem.getBestName(): String { // Note: this code is copied from [DisplayNameResolver] in the SDK - return if (this is MatrixItem.GroupItem || this is MatrixItem.RoomAliasItem) { + return if (this is MatrixItem.RoomAliasItem) { // Best name is the id, and we keep the displayName of the room for the case we need the first letter id } else { diff --git a/vector/src/main/java/im/vector/app/features/grouplist/GroupSummaryItem.kt b/vector/src/main/java/im/vector/app/features/grouplist/GroupSummaryItem.kt deleted file mode 100644 index ce2b35b353..0000000000 --- a/vector/src/main/java/im/vector/app/features/grouplist/GroupSummaryItem.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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.app.features.grouplist - -import android.widget.ImageView -import android.widget.TextView -import com.airbnb.epoxy.EpoxyAttribute -import com.airbnb.epoxy.EpoxyModelClass -import im.vector.app.R -import im.vector.app.core.epoxy.ClickListener -import im.vector.app.core.epoxy.VectorEpoxyHolder -import im.vector.app.core.epoxy.VectorEpoxyModel -import im.vector.app.core.epoxy.onClick -import im.vector.app.core.platform.CheckableConstraintLayout -import im.vector.app.features.home.AvatarRenderer -import org.matrix.android.sdk.api.util.MatrixItem - -@EpoxyModelClass -abstract class GroupSummaryItem : VectorEpoxyModel(R.layout.item_group) { - - @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer - @EpoxyAttribute lateinit var matrixItem: MatrixItem - @EpoxyAttribute var selected: Boolean = false - @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var listener: ClickListener? = null - - override fun bind(holder: Holder) { - super.bind(holder) - holder.rootView.onClick(listener) - holder.groupNameView.text = matrixItem.displayName - holder.rootView.isChecked = selected - avatarRenderer.render(matrixItem, holder.avatarImageView) - } - - class Holder : VectorEpoxyHolder() { - val avatarImageView by bind(R.id.groupAvatarImageView) - val groupNameView by bind(R.id.groupNameView) - val rootView by bind(R.id.itemGroupLayout) - } -} diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt index 1c66cdda64..d82621977f 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt @@ -214,13 +214,12 @@ class HomeActivity : when (sharedAction) { is HomeActivitySharedAction.OpenDrawer -> views.drawerLayout.openDrawer(GravityCompat.START) is HomeActivitySharedAction.CloseDrawer -> views.drawerLayout.closeDrawer(GravityCompat.START) - is HomeActivitySharedAction.OpenGroup -> openGroup(sharedAction.shouldClearFragment) is HomeActivitySharedAction.OpenSpacePreview -> startActivity(SpacePreviewActivity.newIntent(this, sharedAction.spaceId)) is HomeActivitySharedAction.AddSpace -> createSpaceResultLauncher.launch(SpaceCreationActivity.newIntent(this)) is HomeActivitySharedAction.ShowSpaceSettings -> showSpaceSettings(sharedAction.spaceId) is HomeActivitySharedAction.OpenSpaceInvite -> openSpaceInvite(sharedAction.spaceId) HomeActivitySharedAction.SendSpaceFeedBack -> bugReporter.openBugReportScreen(this, ReportType.SPACE_BETA_FEEDBACK) - HomeActivitySharedAction.CloseGroup -> closeGroup() + HomeActivitySharedAction.OnCloseSpace -> onCloseSpace() } } .launchIn(lifecycleScope) @@ -265,17 +264,6 @@ class HomeActivity : homeActivityViewModel.handle(HomeActivityViewActions.ViewStarted) } - private fun openGroup(shouldClearFragment: Boolean) { - views.drawerLayout.closeDrawer(GravityCompat.START) - - // When switching from space to group or group to space, we need to reload the fragment - if (shouldClearFragment) { - replaceFragment(views.homeDetailFragmentContainer, HomeDetailFragment::class.java, allowStateLoss = true) - } else { - // do nothing - } - } - private fun showSpaceSettings(spaceId: String) { // open bottom sheet SpaceSettingsMenuBottomSheet @@ -292,7 +280,7 @@ class HomeActivity : .show(supportFragmentManager, "SPACE_INVITE") } - private fun closeGroup() { + private fun onCloseSpace() { views.drawerLayout.openDrawer(GravityCompat.START) } diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivitySharedAction.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivitySharedAction.kt index a16d710f4e..d66bc94899 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivitySharedAction.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivitySharedAction.kt @@ -24,8 +24,7 @@ import im.vector.app.core.platform.VectorSharedAction sealed class HomeActivitySharedAction : VectorSharedAction { object OpenDrawer : HomeActivitySharedAction() object CloseDrawer : HomeActivitySharedAction() - data class OpenGroup(val shouldClearFragment: Boolean) : HomeActivitySharedAction() - object CloseGroup : HomeActivitySharedAction() + object OnCloseSpace : HomeActivitySharedAction() object AddSpace : HomeActivitySharedAction() data class OpenSpacePreview(val spaceId: String) : HomeActivitySharedAction() data class OpenSpaceInvite(val spaceId: String) : HomeActivitySharedAction() diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt index a3bc5144d1..828e4cc26c 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt @@ -30,7 +30,6 @@ import com.airbnb.mvrx.withState import com.google.android.material.badge.BadgeDrawable import im.vector.app.AppStateHandler import im.vector.app.R -import im.vector.app.RoomGroupingMethod import im.vector.app.core.extensions.commitTransaction import im.vector.app.core.extensions.toMvRxBundle import im.vector.app.core.platform.OnBackPressed @@ -58,7 +57,6 @@ import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.workers.signout.BannerState import im.vector.app.features.workers.signout.ServerBackupStatusViewModel import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo -import org.matrix.android.sdk.api.session.group.model.GroupSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary import javax.inject.Inject @@ -130,11 +128,8 @@ class HomeDetailFragment @Inject constructor( views.bottomNavigationView.selectedItemId = it.currentTab.toMenuId() } - viewModel.onEach(HomeDetailViewState::roomGroupingMethod) { roomGroupingMethod -> - when (roomGroupingMethod) { - is RoomGroupingMethod.ByLegacyGroup -> onGroupChange(roomGroupingMethod.groupSummary) - is RoomGroupingMethod.BySpace -> onSpaceChange(roomGroupingMethod.spaceSummary) - } + viewModel.onEach(HomeDetailViewState::selectedSpace) { selectedSpace -> + onSpaceChange(selectedSpace) } viewModel.onEach(HomeDetailViewState::currentTab) { currentTab -> @@ -188,26 +183,16 @@ class HomeDetailFragment @Inject constructor( } private fun navigateBack() { - try { - val lastSpace = appStateHandler.getSpaceBackstack().removeLast() - setCurrentSpace(lastSpace) - } catch (e: NoSuchElementException) { - navigateUpOneSpace() - } + val previousSpaceId = appStateHandler.getSpaceBackstack().removeLastOrNull() + val parentSpaceId = appStateHandler.getCurrentSpace()?.flattenParentIds?.lastOrNull() + setCurrentSpace(previousSpaceId ?: parentSpaceId) } private fun setCurrentSpace(spaceId: String?) { appStateHandler.setCurrentSpace(spaceId, isForwardNavigation = false) - sharedActionViewModel.post(HomeActivitySharedAction.CloseGroup) + sharedActionViewModel.post(HomeActivitySharedAction.OnCloseSpace) } - private fun navigateUpOneSpace() { - val parentId = getCurrentSpace()?.flattenParentIds?.lastOrNull() - setCurrentSpace(parentId) - } - - private fun getCurrentSpace() = (appStateHandler.getCurrentRoomGroupingMethod() as? RoomGroupingMethod.BySpace)?.spaceSummary - private fun handleCallStarted() { dismissLoadingDialog() val fragmentTag = HomeTab.DialPad.toFragmentTag() @@ -227,10 +212,8 @@ class HomeDetailFragment @Inject constructor( } private fun refreshSpaceState() { - when (val roomGroupingMethod = appStateHandler.getCurrentRoomGroupingMethod()) { - is RoomGroupingMethod.ByLegacyGroup -> onGroupChange(roomGroupingMethod.groupSummary) - is RoomGroupingMethod.BySpace -> onSpaceChange(roomGroupingMethod.spaceSummary) - else -> Unit + appStateHandler.getCurrentSpace()?.let { + onSpaceChange(it) } } @@ -291,15 +274,6 @@ class HomeDetailFragment @Inject constructor( ) } - private fun onGroupChange(groupSummary: GroupSummary?) { - if (groupSummary == null) { - views.groupToolbarSpaceTitleView.isVisible = false - } else { - views.groupToolbarSpaceTitleView.isVisible = true - views.groupToolbarSpaceTitleView.text = groupSummary.displayName - } - } - private fun onSpaceChange(spaceSummary: RoomSummary?) { if (spaceSummary == null) { views.groupToolbarSpaceTitleView.isVisible = false @@ -335,16 +309,9 @@ class HomeDetailFragment @Inject constructor( } views.homeToolbarContent.debouncedClicks { - withState(viewModel) { - when (it.roomGroupingMethod) { - is RoomGroupingMethod.ByLegacyGroup -> { - // do nothing - } - is RoomGroupingMethod.BySpace -> { - it.roomGroupingMethod.spaceSummary?.let { spaceSummary -> - sharedActionViewModel.post(HomeActivitySharedAction.ShowSpaceSettings(spaceSummary.roomId)) - } - } + withState(viewModel) { viewState -> + viewState.selectedSpace?.let { + sharedActionViewModel.post(HomeActivitySharedAction.ShowSpaceSettings(it.roomId)) } } } @@ -499,7 +466,7 @@ class HomeDetailFragment @Inject constructor( return this } - override fun onBackPressed(toolbarButton: Boolean) = if (getCurrentSpace() != null) { + override fun onBackPressed(toolbarButton: Boolean) = if (appStateHandler.getCurrentSpace() != null) { navigateBack() true } else { diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt index 485d1e33ec..357d2b7c69 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt @@ -23,7 +23,6 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import im.vector.app.AppStateHandler -import im.vector.app.RoomGroupingMethod import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.extensions.singletonEntryPoint @@ -208,16 +207,16 @@ class HomeDetailViewModel @AssistedInject constructor( } private fun observeRoomGroupingMethod() { - appStateHandler.selectedRoomGroupingFlow + appStateHandler.selectedSpaceFlow .setOnEach { copy( - roomGroupingMethod = it.orNull() ?: RoomGroupingMethod.BySpace(null) + selectedSpace = it.orNull() ) } } private fun observeRoomSummaries() { - appStateHandler.selectedRoomGroupingFlow.distinctUntilChanged().flatMapLatest { + appStateHandler.selectedSpaceFlow.distinctUntilChanged().flatMapLatest { // we use it as a trigger to all changes in room, but do not really load // the actual models session.roomService().getPagedRoomSummariesLive( @@ -229,67 +228,55 @@ class HomeDetailViewModel @AssistedInject constructor( } .throttleFirst(300) .onEach { - when (val groupingMethod = appStateHandler.getCurrentRoomGroupingMethod()) { - is RoomGroupingMethod.ByLegacyGroup -> { - // TODO!! - } - is RoomGroupingMethod.BySpace -> { - val activeSpaceRoomId = groupingMethod.spaceSummary?.roomId - var dmInvites = 0 - var roomsInvite = 0 - if (autoAcceptInvites.showInvites()) { - dmInvites = session.roomService().getRoomSummaries( - roomSummaryQueryParams { - memberships = listOf(Membership.INVITE) - roomCategoryFilter = RoomCategoryFilter.ONLY_DM - spaceFilter = activeSpaceRoomId?.let { SpaceFilter.ActiveSpace(it) } - } - ).size + val activeSpaceRoomId = appStateHandler.getCurrentSpace()?.roomId + var dmInvites = 0 + var roomsInvite = 0 + if (autoAcceptInvites.showInvites()) { + dmInvites = session.roomService().getRoomSummaries( + roomSummaryQueryParams { + memberships = listOf(Membership.INVITE) + roomCategoryFilter = RoomCategoryFilter.ONLY_DM + spaceFilter = activeSpaceRoomId?.let { SpaceFilter.ActiveSpace(it) } + } + ).size - roomsInvite = session.roomService().getRoomSummaries( - roomSummaryQueryParams { - memberships = listOf(Membership.INVITE) - roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS - spaceFilter = groupingMethod.toActiveSpaceOrOrphanRooms() - } - ).size + roomsInvite = session.roomService().getRoomSummaries( + roomSummaryQueryParams { + memberships = listOf(Membership.INVITE) + roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS + spaceFilter = activeSpaceRoomId.toActiveSpaceOrOrphanRooms() + } + ).size + } + + val dmRooms = session.roomService().getNotificationCountForRooms( + roomSummaryQueryParams { + memberships = listOf(Membership.JOIN) + roomCategoryFilter = RoomCategoryFilter.ONLY_DM + spaceFilter = activeSpaceRoomId?.let { SpaceFilter.ActiveSpace(it) } } + ) - val dmRooms = session.roomService().getNotificationCountForRooms( - roomSummaryQueryParams { - memberships = listOf(Membership.JOIN) - roomCategoryFilter = RoomCategoryFilter.ONLY_DM - spaceFilter = activeSpaceRoomId?.let { SpaceFilter.ActiveSpace(it) } - } - ) - - val otherRooms = session.roomService().getNotificationCountForRooms( - roomSummaryQueryParams { - memberships = listOf(Membership.JOIN) - roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS - spaceFilter = groupingMethod.toActiveSpaceOrOrphanRooms() - } - ) - - setState { - copy( - notificationCountCatchup = dmRooms.totalCount + otherRooms.totalCount + roomsInvite + dmInvites, - notificationHighlightCatchup = dmRooms.isHighlight || otherRooms.isHighlight || (dmInvites + roomsInvite) > 0, - notificationCountPeople = dmRooms.totalCount + dmInvites, - notificationHighlightPeople = dmRooms.isHighlight || dmInvites > 0, - notificationCountRooms = otherRooms.totalCount + roomsInvite, - notificationHighlightRooms = otherRooms.isHighlight || roomsInvite > 0, - hasUnreadMessages = dmRooms.totalCount + otherRooms.totalCount > 0 - ) + val otherRooms = session.roomService().getNotificationCountForRooms( + roomSummaryQueryParams { + memberships = listOf(Membership.JOIN) + roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS + spaceFilter = activeSpaceRoomId.toActiveSpaceOrOrphanRooms() } - } - null -> Unit + ) + + setState { + copy( + notificationCountCatchup = dmRooms.totalCount + otherRooms.totalCount + roomsInvite + dmInvites, + notificationHighlightCatchup = dmRooms.isHighlight || otherRooms.isHighlight || (dmInvites + roomsInvite) > 0, + notificationCountPeople = dmRooms.totalCount + dmInvites, + notificationHighlightPeople = dmRooms.isHighlight || dmInvites > 0, + notificationCountRooms = otherRooms.totalCount + roomsInvite, + notificationHighlightRooms = otherRooms.isHighlight || roomsInvite > 0, + hasUnreadMessages = dmRooms.totalCount + otherRooms.totalCount > 0 + ) } } .launchIn(viewModelScope) } - - private fun RoomGroupingMethod.BySpace.toActiveSpaceOrOrphanRooms(): SpaceFilter { - return spaceSummary?.roomId.toActiveSpaceOrOrphanRooms() - } } diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewState.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewState.kt index 7b8319d8d1..7fbd5b2bf6 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewState.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewState.kt @@ -21,14 +21,13 @@ import com.airbnb.mvrx.Async import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.Uninitialized import im.vector.app.R -import im.vector.app.RoomGroupingMethod import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.sync.SyncRequestState import org.matrix.android.sdk.api.session.sync.SyncState import org.matrix.android.sdk.api.util.MatrixItem data class HomeDetailViewState( - val roomGroupingMethod: RoomGroupingMethod = RoomGroupingMethod.BySpace(null), + val selectedSpace: RoomSummary? = null, val myMatrixItem: MatrixItem? = null, val asyncRooms: Async> = Uninitialized, val currentTab: HomeTab = HomeTab.RoomList(RoomListDisplayMode.PEOPLE), diff --git a/vector/src/main/java/im/vector/app/features/home/InitSyncStepFormatter.kt b/vector/src/main/java/im/vector/app/features/home/InitSyncStepFormatter.kt index 884b4266cd..f4626477c7 100644 --- a/vector/src/main/java/im/vector/app/features/home/InitSyncStepFormatter.kt +++ b/vector/src/main/java/im/vector/app/features/home/InitSyncStepFormatter.kt @@ -32,7 +32,6 @@ class InitSyncStepFormatter @Inject constructor( InitialSyncStep.ImportingAccount -> R.string.initial_sync_start_importing_account InitialSyncStep.ImportingAccountCrypto -> R.string.initial_sync_start_importing_account_crypto InitialSyncStep.ImportingAccountRoom -> R.string.initial_sync_start_importing_account_rooms - InitialSyncStep.ImportingAccountGroups -> R.string.initial_sync_start_importing_account_groups InitialSyncStep.ImportingAccountData -> R.string.initial_sync_start_importing_account_data InitialSyncStep.ImportingAccountJoinedRooms -> R.string.initial_sync_start_importing_account_joined_rooms InitialSyncStep.ImportingAccountInvitedRooms -> R.string.initial_sync_start_importing_account_invited_rooms diff --git a/vector/src/main/java/im/vector/app/features/home/UnreadMessagesSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/home/UnreadMessagesSharedViewModel.kt index 723ca7caae..f2e6b7e064 100644 --- a/vector/src/main/java/im/vector/app/features/home/UnreadMessagesSharedViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/UnreadMessagesSharedViewModel.kt @@ -23,7 +23,6 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import im.vector.app.AppStateHandler -import im.vector.app.RoomGroupingMethod import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.EmptyAction @@ -110,8 +109,8 @@ class UnreadMessagesSharedViewModel @AssistedInject constructor( } combine( - appStateHandler.selectedRoomGroupingFlow.distinctUntilChanged(), - appStateHandler.selectedRoomGroupingFlow.flatMapLatest { + appStateHandler.selectedSpaceFlow.distinctUntilChanged(), + appStateHandler.selectedSpaceFlow.flatMapLatest { roomService.getPagedRoomSummariesLive( roomSummaryQueryParams { this.memberships = Membership.activeMemberships() @@ -119,74 +118,57 @@ class UnreadMessagesSharedViewModel @AssistedInject constructor( ).asFlow() .throttleFirst(300) } - ) { groupingMethod, _ -> - when (groupingMethod.orNull()) { - is RoomGroupingMethod.ByLegacyGroup -> { - // currently not supported - CountInfo( - RoomAggregateNotificationCount(0, 0), - RoomAggregateNotificationCount(0, 0) - ) - } - is RoomGroupingMethod.BySpace -> { - val selectedSpace = appStateHandler.safeActiveSpaceId() + ) { selectedSpaceOption, _ -> + val selectedSpace = selectedSpaceOption.orNull()?.roomId - val inviteCount = if (autoAcceptInvites.hideInvites) { - 0 - } else { - roomService.getRoomSummaries( - roomSummaryQueryParams { this.memberships = listOf(Membership.INVITE) } - ).size - } - - val spaceInviteCount = if (autoAcceptInvites.hideInvites) { - 0 - } else { - roomService.getRoomSummaries( - spaceSummaryQueryParams { - this.memberships = listOf(Membership.INVITE) - } - ).size - } - - val totalCount = roomService.getNotificationCountForRooms( - roomSummaryQueryParams { - this.memberships = listOf(Membership.JOIN) - this.spaceFilter = SpaceFilter.OrphanRooms.takeIf { - !vectorPreferences.prefSpacesShowAllRoomInHome() - } - } - ) - - val counts = RoomAggregateNotificationCount( - totalCount.notificationCount + inviteCount, - totalCount.highlightCount + inviteCount - ) - val rootCounts = session.spaceService().getRootSpaceSummaries() - .filter { - // filter out current selection - it.roomId != selectedSpace - } - - CountInfo( - homeCount = counts, - otherCount = RoomAggregateNotificationCount( - notificationCount = rootCounts.fold(0, { acc, rs -> acc + rs.notificationCount }) + - (counts.notificationCount.takeIf { selectedSpace != null } ?: 0) + - spaceInviteCount, - highlightCount = rootCounts.fold(0, { acc, rs -> acc + rs.highlightCount }) + - (counts.highlightCount.takeIf { selectedSpace != null } ?: 0) + - spaceInviteCount - ) - ) - } - null -> { - CountInfo( - RoomAggregateNotificationCount(0, 0), - RoomAggregateNotificationCount(0, 0) - ) - } + val inviteCount = if (autoAcceptInvites.hideInvites) { + 0 + } else { + roomService.getRoomSummaries( + roomSummaryQueryParams { this.memberships = listOf(Membership.INVITE) } + ).size } + + val spaceInviteCount = if (autoAcceptInvites.hideInvites) { + 0 + } else { + roomService.getRoomSummaries( + spaceSummaryQueryParams { + this.memberships = listOf(Membership.INVITE) + } + ).size + } + + val totalCount = roomService.getNotificationCountForRooms( + roomSummaryQueryParams { + this.memberships = listOf(Membership.JOIN) + this.spaceFilter = SpaceFilter.OrphanRooms.takeIf { + !vectorPreferences.prefSpacesShowAllRoomInHome() + } + } + ) + + val counts = RoomAggregateNotificationCount( + totalCount.notificationCount + inviteCount, + totalCount.highlightCount + inviteCount + ) + val rootCounts = session.spaceService().getRootSpaceSummaries() + .filter { + // filter out current selection + it.roomId != selectedSpace + } + + CountInfo( + homeCount = counts, + otherCount = RoomAggregateNotificationCount( + notificationCount = rootCounts.fold(0, { acc, rs -> acc + rs.notificationCount }) + + (counts.notificationCount.takeIf { selectedSpace != null } ?: 0) + + spaceInviteCount, + highlightCount = rootCounts.fold(0, { acc, rs -> acc + rs.highlightCount }) + + (counts.highlightCount.takeIf { selectedSpace != null } ?: 0) + + spaceInviteCount + ) + ) } .flowOn(Dispatchers.Default) .execute { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt index 68053ed890..51e1fb06f2 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt @@ -32,7 +32,6 @@ import im.vector.app.core.glide.GlideRequests import im.vector.app.features.autocomplete.command.AutocompleteCommandPresenter import im.vector.app.features.autocomplete.command.CommandAutocompletePolicy import im.vector.app.features.autocomplete.emoji.AutocompleteEmojiPresenter -import im.vector.app.features.autocomplete.group.AutocompleteGroupPresenter import im.vector.app.features.autocomplete.member.AutocompleteMemberItem import im.vector.app.features.autocomplete.member.AutocompleteMemberPresenter import im.vector.app.features.autocomplete.room.AutocompleteRoomPresenter @@ -41,7 +40,6 @@ import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.html.PillImageSpan import im.vector.app.features.themes.ThemeUtils -import org.matrix.android.sdk.api.session.group.model.GroupSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.util.MatrixItem import org.matrix.android.sdk.api.util.toEveryoneInRoomMatrixItem @@ -56,7 +54,6 @@ class AutoCompleter @AssistedInject constructor( autocompleteCommandPresenterFactory: AutocompleteCommandPresenter.Factory, private val autocompleteMemberPresenterFactory: AutocompleteMemberPresenter.Factory, private val autocompleteRoomPresenter: AutocompleteRoomPresenter, - private val autocompleteGroupPresenter: AutocompleteGroupPresenter, private val autocompleteEmojiPresenter: AutocompleteEmojiPresenter ) { @@ -89,7 +86,6 @@ class AutoCompleter @AssistedInject constructor( val backgroundDrawable = ColorDrawable(ThemeUtils.getColor(editText.context, android.R.attr.colorBackground)) setupCommands(backgroundDrawable, editText) setupMembers(backgroundDrawable, editText) - setupGroups(backgroundDrawable, editText) setupEmojis(backgroundDrawable, editText) setupRooms(backgroundDrawable, editText) } @@ -97,7 +93,6 @@ class AutoCompleter @AssistedInject constructor( fun clear() { this.editText = null autocompleteEmojiPresenter.clear() - autocompleteGroupPresenter.clear() autocompleteRoomPresenter.clear() autocompleteCommandPresenter.clear() autocompleteMemberPresenter.clear() @@ -170,24 +165,6 @@ class AutoCompleter @AssistedInject constructor( .build() } - private fun setupGroups(backgroundDrawable: ColorDrawable, editText: EditText) { - Autocomplete.on(editText) - .with(CharPolicy(TRIGGER_AUTO_COMPLETE_GROUPS, true)) - .with(autocompleteGroupPresenter) - .with(ELEVATION_DP) - .with(backgroundDrawable) - .with(object : AutocompleteCallback { - override fun onPopupItemClicked(editable: Editable, item: GroupSummary): Boolean { - insertMatrixItem(editText, editable, TRIGGER_AUTO_COMPLETE_GROUPS, item.toMatrixItem()) - return true - } - - override fun onPopupVisibilityChanged(shown: Boolean) { - } - }) - .build() - } - private fun setupEmojis(backgroundDrawable: Drawable, editText: EditText) { Autocomplete.on(editText) .with(CharPolicy(TRIGGER_AUTO_COMPLETE_EMOJIS, false)) @@ -262,7 +239,6 @@ class AutoCompleter @AssistedInject constructor( private const val ELEVATION_DP = 6f private const val TRIGGER_AUTO_COMPLETE_MEMBERS = '@' private const val TRIGGER_AUTO_COMPLETE_ROOMS = '#' - private const val TRIGGER_AUTO_COMPLETE_GROUPS = '+' private const val TRIGGER_AUTO_COMPLETE_EMOJIS = ':' } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt index 194db8bce7..e305ccbec1 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt @@ -61,7 +61,6 @@ import im.vector.app.features.raw.wellknown.withElementWellKnown import im.vector.app.features.session.coroutineScope import im.vector.app.features.settings.VectorDataStore import im.vector.app.features.settings.VectorPreferences -import im.vector.app.space import im.vector.lib.core.utils.flow.chunk import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableSharedFlow @@ -219,7 +218,7 @@ class TimelineViewModel @AssistedInject constructor( if (initialState.switchToParentSpace) { // We are coming from a notification, try to switch to the most relevant space // so that when hitting back the room will appear in the list - appStateHandler.getCurrentRoomGroupingMethod()?.space().let { currentSpace -> + appStateHandler.getCurrentSpace().let { currentSpace -> val currentRoomSummary = room.roomSummary() ?: return@let // nothing we are good if ((currentSpace == null && !vectorPreferences.prefSpacesShowAllRoomInHome()) || diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFooterController.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFooterController.kt index df009e8d6b..269af4afa0 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFooterController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFooterController.kt @@ -24,7 +24,6 @@ import im.vector.app.core.resources.UserPreferencesProvider import im.vector.app.features.home.RoomListDisplayMode import im.vector.app.features.home.room.filtered.FilteredRoomFooterItem import im.vector.app.features.home.room.filtered.filteredRoomFooterItem -import im.vector.app.space import javax.inject.Inject class RoomListFooterController @Inject constructor( @@ -42,7 +41,7 @@ class RoomListFooterController @Inject constructor( id("filter_footer") listener(host.listener) currentFilter(data.roomFilter) - inSpace(data.currentRoomGrouping.invoke()?.space() != null) + inSpace(data.asyncSelectedSpace.invoke() != null) } } else -> { diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilder.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilder.kt index c98f613c40..42634c237a 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilder.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilder.kt @@ -16,8 +16,443 @@ package im.vector.app.features.home.room.list +import androidx.annotation.StringRes +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.asFlow +import androidx.lifecycle.liveData +import androidx.paging.PagedList +import com.airbnb.mvrx.Async +import im.vector.app.AppStateHandler +import im.vector.app.R +import im.vector.app.core.resources.StringProvider import im.vector.app.features.home.RoomListDisplayMode +import im.vector.app.features.invite.AutoAcceptInvites +import im.vector.app.features.invite.showInvites +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.update +import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.api.query.RoomCategoryFilter +import org.matrix.android.sdk.api.query.RoomTagQueryFilter +import org.matrix.android.sdk.api.query.SpaceFilter +import org.matrix.android.sdk.api.query.toActiveSpaceOrOrphanRooms +import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.getRoomSummary +import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams +import org.matrix.android.sdk.api.session.room.UpdatableLivePageResult +import org.matrix.android.sdk.api.session.room.model.Membership +import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams +import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount +import timber.log.Timber -interface RoomListSectionBuilder { - fun buildSections(mode: RoomListDisplayMode): List +class RoomListSectionBuilder( + private val session: Session, + private val stringProvider: StringProvider, + private val appStateHandler: AppStateHandler, + private val viewModelScope: CoroutineScope, + private val autoAcceptInvites: AutoAcceptInvites, + private val onUpdatable: (UpdatableLivePageResult) -> Unit, + private val suggestedRoomJoiningState: LiveData>>, + private val onlyOrphansInHome: Boolean = false +) { + + private val pagedListConfig = PagedList.Config.Builder() + .setPageSize(10) + .setInitialLoadSizeHint(20) + .setEnablePlaceholders(true) + .setPrefetchDistance(10) + .build() + + fun buildSections(mode: RoomListDisplayMode): List { + val sections = mutableListOf() + val activeSpaceAwareQueries = mutableListOf() + when (mode) { + RoomListDisplayMode.PEOPLE -> { + // 4 sections Invites / Fav / Dms / Low Priority + buildDmSections(sections, activeSpaceAwareQueries) + } + RoomListDisplayMode.ROOMS -> { + // 6 sections invites / Fav / Rooms / Low Priority / Server notice / Suggested rooms + buildRoomsSections(sections, activeSpaceAwareQueries) + } + RoomListDisplayMode.FILTERED -> { + // Used when searching for rooms + buildFilteredSection(sections) + } + RoomListDisplayMode.NOTIFICATIONS -> { + buildNotificationsSection(sections, activeSpaceAwareQueries) + } + } + + appStateHandler.selectedSpaceFlow + .distinctUntilChanged() + .onEach { selectedSpaceOption -> + val selectedSpace = selectedSpaceOption.orNull() + activeSpaceAwareQueries.onEach { updater -> + updater.updateForSpaceId(selectedSpace?.roomId) + } + }.launchIn(viewModelScope) + + return sections + } + + private fun buildRoomsSections( + sections: MutableList, + activeSpaceAwareQueries: MutableList + ) { + if (autoAcceptInvites.showInvites()) { + addSection( + sections = sections, + activeSpaceUpdaters = activeSpaceAwareQueries, + nameRes = R.string.invitations_header, + notifyOfLocalEcho = true, + spaceFilterStrategy = RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL, + countRoomAsNotif = true + ) { + it.memberships = listOf(Membership.INVITE) + it.roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS + } + } + + addSection( + sections, + activeSpaceAwareQueries, + R.string.bottom_action_favourites, + false, + RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL + ) { + it.memberships = listOf(Membership.JOIN) + it.roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS + it.roomTagQueryFilter = RoomTagQueryFilter(true, null, null) + } + + addSection( + sections = sections, + activeSpaceUpdaters = activeSpaceAwareQueries, + nameRes = R.string.bottom_action_rooms, + notifyOfLocalEcho = false, + spaceFilterStrategy = if (onlyOrphansInHome) { + RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL + } else { + RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL + } + ) { + it.memberships = listOf(Membership.JOIN) + it.roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS + it.roomTagQueryFilter = RoomTagQueryFilter(false, false, false) + } + + addSection( + sections = sections, + activeSpaceUpdaters = activeSpaceAwareQueries, + nameRes = R.string.low_priority_header, + notifyOfLocalEcho = false, + spaceFilterStrategy = if (onlyOrphansInHome) { + RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL + } else { + RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL + } + ) { + it.memberships = listOf(Membership.JOIN) + it.roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS + it.roomTagQueryFilter = RoomTagQueryFilter(null, true, null) + } + + addSection( + sections = sections, + activeSpaceUpdaters = activeSpaceAwareQueries, + nameRes = R.string.system_alerts_header, + notifyOfLocalEcho = false, + spaceFilterStrategy = if (onlyOrphansInHome) { + RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL + } else { + RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL + } + ) { + it.memberships = listOf(Membership.JOIN) + it.roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS + it.roomTagQueryFilter = RoomTagQueryFilter(null, null, true) + } + + // add suggested rooms + val suggestedRoomsFlow = // MutableLiveData>() + appStateHandler.selectedSpaceFlow + .distinctUntilChanged() + .flatMapLatest { selectedSpaceOption -> + val selectedSpace = selectedSpaceOption.orNull() + if (selectedSpace == null) { + flowOf(emptyList()) + } else { + liveData(context = viewModelScope.coroutineContext + Dispatchers.IO) { + val spaceSum = tryOrNull { + session.spaceService() + .querySpaceChildren(selectedSpace.roomId, suggestedOnly = true, null, null) + } + val value = spaceSum?.children.orEmpty().distinctBy { it.childRoomId } + // i need to check if it's already joined. + val filtered = value.filter { + session.getRoomSummary(it.childRoomId)?.membership?.isActive() != true + } + emit(filtered) + }.asFlow() + } + } + + val liveSuggestedRooms = MutableLiveData() + combine( + suggestedRoomsFlow, + suggestedRoomJoiningState.asFlow() + ) { rooms, joinStates -> + SuggestedRoomInfo( + rooms, + joinStates + ) + }.onEach { + liveSuggestedRooms.postValue(it) + }.launchIn(viewModelScope) + + sections.add( + RoomsSection( + sectionName = stringProvider.getString(R.string.suggested_header), + liveSuggested = liveSuggestedRooms, + notifyOfLocalEcho = false, + itemCount = suggestedRoomsFlow.map { suggestions -> suggestions.size } + ) + ) + } + + private fun buildDmSections( + sections: MutableList, + activeSpaceAwareQueries: MutableList + ) { + if (autoAcceptInvites.showInvites()) { + addSection( + sections = sections, + activeSpaceUpdaters = activeSpaceAwareQueries, + nameRes = R.string.invitations_header, + notifyOfLocalEcho = true, + spaceFilterStrategy = RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL, + countRoomAsNotif = true + ) { + it.memberships = listOf(Membership.INVITE) + it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM + } + } + + addSection( + sections, + activeSpaceAwareQueries, + R.string.bottom_action_favourites, + false, + RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL + ) { + it.memberships = listOf(Membership.JOIN) + it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM + it.roomTagQueryFilter = RoomTagQueryFilter(true, null, null) + } + + addSection( + sections, + activeSpaceAwareQueries, + R.string.bottom_action_people_x, + false, + RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL + ) { + it.memberships = listOf(Membership.JOIN) + it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM + it.roomTagQueryFilter = RoomTagQueryFilter(false, false, null) + } + + addSection( + sections, + activeSpaceAwareQueries, + R.string.low_priority_header, + false, + RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL + ) { + it.memberships = listOf(Membership.JOIN) + it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM + it.roomTagQueryFilter = RoomTagQueryFilter(false, true, null) + } + } + + private fun buildNotificationsSection( + sections: MutableList, + activeSpaceAwareQueries: MutableList + ) { + if (autoAcceptInvites.showInvites()) { + addSection( + sections = sections, + activeSpaceUpdaters = activeSpaceAwareQueries, + nameRes = R.string.invitations_header, + notifyOfLocalEcho = true, + spaceFilterStrategy = if (onlyOrphansInHome) { + RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL + } else { + RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL + }, + countRoomAsNotif = true + ) { + it.memberships = listOf(Membership.INVITE) + } + } + + addSection( + sections = sections, + activeSpaceUpdaters = activeSpaceAwareQueries, + nameRes = R.string.bottom_action_rooms, + notifyOfLocalEcho = false, + spaceFilterStrategy = if (onlyOrphansInHome) { + RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL + } else { + RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL + } + ) { + it.memberships = listOf(Membership.JOIN) + it.roomCategoryFilter = RoomCategoryFilter.ONLY_WITH_NOTIFICATIONS + } + } + + private fun buildFilteredSection(sections: MutableList) { + // Used when searching for rooms + withQueryParams( + { + it.memberships = Membership.activeMemberships() + }, + { queryParams -> + val name = stringProvider.getString(R.string.bottom_action_rooms) + val updatableFilterLivePageResult = session.roomService().getFilteredPagedRoomSummariesLive(queryParams, getFlattenParents = true) + onUpdatable(updatableFilterLivePageResult) + + val itemCountFlow = updatableFilterLivePageResult.livePagedList.asFlow() + .flatMapLatest { session.roomService().getRoomCountLive(updatableFilterLivePageResult.queryParams).asFlow() } + .distinctUntilChanged() + + sections.add( + RoomsSection( + sectionName = name, + livePages = updatableFilterLivePageResult.livePagedList, + itemCount = itemCountFlow + ) + ) + } + ) + } + + private fun addSection( + sections: MutableList, + activeSpaceUpdaters: MutableList, + @StringRes nameRes: Int, + notifyOfLocalEcho: Boolean = false, + spaceFilterStrategy: RoomListViewModel.SpaceFilterStrategy = RoomListViewModel.SpaceFilterStrategy.NONE, + countRoomAsNotif: Boolean = false, + query: (RoomSummaryQueryParams.Builder) -> Unit + ) { + withQueryParams(query) { roomQueryParams -> + val updatedQueryParams = roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId()) + val liveQueryParams = MutableStateFlow(updatedQueryParams) + val itemCountFlow = liveQueryParams + .flatMapLatest { + session.roomService().getRoomCountLive(it).asFlow() + } + .flowOn(Dispatchers.Main) + .distinctUntilChanged() + + val name = stringProvider.getString(nameRes) + val filteredPagedRoomSummariesLive = session.roomService().getFilteredPagedRoomSummariesLive( + roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId()), + pagedListConfig + ) + when (spaceFilterStrategy) { + RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL -> { + activeSpaceUpdaters.add(object : RoomListViewModel.ActiveSpaceQueryUpdater { + override fun updateForSpaceId(roomId: String?) { + filteredPagedRoomSummariesLive.queryParams = roomQueryParams.copy( + spaceFilter = roomId?.toActiveSpaceOrOrphanRooms() + ) + liveQueryParams.update { filteredPagedRoomSummariesLive.queryParams } + } + }) + } + RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL -> { + activeSpaceUpdaters.add(object : RoomListViewModel.ActiveSpaceQueryUpdater { + override fun updateForSpaceId(roomId: String?) { + if (roomId != null) { + filteredPagedRoomSummariesLive.queryParams = roomQueryParams.copy( + spaceFilter = SpaceFilter.ActiveSpace(roomId) + ) + } else { + filteredPagedRoomSummariesLive.queryParams = roomQueryParams.copy( + spaceFilter = null + ) + } + liveQueryParams.update { filteredPagedRoomSummariesLive.queryParams } + } + }) + } + RoomListViewModel.SpaceFilterStrategy.NONE -> { + // we ignore current space for this one + } + } + + val livePagedList = filteredPagedRoomSummariesLive.livePagedList + // use it also as a source to update count + livePagedList.asFlow() + .onEach { + Timber.v("Thread space list: ${Thread.currentThread()}") + sections.find { it.sectionName == name } + ?.notificationCount + ?.postValue( + if (countRoomAsNotif) { + RoomAggregateNotificationCount(it.size, it.size) + } else { + session.roomService().getNotificationCountForRooms( + roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId()) + ) + } + ) + } + .flowOn(Dispatchers.Default) + .launchIn(viewModelScope) + + sections.add( + RoomsSection( + sectionName = name, + livePages = livePagedList, + notifyOfLocalEcho = notifyOfLocalEcho, + itemCount = itemCountFlow + ) + ) + } + } + + private fun withQueryParams(builder: (RoomSummaryQueryParams.Builder) -> Unit, block: (RoomSummaryQueryParams) -> Unit) { + block(roomSummaryQueryParams { builder.invoke(this) }) + } + + internal fun RoomSummaryQueryParams.process(spaceFilter: RoomListViewModel.SpaceFilterStrategy, currentSpace: String?): RoomSummaryQueryParams { + return when (spaceFilter) { + RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL -> { + copy( + spaceFilter = currentSpace?.toActiveSpaceOrOrphanRooms() + ) + } + RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL -> { + copy( + spaceFilter = currentSpace?.let { SpaceFilter.ActiveSpace(it) } + ) + } + RoomListViewModel.SpaceFilterStrategy.NONE -> this + } + } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderGroup.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderGroup.kt deleted file mode 100644 index a8a30349c7..0000000000 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderGroup.kt +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (c) 2021 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package im.vector.app.features.home.room.list - -import androidx.annotation.StringRes -import androidx.lifecycle.asFlow -import im.vector.app.AppStateHandler -import im.vector.app.R -import im.vector.app.RoomGroupingMethod -import im.vector.app.core.resources.StringProvider -import im.vector.app.features.home.RoomListDisplayMode -import im.vector.app.features.invite.AutoAcceptInvites -import im.vector.app.features.invite.showInvites -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.flatMapLatest -import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import org.matrix.android.sdk.api.query.RoomCategoryFilter -import org.matrix.android.sdk.api.query.RoomTagQueryFilter -import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams -import org.matrix.android.sdk.api.session.room.UpdatableLivePageResult -import org.matrix.android.sdk.api.session.room.model.Membership -import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams - -class RoomListSectionBuilderGroup( - private val coroutineScope: CoroutineScope, - private val session: Session, - private val stringProvider: StringProvider, - private val appStateHandler: AppStateHandler, - private val autoAcceptInvites: AutoAcceptInvites, - private val onUpdatable: (UpdatableLivePageResult) -> Unit -) : RoomListSectionBuilder { - - override fun buildSections(mode: RoomListDisplayMode): List { - val activeGroupAwareQueries = mutableListOf() - val sections = mutableListOf() - val actualGroupId = appStateHandler.safeActiveGroupId() - - when (mode) { - RoomListDisplayMode.PEOPLE -> { - // 4 sections Invites / Fav / Dms / Low Priority - buildPeopleSections(sections, activeGroupAwareQueries, actualGroupId) - } - RoomListDisplayMode.ROOMS -> { - // 5 sections invites / Fav / Rooms / Low Priority / Server notice - buildRoomsSections(sections, activeGroupAwareQueries, actualGroupId) - } - RoomListDisplayMode.FILTERED -> { - // Used when searching for rooms - withQueryParams( - { - it.memberships = Membership.activeMemberships() - }, - { qpm -> - val name = stringProvider.getString(R.string.bottom_action_rooms) - val updatableFilterLivePageResult = session.roomService().getFilteredPagedRoomSummariesLive(qpm, getFlattenParents = true) - onUpdatable(updatableFilterLivePageResult) - - val itemCountFlow = updatableFilterLivePageResult.livePagedList.asFlow() - .flatMapLatest { session.roomService().getRoomCountLive(updatableFilterLivePageResult.queryParams).asFlow() } - .distinctUntilChanged() - - sections.add( - RoomsSection( - sectionName = name, - livePages = updatableFilterLivePageResult.livePagedList, - itemCount = itemCountFlow - ) - ) - } - ) - } - RoomListDisplayMode.NOTIFICATIONS -> { - if (autoAcceptInvites.showInvites()) { - addSection( - sections, - activeGroupAwareQueries, - R.string.invitations_header, - true - ) { - it.memberships = listOf(Membership.INVITE) - it.activeGroupId = actualGroupId - } - } - - addSection( - sections, - activeGroupAwareQueries, - R.string.bottom_action_rooms, - false - ) { - it.memberships = listOf(Membership.JOIN) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_WITH_NOTIFICATIONS - it.activeGroupId = actualGroupId - } - } - } - - appStateHandler.selectedRoomGroupingFlow - .distinctUntilChanged() - .onEach { groupingMethod -> - val selectedGroupId = (groupingMethod.orNull() as? RoomGroupingMethod.ByLegacyGroup)?.groupSummary?.groupId - activeGroupAwareQueries.onEach { updater -> - updater.queryParams = updater.queryParams.copy(activeGroupId = selectedGroupId) - } - }.launchIn(coroutineScope) - - return sections - } - - private fun buildRoomsSections( - sections: MutableList, - activeSpaceAwareQueries: MutableList, - actualGroupId: String? - ) { - if (autoAcceptInvites.showInvites()) { - addSection( - sections, - activeSpaceAwareQueries, - R.string.invitations_header, - true - ) { - it.memberships = listOf(Membership.INVITE) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS - it.activeGroupId = actualGroupId - } - } - - addSection( - sections, - activeSpaceAwareQueries, - R.string.bottom_action_favourites, - false - ) { - it.memberships = listOf(Membership.JOIN) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS - it.roomTagQueryFilter = RoomTagQueryFilter(true, null, null) - it.activeGroupId = actualGroupId - } - - addSection( - sections, - activeSpaceAwareQueries, - R.string.bottom_action_rooms, - false - ) { - it.memberships = listOf(Membership.JOIN) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS - it.roomTagQueryFilter = RoomTagQueryFilter(false, false, false) - it.activeGroupId = actualGroupId - } - - addSection( - sections, - activeSpaceAwareQueries, - R.string.low_priority_header, - false - ) { - it.memberships = listOf(Membership.JOIN) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS - it.roomTagQueryFilter = RoomTagQueryFilter(null, true, null) - it.activeGroupId = actualGroupId - } - - addSection( - sections, - activeSpaceAwareQueries, - R.string.system_alerts_header, - false - ) { - it.memberships = listOf(Membership.JOIN) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS - it.roomTagQueryFilter = RoomTagQueryFilter(null, null, true) - it.activeGroupId = actualGroupId - } - } - - private fun buildPeopleSections( - sections: MutableList, - activeSpaceAwareQueries: MutableList, - actualGroupId: String? - ) { - if (autoAcceptInvites.showInvites()) { - addSection( - sections, - activeSpaceAwareQueries, - R.string.invitations_header, - true - ) { - it.memberships = listOf(Membership.INVITE) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM - it.activeGroupId = actualGroupId - } - } - - addSection( - sections, - activeSpaceAwareQueries, - R.string.bottom_action_favourites, - false - ) { - it.memberships = listOf(Membership.JOIN) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM - it.roomTagQueryFilter = RoomTagQueryFilter(true, null, null) - it.activeGroupId = actualGroupId - } - - addSection( - sections, - activeSpaceAwareQueries, - R.string.bottom_action_people_x, - false - ) { - it.memberships = listOf(Membership.JOIN) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM - it.roomTagQueryFilter = RoomTagQueryFilter(false, false, null) - it.activeGroupId = actualGroupId - } - - addSection( - sections, - activeSpaceAwareQueries, - R.string.low_priority_header, - false - ) { - it.memberships = listOf(Membership.JOIN) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM - it.roomTagQueryFilter = RoomTagQueryFilter(false, true, null) - it.activeGroupId = actualGroupId - } - } - - private fun addSection( - sections: MutableList, - activeSpaceUpdaters: MutableList, - @StringRes nameRes: Int, - notifyOfLocalEcho: Boolean = false, - query: (RoomSummaryQueryParams.Builder) -> Unit - ) { - withQueryParams(query) { roomQueryParams -> - val name = stringProvider.getString(nameRes) - session.roomService().getFilteredPagedRoomSummariesLive(roomQueryParams) - .also { - activeSpaceUpdaters.add(it) - }.livePagedList - .let { livePagedList -> - // use it also as a source to update count - livePagedList.asFlow() - .onEach { - sections.find { it.sectionName == name } - ?.notificationCount - ?.postValue(session.roomService().getNotificationCountForRooms(roomQueryParams)) - } - .flowOn(Dispatchers.Default) - .launchIn(coroutineScope) - - sections.add( - RoomsSection( - sectionName = name, - livePages = livePagedList, - notifyOfLocalEcho = notifyOfLocalEcho, - itemCount = session.roomService().getRoomCountLive(roomQueryParams).asFlow() - ) - ) - } - } - } - - private fun withQueryParams(builder: (RoomSummaryQueryParams.Builder) -> Unit, block: (RoomSummaryQueryParams) -> Unit) { - block(roomSummaryQueryParams { builder.invoke(this) }) - } -} diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderSpace.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderSpace.kt deleted file mode 100644 index 47a1df3ed0..0000000000 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderSpace.kt +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Copyright (c) 2021 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package im.vector.app.features.home.room.list - -import androidx.annotation.StringRes -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.asFlow -import androidx.lifecycle.liveData -import androidx.paging.PagedList -import com.airbnb.mvrx.Async -import im.vector.app.AppStateHandler -import im.vector.app.R -import im.vector.app.core.resources.StringProvider -import im.vector.app.features.home.RoomListDisplayMode -import im.vector.app.features.invite.AutoAcceptInvites -import im.vector.app.features.invite.showInvites -import im.vector.app.space -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.flatMapLatest -import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.flow.update -import org.matrix.android.sdk.api.extensions.tryOrNull -import org.matrix.android.sdk.api.query.RoomCategoryFilter -import org.matrix.android.sdk.api.query.RoomTagQueryFilter -import org.matrix.android.sdk.api.query.SpaceFilter -import org.matrix.android.sdk.api.query.toActiveSpaceOrOrphanRooms -import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.api.session.getRoomSummary -import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams -import org.matrix.android.sdk.api.session.room.UpdatableLivePageResult -import org.matrix.android.sdk.api.session.room.model.Membership -import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams -import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount -import timber.log.Timber - -class RoomListSectionBuilderSpace( - private val session: Session, - private val stringProvider: StringProvider, - private val appStateHandler: AppStateHandler, - private val viewModelScope: CoroutineScope, - private val autoAcceptInvites: AutoAcceptInvites, - private val onUpdatable: (UpdatableLivePageResult) -> Unit, - private val suggestedRoomJoiningState: LiveData>>, - private val onlyOrphansInHome: Boolean = false -) : RoomListSectionBuilder { - - private val pagedListConfig = PagedList.Config.Builder() - .setPageSize(10) - .setInitialLoadSizeHint(20) - .setEnablePlaceholders(true) - .setPrefetchDistance(10) - .build() - - override fun buildSections(mode: RoomListDisplayMode): List { - val sections = mutableListOf() - val activeSpaceAwareQueries = mutableListOf() - when (mode) { - RoomListDisplayMode.PEOPLE -> { - // 4 sections Invites / Fav / Dms / Low Priority - buildDmSections(sections, activeSpaceAwareQueries) - } - RoomListDisplayMode.ROOMS -> { - // 6 sections invites / Fav / Rooms / Low Priority / Server notice / Suggested rooms - buildRoomsSections(sections, activeSpaceAwareQueries) - } - RoomListDisplayMode.FILTERED -> { - // Used when searching for rooms - buildFilteredSection(sections) - } - RoomListDisplayMode.NOTIFICATIONS -> { - buildNotificationsSection(sections, activeSpaceAwareQueries) - } - } - - appStateHandler.selectedRoomGroupingFlow - .distinctUntilChanged() - .onEach { groupingMethod -> - val selectedSpace = groupingMethod.orNull()?.space() - activeSpaceAwareQueries.onEach { updater -> - updater.updateForSpaceId(selectedSpace?.roomId) - } - }.launchIn(viewModelScope) - - return sections - } - - private fun buildRoomsSections( - sections: MutableList, - activeSpaceAwareQueries: MutableList - ) { - if (autoAcceptInvites.showInvites()) { - addSection( - sections = sections, - activeSpaceUpdaters = activeSpaceAwareQueries, - nameRes = R.string.invitations_header, - notifyOfLocalEcho = true, - spaceFilterStrategy = RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL, - countRoomAsNotif = true - ) { - it.memberships = listOf(Membership.INVITE) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS - } - } - - addSection( - sections, - activeSpaceAwareQueries, - R.string.bottom_action_favourites, - false, - RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL - ) { - it.memberships = listOf(Membership.JOIN) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS - it.roomTagQueryFilter = RoomTagQueryFilter(true, null, null) - } - - addSection( - sections = sections, - activeSpaceUpdaters = activeSpaceAwareQueries, - nameRes = R.string.bottom_action_rooms, - notifyOfLocalEcho = false, - spaceFilterStrategy = if (onlyOrphansInHome) { - RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL - } else { - RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL - } - ) { - it.memberships = listOf(Membership.JOIN) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS - it.roomTagQueryFilter = RoomTagQueryFilter(false, false, false) - } - - addSection( - sections = sections, - activeSpaceUpdaters = activeSpaceAwareQueries, - nameRes = R.string.low_priority_header, - notifyOfLocalEcho = false, - spaceFilterStrategy = if (onlyOrphansInHome) { - RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL - } else { - RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL - } - ) { - it.memberships = listOf(Membership.JOIN) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS - it.roomTagQueryFilter = RoomTagQueryFilter(null, true, null) - } - - addSection( - sections = sections, - activeSpaceUpdaters = activeSpaceAwareQueries, - nameRes = R.string.system_alerts_header, - notifyOfLocalEcho = false, - spaceFilterStrategy = if (onlyOrphansInHome) { - RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL - } else { - RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL - } - ) { - it.memberships = listOf(Membership.JOIN) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS - it.roomTagQueryFilter = RoomTagQueryFilter(null, null, true) - } - - // add suggested rooms - val suggestedRoomsFlow = // MutableLiveData>() - appStateHandler.selectedRoomGroupingFlow - .distinctUntilChanged() - .flatMapLatest { groupingMethod -> - val selectedSpace = groupingMethod.orNull()?.space() - if (selectedSpace == null) { - flowOf(emptyList()) - } else { - liveData(context = viewModelScope.coroutineContext + Dispatchers.IO) { - val spaceSum = tryOrNull { - session.spaceService() - .querySpaceChildren(selectedSpace.roomId, suggestedOnly = true, null, null) - } - val value = spaceSum?.children.orEmpty().distinctBy { it.childRoomId } - // i need to check if it's already joined. - val filtered = value.filter { - session.getRoomSummary(it.childRoomId)?.membership?.isActive() != true - } - emit(filtered) - }.asFlow() - } - } - - val liveSuggestedRooms = MutableLiveData() - combine( - suggestedRoomsFlow, - suggestedRoomJoiningState.asFlow() - ) { rooms, joinStates -> - SuggestedRoomInfo( - rooms, - joinStates - ) - }.onEach { - liveSuggestedRooms.postValue(it) - }.launchIn(viewModelScope) - - sections.add( - RoomsSection( - sectionName = stringProvider.getString(R.string.suggested_header), - liveSuggested = liveSuggestedRooms, - notifyOfLocalEcho = false, - itemCount = suggestedRoomsFlow.map { suggestions -> suggestions.size } - ) - ) - } - - private fun buildDmSections( - sections: MutableList, - activeSpaceAwareQueries: MutableList - ) { - if (autoAcceptInvites.showInvites()) { - addSection( - sections = sections, - activeSpaceUpdaters = activeSpaceAwareQueries, - nameRes = R.string.invitations_header, - notifyOfLocalEcho = true, - spaceFilterStrategy = RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL, - countRoomAsNotif = true - ) { - it.memberships = listOf(Membership.INVITE) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM - } - } - - addSection( - sections, - activeSpaceAwareQueries, - R.string.bottom_action_favourites, - false, - RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL - ) { - it.memberships = listOf(Membership.JOIN) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM - it.roomTagQueryFilter = RoomTagQueryFilter(true, null, null) - } - - addSection( - sections, - activeSpaceAwareQueries, - R.string.bottom_action_people_x, - false, - RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL - ) { - it.memberships = listOf(Membership.JOIN) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM - it.roomTagQueryFilter = RoomTagQueryFilter(false, false, null) - } - - addSection( - sections, - activeSpaceAwareQueries, - R.string.low_priority_header, - false, - RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL - ) { - it.memberships = listOf(Membership.JOIN) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM - it.roomTagQueryFilter = RoomTagQueryFilter(false, true, null) - } - } - - private fun buildNotificationsSection( - sections: MutableList, - activeSpaceAwareQueries: MutableList - ) { - if (autoAcceptInvites.showInvites()) { - addSection( - sections = sections, - activeSpaceUpdaters = activeSpaceAwareQueries, - nameRes = R.string.invitations_header, - notifyOfLocalEcho = true, - spaceFilterStrategy = if (onlyOrphansInHome) { - RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL - } else { - RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL - }, - countRoomAsNotif = true - ) { - it.memberships = listOf(Membership.INVITE) - } - } - - addSection( - sections = sections, - activeSpaceUpdaters = activeSpaceAwareQueries, - nameRes = R.string.bottom_action_rooms, - notifyOfLocalEcho = false, - spaceFilterStrategy = if (onlyOrphansInHome) { - RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL - } else { - RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL - } - ) { - it.memberships = listOf(Membership.JOIN) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_WITH_NOTIFICATIONS - } - } - - private fun buildFilteredSection(sections: MutableList) { - // Used when searching for rooms - withQueryParams( - { - it.memberships = Membership.activeMemberships() - }, - { queryParams -> - val name = stringProvider.getString(R.string.bottom_action_rooms) - val updatableFilterLivePageResult = session.roomService().getFilteredPagedRoomSummariesLive(queryParams, getFlattenParents = true) - onUpdatable(updatableFilterLivePageResult) - - val itemCountFlow = updatableFilterLivePageResult.livePagedList.asFlow() - .flatMapLatest { session.roomService().getRoomCountLive(updatableFilterLivePageResult.queryParams).asFlow() } - .distinctUntilChanged() - - sections.add( - RoomsSection( - sectionName = name, - livePages = updatableFilterLivePageResult.livePagedList, - itemCount = itemCountFlow - ) - ) - } - ) - } - - private fun addSection( - sections: MutableList, - activeSpaceUpdaters: MutableList, - @StringRes nameRes: Int, - notifyOfLocalEcho: Boolean = false, - spaceFilterStrategy: RoomListViewModel.SpaceFilterStrategy = RoomListViewModel.SpaceFilterStrategy.NONE, - countRoomAsNotif: Boolean = false, - query: (RoomSummaryQueryParams.Builder) -> Unit - ) { - withQueryParams(query) { roomQueryParams -> - val updatedQueryParams = roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId()) - val liveQueryParams = MutableStateFlow(updatedQueryParams) - val itemCountFlow = liveQueryParams - .flatMapLatest { - session.roomService().getRoomCountLive(it).asFlow() - } - .flowOn(Dispatchers.Main) - .distinctUntilChanged() - - val name = stringProvider.getString(nameRes) - val filteredPagedRoomSummariesLive = session.roomService().getFilteredPagedRoomSummariesLive( - roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId()), - pagedListConfig - ) - when (spaceFilterStrategy) { - RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL -> { - activeSpaceUpdaters.add(object : RoomListViewModel.ActiveSpaceQueryUpdater { - override fun updateForSpaceId(roomId: String?) { - filteredPagedRoomSummariesLive.queryParams = roomQueryParams.copy( - spaceFilter = roomId.toActiveSpaceOrOrphanRooms() - ) - liveQueryParams.update { filteredPagedRoomSummariesLive.queryParams } - } - }) - } - RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL -> { - activeSpaceUpdaters.add(object : RoomListViewModel.ActiveSpaceQueryUpdater { - override fun updateForSpaceId(roomId: String?) { - if (roomId != null) { - filteredPagedRoomSummariesLive.queryParams = roomQueryParams.copy( - spaceFilter = SpaceFilter.ActiveSpace(roomId) - ) - } else { - filteredPagedRoomSummariesLive.queryParams = roomQueryParams.copy( - spaceFilter = null - ) - } - liveQueryParams.update { filteredPagedRoomSummariesLive.queryParams } - } - }) - } - RoomListViewModel.SpaceFilterStrategy.NONE -> { - // we ignore current space for this one - } - } - - val livePagedList = filteredPagedRoomSummariesLive.livePagedList - // use it also as a source to update count - livePagedList.asFlow() - .onEach { - Timber.v("Thread space list: ${Thread.currentThread()}") - sections.find { it.sectionName == name } - ?.notificationCount - ?.postValue( - if (countRoomAsNotif) { - RoomAggregateNotificationCount(it.size, it.size) - } else { - session.roomService().getNotificationCountForRooms( - roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId()) - ) - } - ) - } - .flowOn(Dispatchers.Default) - .launchIn(viewModelScope) - - sections.add( - RoomsSection( - sectionName = name, - livePages = livePagedList, - notifyOfLocalEcho = notifyOfLocalEcho, - itemCount = itemCountFlow - ) - ) - } - } - - private fun withQueryParams(builder: (RoomSummaryQueryParams.Builder) -> Unit, block: (RoomSummaryQueryParams) -> Unit) { - block(roomSummaryQueryParams { builder.invoke(this) }) - } - - internal fun RoomSummaryQueryParams.process(spaceFilter: RoomListViewModel.SpaceFilterStrategy, currentSpace: String?): RoomSummaryQueryParams { - return when (spaceFilter) { - RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL -> { - copy( - spaceFilter = currentSpace.toActiveSpaceOrOrphanRooms() - ) - } - RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL -> { - copy( - spaceFilter = currentSpace?.let { SpaceFilter.ActiveSpace(it) } - ) - } - RoomListViewModel.SpaceFilterStrategy.NONE -> this - } - } -} diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt index cd4bb06949..44d61f9ed2 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt @@ -26,7 +26,6 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import im.vector.app.AppStateHandler -import im.vector.app.RoomGroupingMethod import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel @@ -101,11 +100,11 @@ class RoomListViewModel @AssistedInject constructor( observeMembershipChanges() observeLocalRooms() - appStateHandler.selectedRoomGroupingFlow + appStateHandler.selectedSpaceFlow .distinctUntilChanged() .execute { copy( - currentRoomGrouping = it.invoke()?.orNull()?.let { Success(it) } ?: Loading() + asyncSelectedSpace = it.invoke()?.orNull()?.let { Success(it) } ?: Loading() ) } @@ -146,8 +145,7 @@ class RoomListViewModel @AssistedInject constructor( companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() - private val roomListSectionBuilder = if (appStateHandler.getCurrentRoomGroupingMethod() is RoomGroupingMethod.BySpace) { - RoomListSectionBuilderSpace( + private val roomListSectionBuilder = RoomListSectionBuilder( session, stringProvider, appStateHandler, @@ -159,17 +157,6 @@ class RoomListViewModel @AssistedInject constructor( suggestedRoomJoiningState, !vectorPreferences.prefSpacesShowAllRoomInHome() ) - } else { - RoomListSectionBuilderGroup( - viewModelScope, - session, - stringProvider, - appStateHandler, - autoAcceptInvites - ) { - updatableQuery = it - } - } val sections: List by lazy { roomListSectionBuilder.buildSections(initialState.displayMode) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewState.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewState.kt index 9d386b679a..3f46293346 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewState.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewState.kt @@ -19,9 +19,9 @@ package im.vector.app.features.home.room.list import com.airbnb.mvrx.Async import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.Uninitialized -import im.vector.app.RoomGroupingMethod import im.vector.app.features.home.RoomListDisplayMode import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState +import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo data class RoomListViewState( @@ -30,7 +30,7 @@ data class RoomListViewState( val roomMembershipChanges: Map = emptyMap(), val asyncSuggestedRooms: Async> = Uninitialized, val currentUserName: String? = null, - val currentRoomGrouping: Async = Uninitialized, + val asyncSelectedSpace: Async = Uninitialized, val localRoomIds: Set = emptySet() ) : MavericksState { diff --git a/vector/src/main/java/im/vector/app/features/html/PillsPostProcessor.kt b/vector/src/main/java/im/vector/app/features/html/PillsPostProcessor.kt index 13a33cf30d..5f20b7278e 100644 --- a/vector/src/main/java/im/vector/app/features/html/PillsPostProcessor.kt +++ b/vector/src/main/java/im/vector/app/features/html/PillsPostProcessor.kt @@ -94,7 +94,6 @@ class PillsPostProcessor @AssistedInject constructor( val matrixItem = when (val permalinkData = PermalinkParser.parse(url)) { is PermalinkData.UserLink -> permalinkData.toMatrixItem(roomId) is PermalinkData.RoomLink -> permalinkData.toMatrixItem() - is PermalinkData.GroupLink -> permalinkData.toMatrixItem() else -> null } ?: return null return createPillImageSpan(matrixItem) @@ -118,9 +117,4 @@ class PillsPostProcessor @AssistedInject constructor( // Exclude event link (used in reply events, we do not want to pill the "in reply to") null } - - private fun PermalinkData.GroupLink.toMatrixItem(): MatrixItem? { - val group = sessionHolder.getSafeActiveSession()?.groupService()?.getGroupSummary(groupId) - return MatrixItem.GroupItem(groupId, group?.displayName, group?.avatarUrl) - } } diff --git a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheet.kt b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheet.kt index 8e4699aa0f..97a993d4d3 100644 --- a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheet.kt @@ -75,8 +75,7 @@ class MatrixToBottomSheet : views.matrixToCardContentLoading.isVisible = state.matrixItem is Incomplete showFragment(MatrixToUserFragment::class, Bundle()) } - is PermalinkData.GroupLink -> Unit - is PermalinkData.FallbackLink -> Unit + is PermalinkData.FallbackLink, is PermalinkData.RoomEmailInviteLink -> Unit } } diff --git a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt index 67bc245014..24a623160e 100644 --- a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt @@ -76,13 +76,8 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor( copy(matrixItem = Loading()) } } - is PermalinkData.GroupLink -> { - // Not yet supported - } - is PermalinkData.FallbackLink -> { - // Not yet supported - } - is PermalinkData.RoomEmailInviteLink -> Unit + is PermalinkData.RoomEmailInviteLink, + is PermalinkData.FallbackLink -> Unit } viewModelScope.launch(Dispatchers.IO) { resolveLink(initialState) @@ -186,10 +181,6 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor( } } } - is PermalinkData.GroupLink -> { - // not yet supported - _viewEvents.post(MatrixToViewEvents.Dismiss) - } is PermalinkData.RoomEmailInviteLink, is PermalinkData.FallbackLink -> { _viewEvents.post(MatrixToViewEvents.Dismiss) diff --git a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt index 2de01a5531..291eee307f 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt @@ -23,6 +23,7 @@ import android.net.Uri import android.os.Build import android.view.View import android.view.Window +import android.widget.Toast import androidx.activity.result.ActivityResultLauncher import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityOptionsCompat @@ -32,11 +33,8 @@ import androidx.core.view.ViewCompat import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.AppStateHandler import im.vector.app.R -import im.vector.app.RoomGroupingMethod import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.error.fatalError -import im.vector.app.core.platform.VectorBaseActivity -import im.vector.app.core.utils.toast import im.vector.app.features.VectorFeatures import im.vector.app.features.VectorFeatures.OnboardingVariant import im.vector.app.features.analytics.AnalyticsTracker @@ -105,11 +103,11 @@ import im.vector.app.features.spaces.people.SpacePeopleActivity import im.vector.app.features.terms.ReviewTermsActivity import im.vector.app.features.widgets.WidgetActivity import im.vector.app.features.widgets.WidgetArgsBuilder -import im.vector.app.space import org.matrix.android.sdk.api.session.crypto.verification.IncomingSasVerificationTransaction import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.getRoomSummary import org.matrix.android.sdk.api.session.permalinks.PermalinkData +import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoom import org.matrix.android.sdk.api.session.terms.TermsService import org.matrix.android.sdk.api.session.widgets.model.Widget @@ -169,7 +167,7 @@ class DefaultNavigator @Inject constructor( analyticsTracker.capture( sessionHolder.getActiveSession().getRoomSummary(roomId).toAnalyticsViewRoom( trigger = trigger, - groupingMethod = appStateHandler.getCurrentRoomGroupingMethod() + selectedSpace = appStateHandler.getCurrentSpace() ) ) } @@ -284,14 +282,6 @@ class DefaultNavigator @Inject constructor( } } - override fun openGroupDetail(groupId: String, context: Context, buildTask: Boolean) { - if (context is VectorBaseActivity<*>) { - context.notImplemented("Open group detail") - } else { - context.toast(R.string.not_implemented) - } - } - override fun openRoomMemberProfile(userId: String, roomId: String?, context: Context, buildTask: Boolean) { val args = RoomMemberProfileArgs(userId = userId, roomId = roomId) val intent = RoomMemberProfileActivity.newIntent(context, args) @@ -328,25 +318,10 @@ class DefaultNavigator @Inject constructor( } override fun openRoomDirectory(context: Context, initialFilter: String) { - when (val groupingMethod = appStateHandler.getCurrentRoomGroupingMethod()) { - is RoomGroupingMethod.ByLegacyGroup -> { - // TODO should open list of rooms of this group - val intent = RoomDirectoryActivity.getIntent(context, initialFilter) - context.startActivity(intent) - } - is RoomGroupingMethod.BySpace -> { - val selectedSpace = groupingMethod.space() - if (selectedSpace == null) { - val intent = RoomDirectoryActivity.getIntent(context, initialFilter) - context.startActivity(intent) - } else { - SpaceExploreActivity.newIntent(context, selectedSpace.roomId).let { - context.startActivity(it) - } - } - } - null -> Unit - } + when (val currentSpace = appStateHandler.getCurrentSpace()) { + null -> RoomDirectoryActivity.getIntent(context, initialFilter) + else -> SpaceExploreActivity.newIntent(context, currentSpace.roomId) + }.start(context) } override fun openCreateRoom(context: Context, initialName: String, openAfterCreate: Boolean) { @@ -355,54 +330,24 @@ class DefaultNavigator @Inject constructor( } override fun openCreateDirectRoom(context: Context) { - val intent = when (val currentGroupingMethod = appStateHandler.getCurrentRoomGroupingMethod()) { - is RoomGroupingMethod.ByLegacyGroup -> { - CreateDirectRoomActivity.getIntent(context) - } - is RoomGroupingMethod.BySpace -> { - if (currentGroupingMethod.spaceSummary != null) { - SpacePeopleActivity.newIntent(context, currentGroupingMethod.spaceSummary.roomId) - } else { - CreateDirectRoomActivity.getIntent(context) - } - } - else -> null - } ?: return - context.startActivity(intent) + when (val currentSpace = appStateHandler.getCurrentSpace()) { + null -> CreateDirectRoomActivity.getIntent(context) + else -> SpacePeopleActivity.newIntent(context, currentSpace.roomId) + }.start(context) } override fun openInviteUsersToRoom(context: Context, roomId: String) { - when (val currentGroupingMethod = appStateHandler.getCurrentRoomGroupingMethod()) { - is RoomGroupingMethod.ByLegacyGroup -> { - val intent = InviteUsersToRoomActivity.getIntent(context, roomId) - context.startActivity(intent) - } - is RoomGroupingMethod.BySpace -> { - if (currentGroupingMethod.spaceSummary != null) { - // let user decides if he does it from space or room - (context as? AppCompatActivity)?.supportFragmentManager?.let { fm -> - InviteRoomSpaceChooserBottomSheet.newInstance( - currentGroupingMethod.spaceSummary.roomId, - roomId, - object : InviteRoomSpaceChooserBottomSheet.InteractionListener { - override fun inviteToSpace(spaceId: String) { - val intent = InviteUsersToRoomActivity.getIntent(context, spaceId) - context.startActivity(intent) - } + when (val currentSpace = appStateHandler.getCurrentSpace()) { + null -> InviteUsersToRoomActivity.getIntent(context, roomId).start(context) + else -> showInviteToDialog(context, currentSpace, roomId) + } + } - override fun inviteToRoom(roomId: String) { - val intent = InviteUsersToRoomActivity.getIntent(context, roomId) - context.startActivity(intent) - } - } - ).show(fm, InviteRoomSpaceChooserBottomSheet::class.java.name) - } - } else { - val intent = InviteUsersToRoomActivity.getIntent(context, roomId) - context.startActivity(intent) - } + private fun showInviteToDialog(context: Context, currentSpace: RoomSummary, roomId: String) { + (context as? AppCompatActivity)?.supportFragmentManager?.let { fragmentManager -> + InviteRoomSpaceChooserBottomSheet.showInstance(fragmentManager, currentSpace.roomId, roomId) { itemId -> + InviteUsersToRoomActivity.getIntent(context, itemId).start(context) } - null -> Unit } } @@ -449,6 +394,10 @@ class DefaultNavigator @Inject constructor( context.startActivity(KeysBackupManageActivity.intent(context)) } + override fun showGroupsUnsupportedWarning(context: Context) { + Toast.makeText(context, context.getString(R.string.permalink_unsupported_groups), Toast.LENGTH_LONG).show() + } + override fun openRoomProfile(context: Context, roomId: String, directAccess: Int?) { context.startActivity(RoomProfileActivity.newIntent(context, roomId, directAccess)) } @@ -658,4 +607,8 @@ class DefaultNavigator @Inject constructor( ) { activityResultLauncher.launch(screenCaptureIntent) } + + private fun Intent.start(context: Context) { + context.startActivity(this) + } } diff --git a/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt b/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt index 7b6a81db52..7410d412c2 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt @@ -112,7 +112,7 @@ interface Navigator { fun openKeysBackupManager(context: Context) - fun openGroupDetail(groupId: String, context: Context, buildTask: Boolean = false) + fun showGroupsUnsupportedWarning(context: Context) fun openRoomMemberProfile(userId: String, roomId: String?, context: Context, buildTask: Boolean = false) diff --git a/vector/src/main/java/im/vector/app/features/permalink/PermalinkHandler.kt b/vector/src/main/java/im/vector/app/features/permalink/PermalinkHandler.kt index cd75fd5036..fc56891b72 100644 --- a/vector/src/main/java/im/vector/app/features/permalink/PermalinkHandler.kt +++ b/vector/src/main/java/im/vector/app/features/permalink/PermalinkHandler.kt @@ -90,55 +90,84 @@ class PermalinkHandler @Inject constructor( buildTask: Boolean ): Boolean { return when (permalinkData) { - is PermalinkData.RoomLink -> { - val roomId = permalinkData.getRoomId() - val session = activeSessionHolder.getSafeActiveSession() + is PermalinkData.RoomLink -> handleRoomLink(permalinkData, rawLink, context, navigationInterceptor, buildTask) + is PermalinkData.UserLink -> handleUserLink(permalinkData, rawLink, context, navigationInterceptor, buildTask) + is PermalinkData.FallbackLink -> handleFallbackLink(permalinkData, context) + is PermalinkData.RoomEmailInviteLink -> handleRoomInviteLink(permalinkData, context) + } + } - val rootThreadEventId = permalinkData.eventId?.let { eventId -> - val room = roomId?.let { session?.getRoom(it) } + private suspend fun handleRoomLink( + permalinkData: PermalinkData.RoomLink, + rawLink: Uri, + context: Context, + navigationInterceptor: NavigationInterceptor?, + buildTask: Boolean + ): Boolean { + val roomId = permalinkData.getRoomId() + val session = activeSessionHolder.getSafeActiveSession() - val rootThreadEventId = room?.getTimelineEvent(eventId)?.root?.getRootThreadEventId() - rootThreadEventId ?: if (room?.getTimelineEvent(eventId)?.isRootThread() == true) { - eventId - } else { - null - } - } - openRoom( - navigationInterceptor, - context = context, - roomId = roomId, - permalinkData = permalinkData, - rawLink = rawLink, - buildTask = buildTask, - rootThreadEventId = rootThreadEventId - ) - true + val rootThreadEventId = permalinkData.eventId?.let { eventId -> + val room = roomId?.let { session?.getRoom(it) } + + val rootThreadEventId = room?.getTimelineEvent(eventId)?.root?.getRootThreadEventId() + rootThreadEventId ?: if (room?.getTimelineEvent(eventId)?.isRootThread() == true) { + eventId + } else { + null } - is PermalinkData.GroupLink -> { - navigator.openGroupDetail(permalinkData.groupId, context, buildTask) - true - } - is PermalinkData.UserLink -> { - if (navigationInterceptor?.navToMemberProfile(permalinkData.userId, rawLink) != true) { - navigator.openRoomMemberProfile(userId = permalinkData.userId, roomId = null, context = context, buildTask = buildTask) - } - true - } - is PermalinkData.FallbackLink -> { - false - } - is PermalinkData.RoomEmailInviteLink -> { - val data = RoomPreviewData( - roomId = permalinkData.roomId, - roomName = permalinkData.roomName, - avatarUrl = permalinkData.roomAvatarUrl, - fromEmailInvite = permalinkData, - roomType = permalinkData.roomType - ) - navigator.openRoomPreview(context, data) - true + } + openRoom( + navigationInterceptor, + context = context, + roomId = roomId, + permalinkData = permalinkData, + rawLink = rawLink, + buildTask = buildTask, + rootThreadEventId = rootThreadEventId + ) + return true + } + + private fun handleUserLink( + permalinkData: PermalinkData.UserLink, + rawLink: Uri, + context: Context, + navigationInterceptor: NavigationInterceptor?, + buildTask: Boolean + ): Boolean { + if (navigationInterceptor?.navToMemberProfile(permalinkData.userId, rawLink) != true) { + navigator.openRoomMemberProfile(userId = permalinkData.userId, roomId = null, context = context, buildTask = buildTask) + } + return true + } + + private fun handleRoomInviteLink( + permalinkData: PermalinkData.RoomEmailInviteLink, + context: Context + ): Boolean { + val data = RoomPreviewData( + roomId = permalinkData.roomId, + roomName = permalinkData.roomName, + avatarUrl = permalinkData.roomAvatarUrl, + fromEmailInvite = permalinkData, + roomType = permalinkData.roomType + ) + navigator.openRoomPreview(context, data) + return true + } + + private suspend fun handleFallbackLink( + permalinkData: PermalinkData.FallbackLink, + context: Context + ): Boolean { + return if (permalinkData.isLegacyGroupLink) { + withContext(Dispatchers.Main) { + navigator.showGroupsUnsupportedWarning(context) } + true + } else { + false } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/InviteRoomSpaceChooserBottomSheet.kt b/vector/src/main/java/im/vector/app/features/spaces/InviteRoomSpaceChooserBottomSheet.kt index b4c1e67cfb..702bdc2a8f 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/InviteRoomSpaceChooserBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/InviteRoomSpaceChooserBottomSheet.kt @@ -22,6 +22,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.core.view.isVisible +import androidx.fragment.app.FragmentManager import com.airbnb.mvrx.args import dagger.hilt.android.AndroidEntryPoint import im.vector.app.R @@ -47,12 +48,7 @@ class InviteRoomSpaceChooserBottomSheet : VectorBaseBottomSheetDialogFragment Unit)? = null override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetSpaceInviteChooserBinding { return BottomSheetSpaceInviteChooserBinding.inflate(inflater, container, false) @@ -72,7 +68,7 @@ class InviteRoomSpaceChooserBottomSheet : VectorBaseBottomSheetDialogFragment Unit + ) { + InviteRoomSpaceChooserBottomSheet().apply { + this.onItemSelected = onItemSelected setArguments(Args(spaceId, roomId)) - } + }.show(fragmentManager, InviteRoomSpaceChooserBottomSheet::class.java.name) } } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListAction.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListAction.kt index 5bff2b733f..fd2e68e172 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListAction.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListAction.kt @@ -17,7 +17,6 @@ package im.vector.app.features.spaces import im.vector.app.core.platform.VectorViewModelAction -import org.matrix.android.sdk.api.session.group.model.GroupSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary sealed class SpaceListAction : VectorViewModelAction { @@ -29,6 +28,4 @@ sealed class SpaceListAction : VectorViewModelAction { data class MoveSpace(val spaceId: String, val delta: Int) : SpaceListAction() data class OnStartDragging(val spaceId: String, val expanded: Boolean) : SpaceListAction() data class OnEndDragging(val spaceId: String, val expanded: Boolean) : SpaceListAction() - - data class SelectLegacyGroup(val groupSummary: GroupSummary?) : SpaceListAction() } diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt index 29742bb290..ad131cbd57 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt @@ -34,7 +34,6 @@ import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentGroupListBinding import im.vector.app.features.home.HomeActivitySharedAction import im.vector.app.features.home.HomeSharedActionViewModel -import org.matrix.android.sdk.api.session.group.model.GroupSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary import javax.inject.Inject @@ -76,19 +75,16 @@ class SpaceListFragment @Inject constructor( } override fun onDragReleased(model: SpaceSummaryItem?, itemView: View?) { -// Timber.v("VAL: onModelMoved from $fromPositionM to $toPositionM ${model?.matrixItem?.getBestName()}") if (toPositionM == null || fromPositionM == null) return val movingSpace = model?.matrixItem?.id ?: return viewModel.handle(SpaceListAction.MoveSpace(movingSpace, toPositionM!! - fromPositionM!!)) } override fun clearView(model: SpaceSummaryItem?, itemView: View?) { -// Timber.v("VAL: clearView ${model?.matrixItem?.getBestName()}") itemView?.elevation = initialElevation ?: 0f } override fun onModelMoved(fromPosition: Int, toPosition: Int, modelBeingMoved: SpaceSummaryItem?, itemView: View?) { -// Timber.v("VAL: onModelMoved incremental from $fromPosition to $toPosition ${modelBeingMoved?.matrixItem?.getBestName()}") if (fromPositionM == null) { fromPositionM = fromPosition } @@ -97,7 +93,6 @@ class SpaceListFragment @Inject constructor( } override fun isDragEnabledForModel(model: SpaceSummaryItem?): Boolean { -// Timber.v("VAL: isDragEnabledForModel ${model?.matrixItem?.getBestName()}") return model?.canDrag == true } }) @@ -105,10 +100,9 @@ class SpaceListFragment @Inject constructor( viewModel.observeViewEvents { when (it) { is SpaceListViewEvents.OpenSpaceSummary -> sharedActionViewModel.post(HomeActivitySharedAction.OpenSpacePreview(it.id)) - is SpaceListViewEvents.OpenSpace -> sharedActionViewModel.post(HomeActivitySharedAction.OpenGroup(it.groupingMethodHasChanged)) is SpaceListViewEvents.AddSpace -> sharedActionViewModel.post(HomeActivitySharedAction.AddSpace) - is SpaceListViewEvents.OpenGroup -> sharedActionViewModel.post(HomeActivitySharedAction.OpenGroup(it.groupingMethodHasChanged)) is SpaceListViewEvents.OpenSpaceInvite -> sharedActionViewModel.post(HomeActivitySharedAction.OpenSpaceInvite(it.id)) + SpaceListViewEvents.CloseDrawer -> sharedActionViewModel.post(HomeActivitySharedAction.CloseDrawer) } } } @@ -149,10 +143,6 @@ class SpaceListFragment @Inject constructor( viewModel.handle(SpaceListAction.AddSpace) } - override fun onGroupSelected(groupSummary: GroupSummary?) { - viewModel.handle(SpaceListAction.SelectLegacyGroup(groupSummary)) - } - override fun sendFeedBack() { sharedActionViewModel.post(HomeActivitySharedAction.SendSpaceFeedBack) } diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewEvents.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewEvents.kt index afc72b188d..bddd7c3c3d 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewEvents.kt @@ -22,9 +22,8 @@ import im.vector.app.core.platform.VectorViewEvents * Transient events for group list screen. */ sealed class SpaceListViewEvents : VectorViewEvents { - data class OpenSpace(val groupingMethodHasChanged: Boolean) : SpaceListViewEvents() data class OpenSpaceSummary(val id: String) : SpaceListViewEvents() data class OpenSpaceInvite(val id: String) : SpaceListViewEvents() object AddSpace : SpaceListViewEvents() - data class OpenGroup(val groupingMethodHasChanged: Boolean) : SpaceListViewEvents() + object CloseDrawer : SpaceListViewEvents() } diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt index 16cc2d21f4..3b2fb31b74 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt @@ -24,7 +24,6 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import im.vector.app.AppStateHandler -import im.vector.app.RoomGroupingMethod import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel @@ -33,8 +32,6 @@ import im.vector.app.features.analytics.plan.Interaction import im.vector.app.features.invite.AutoAcceptInvites import im.vector.app.features.session.coroutineScope import im.vector.app.features.settings.VectorPreferences -import im.vector.app.group -import im.vector.app.space import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged @@ -50,7 +47,6 @@ import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.getRoom -import org.matrix.android.sdk.api.session.group.groupSummaryQueryParams import org.matrix.android.sdk.api.session.room.RoomSortOrder import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataTypes import org.matrix.android.sdk.api.session.room.model.Membership @@ -79,10 +75,7 @@ class SpaceListViewModel @AssistedInject constructor( companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() -// private var currentGroupingMethod : RoomGroupingMethod? = null - init { - session.userService().getUserLive(session.myUserId) .asFlow() .setOnEach { @@ -93,20 +86,14 @@ class SpaceListViewModel @AssistedInject constructor( observeSpaceSummaries() // observeSelectionState() - appStateHandler.selectedRoomGroupingFlow + appStateHandler.selectedSpaceFlow .distinctUntilChanged() - .setOnEach { + .setOnEach { selectedSpaceOption -> copy( - selectedGroupingMethod = it.orNull() ?: RoomGroupingMethod.BySpace(null) + selectedSpace = selectedSpaceOption.orNull() ) } - session.groupService().getGroupSummariesLive(groupSummaryQueryParams {}) - .asFlow() - .setOnEach { - copy(legacyGroups = it) - } - // XXX there should be a way to refactor this and share it session.roomService().getPagedRoomSummariesLive( roomSummaryQueryParams { @@ -154,7 +141,6 @@ class SpaceListViewModel @AssistedInject constructor( SpaceListAction.AddSpace -> handleAddSpace() is SpaceListAction.ToggleExpand -> handleToggleExpand(action) is SpaceListAction.OpenSpaceInvite -> handleSelectSpaceInvite(action) - is SpaceListAction.SelectLegacyGroup -> handleSelectGroup(action) is SpaceListAction.MoveSpace -> handleMoveSpace(action) is SpaceListAction.OnEndDragging -> handleEndDragging() is SpaceListAction.OnStartDragging -> handleStartDragging() @@ -229,26 +215,16 @@ class SpaceListViewModel @AssistedInject constructor( } private fun handleSelectSpace(action: SpaceListAction.SelectSpace) = withState { state -> - val groupingMethod = state.selectedGroupingMethod - if (groupingMethod is RoomGroupingMethod.ByLegacyGroup || groupingMethod.space()?.roomId != action.spaceSummary?.roomId) { + if (state.selectedSpace?.roomId != action.spaceSummary?.roomId) { analyticsTracker.capture(Interaction(null, null, Interaction.Name.SpacePanelSwitchSpace)) - setState { copy(selectedGroupingMethod = RoomGroupingMethod.BySpace(action.spaceSummary)) } + setState { copy(selectedSpace = action.spaceSummary) } appStateHandler.setCurrentSpace(action.spaceSummary?.roomId) - _viewEvents.post(SpaceListViewEvents.OpenSpace(groupingMethod is RoomGroupingMethod.ByLegacyGroup)) + _viewEvents.post(SpaceListViewEvents.CloseDrawer) } else { analyticsTracker.capture(Interaction(null, null, Interaction.Name.SpacePanelSelectedSpace)) } } - private fun handleSelectGroup(action: SpaceListAction.SelectLegacyGroup) = withState { state -> - val groupingMethod = state.selectedGroupingMethod - if (groupingMethod is RoomGroupingMethod.BySpace || groupingMethod.group()?.groupId != action.groupSummary?.groupId) { - setState { copy(selectedGroupingMethod = RoomGroupingMethod.ByLegacyGroup(action.groupSummary)) } - appStateHandler.setCurrentGroup(action.groupSummary?.groupId) - _viewEvents.post(SpaceListViewEvents.OpenGroup(groupingMethod is RoomGroupingMethod.BySpace)) - } - } - private fun handleSelectSpaceInvite(action: SpaceListAction.OpenSpaceInvite) { _viewEvents.post(SpaceListViewEvents.OpenSpaceInvite(action.spaceSummary.roomId)) } diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewState.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewState.kt index eafc6a241e..794f1dbd69 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewState.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewState.kt @@ -19,8 +19,6 @@ package im.vector.app.features.spaces import com.airbnb.mvrx.Async import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.Uninitialized -import im.vector.app.RoomGroupingMethod -import org.matrix.android.sdk.api.session.group.model.GroupSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount import org.matrix.android.sdk.api.util.MatrixItem @@ -28,11 +26,10 @@ import org.matrix.android.sdk.api.util.MatrixItem data class SpaceListViewState( val myMxItem: Async = Uninitialized, val asyncSpaces: Async> = Uninitialized, - val selectedGroupingMethod: RoomGroupingMethod = RoomGroupingMethod.BySpace(null), + val selectedSpace: RoomSummary? = null, val rootSpacesOrdered: List? = null, val spaceOrderInfo: Map? = null, val spaceOrderLocalEchos: Map? = null, - val legacyGroups: List? = null, val expandedStates: Map = emptyMap(), val homeAggregateCount: RoomAggregateNotificationCount = RoomAggregateNotificationCount(0, 0) ) : MavericksState diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceSummaryController.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceSummaryController.kt index 302676a27c..233e33af18 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceSummaryController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceSummaryController.kt @@ -18,20 +18,11 @@ package im.vector.app.features.spaces import com.airbnb.epoxy.EpoxyController import im.vector.app.R -import im.vector.app.RoomGroupingMethod -import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider -import im.vector.app.core.ui.list.genericFooterItem -import im.vector.app.core.ui.list.genericHeaderItem -import im.vector.app.features.grouplist.groupSummaryItem import im.vector.app.features.grouplist.homeSpaceSummaryItem import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.list.UnreadCounterBadgeView -import im.vector.app.group -import im.vector.app.space -import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.extensions.orFalse -import org.matrix.android.sdk.api.session.group.model.GroupSummary import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo @@ -41,7 +32,6 @@ import javax.inject.Inject class SpaceSummaryController @Inject constructor( private val avatarRenderer: AvatarRenderer, - private val colorProvider: ColorProvider, private val stringProvider: StringProvider, ) : EpoxyController() { @@ -57,59 +47,18 @@ class SpaceSummaryController @Inject constructor( override fun buildModels() { val nonNullViewState = viewState ?: return - val host = this buildGroupModels( nonNullViewState.asyncSpaces(), - nonNullViewState.selectedGroupingMethod, + nonNullViewState.selectedSpace, nonNullViewState.rootSpacesOrdered, nonNullViewState.expandedStates, nonNullViewState.homeAggregateCount ) - - if (!nonNullViewState.legacyGroups.isNullOrEmpty()) { - genericFooterItem { - id("legacy_space") - text(" ".toEpoxyCharSequence()) - } - - genericHeaderItem { - id("legacy_groups") - text(host.stringProvider.getString(R.string.groups_header)) - textColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) - } - - // add home for communities - nonNullViewState.myMxItem.invoke()?.let { mxItem -> - groupSummaryItem { - avatarRenderer(host.avatarRenderer) - id("all_communities") - matrixItem(mxItem.copy(displayName = host.stringProvider.getString(R.string.group_all_communities))) - selected( - nonNullViewState.selectedGroupingMethod is RoomGroupingMethod.ByLegacyGroup && - nonNullViewState.selectedGroupingMethod.group() == null - ) - listener { host.callback?.onGroupSelected(null) } - } - } - - nonNullViewState.legacyGroups.forEach { groupSummary -> - groupSummaryItem { - avatarRenderer(host.avatarRenderer) - id(groupSummary.groupId) - matrixItem(groupSummary.toMatrixItem()) - selected( - nonNullViewState.selectedGroupingMethod is RoomGroupingMethod.ByLegacyGroup && - nonNullViewState.selectedGroupingMethod.group()?.groupId == groupSummary.groupId - ) - listener { host.callback?.onGroupSelected(groupSummary) } - } - } - } } private fun buildGroupModels( summaries: List?, - selected: RoomGroupingMethod, + selectedSpace: RoomSummary?, rootSpaces: List?, expandedStates: Map, homeCount: RoomAggregateNotificationCount @@ -137,7 +86,7 @@ class SpaceSummaryController @Inject constructor( homeSpaceSummaryItem { id("space_home") - selected(selected is RoomGroupingMethod.BySpace && selected.space() == null) + selected(selectedSpace == null) countState(UnreadCounterBadgeView.State(homeCount.totalCount, homeCount.isHighlight)) listener { host.callback?.onSpaceSelected(null) } } @@ -145,7 +94,7 @@ class SpaceSummaryController @Inject constructor( rootSpaces ?.filter { it.membership != Membership.INVITE } ?.forEach { roomSummary -> - val isSelected = selected is RoomGroupingMethod.BySpace && roomSummary.roomId == selected.space()?.roomId + val isSelected = roomSummary.roomId == selectedSpace?.roomId // does it have children? val subSpaces = roomSummary.spaceChildren?.filter { childInfo -> summaries?.any { it.roomId == childInfo.childRoomId }.orFalse() @@ -178,7 +127,7 @@ class SpaceSummaryController @Inject constructor( if (hasChildren && expanded) { // it's expanded subSpaces?.forEach { child -> - buildSubSpace(roomSummary.roomId, summaries, expandedStates, selected, child, 1, 3) + buildSubSpace(roomSummary.roomId, summaries, expandedStates, selectedSpace, child, 1, 3) } } } @@ -193,7 +142,7 @@ class SpaceSummaryController @Inject constructor( idPrefix: String, summaries: List?, expandedStates: Map, - selected: RoomGroupingMethod, + selectedSpace: RoomSummary?, info: SpaceChildInfo, currentDepth: Int, maxDepth: Int ) { val host = this @@ -204,7 +153,7 @@ class SpaceSummaryController @Inject constructor( summaries.any { it.roomId == childInfo.childRoomId } }?.sortedWith(subSpaceComparator) val expanded = expandedStates[childSummary.roomId] == true - val isSelected = selected is RoomGroupingMethod.BySpace && childSummary.roomId == selected.space()?.roomId + val isSelected = childSummary.roomId == selectedSpace?.roomId val id = "$idPrefix:${childSummary.roomId}" @@ -229,7 +178,7 @@ class SpaceSummaryController @Inject constructor( if (expanded) { subSpaces?.forEach { - buildSubSpace(id, summaries, expandedStates, selected, it, currentDepth + 1, maxDepth) + buildSubSpace(id, summaries, expandedStates, selectedSpace, it, currentDepth + 1, maxDepth) } } } @@ -240,7 +189,6 @@ class SpaceSummaryController @Inject constructor( fun onSpaceSettings(spaceSummary: RoomSummary) fun onToggleExpand(spaceSummary: RoomSummary) fun onAddSpaceSelected() - fun onGroupSelected(groupSummary: GroupSummary?) fun sendFeedBack() } } diff --git a/vector/src/main/java/im/vector/app/features/ui/SharedPreferencesUiStateRepository.kt b/vector/src/main/java/im/vector/app/features/ui/SharedPreferencesUiStateRepository.kt index 22abea15b0..e1bac6ab63 100644 --- a/vector/src/main/java/im/vector/app/features/ui/SharedPreferencesUiStateRepository.kt +++ b/vector/src/main/java/im/vector/app/features/ui/SharedPreferencesUiStateRepository.kt @@ -67,30 +67,10 @@ class SharedPreferencesUiStateRepository @Inject constructor( } } - override fun storeSelectedGroup(groupId: String?, sessionId: String) { - sharedPreferences.edit { - putString("$KEY_SELECTED_GROUP@$sessionId", groupId) - } - } - - override fun storeGroupingMethod(isSpace: Boolean, sessionId: String) { - sharedPreferences.edit { - putBoolean("$KEY_SELECTED_METHOD@$sessionId", isSpace) - } - } - - override fun getSelectedGroup(sessionId: String): String? { - return sharedPreferences.getString("$KEY_SELECTED_GROUP@$sessionId", null) - } - override fun getSelectedSpace(sessionId: String): String? { return sharedPreferences.getString("$KEY_SELECTED_SPACE@$sessionId", null) } - override fun isGroupingMethodSpace(sessionId: String): Boolean { - return sharedPreferences.getBoolean("$KEY_SELECTED_METHOD@$sessionId", true) - } - override fun setCustomRoomDirectoryHomeservers(sessionId: String, servers: Set) { sharedPreferences.edit { putStringSet("$KEY_CUSTOM_DIRECTORY_HOMESERVER@$sessionId", servers) @@ -110,8 +90,6 @@ class SharedPreferencesUiStateRepository @Inject constructor( private const val VALUE_DISPLAY_MODE_ROOMS = 2 private const val KEY_SELECTED_SPACE = "UI_STATE_SELECTED_SPACE" - private const val KEY_SELECTED_GROUP = "UI_STATE_SELECTED_GROUP" - private const val KEY_SELECTED_METHOD = "UI_STATE_SELECTED_METHOD" private const val KEY_CUSTOM_DIRECTORY_HOMESERVER = "KEY_CUSTOM_DIRECTORY_HOMESERVER" } diff --git a/vector/src/main/java/im/vector/app/features/ui/UiStateRepository.kt b/vector/src/main/java/im/vector/app/features/ui/UiStateRepository.kt index e2a87ce226..b610346433 100644 --- a/vector/src/main/java/im/vector/app/features/ui/UiStateRepository.kt +++ b/vector/src/main/java/im/vector/app/features/ui/UiStateRepository.kt @@ -34,13 +34,7 @@ interface UiStateRepository { // TODO Handle SharedPreference per session in a better way, also to cleanup when login out fun storeSelectedSpace(spaceId: String?, sessionId: String) - fun storeSelectedGroup(groupId: String?, sessionId: String) - - fun storeGroupingMethod(isSpace: Boolean, sessionId: String) - fun getSelectedSpace(sessionId: String): String? - fun getSelectedGroup(sessionId: String): String? - fun isGroupingMethodSpace(sessionId: String): Boolean fun setCustomRoomDirectoryHomeservers(sessionId: String, servers: Set) fun getCustomRoomDirectoryHomeservers(sessionId: String): Set diff --git a/vector/src/main/java/im/vector/app/features/usercode/UserCodeSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/usercode/UserCodeSharedViewModel.kt index ff2d551212..8c377cafd5 100644 --- a/vector/src/main/java/im/vector/app/features/usercode/UserCodeSharedViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/usercode/UserCodeSharedViewModel.kt @@ -29,7 +29,6 @@ import im.vector.app.features.createdirect.DirectRoomHelper import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.matrix.android.sdk.api.extensions.tryOrNull -import org.matrix.android.sdk.api.raw.RawService import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.getUser import org.matrix.android.sdk.api.session.permalinks.PermalinkData @@ -42,7 +41,6 @@ class UserCodeSharedViewModel @AssistedInject constructor( private val session: Session, private val stringProvider: StringProvider, private val directRoomHelper: DirectRoomHelper, - private val rawService: RawService ) : VectorViewModel(initialState) { companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() @@ -129,15 +127,11 @@ class UserCodeSharedViewModel @AssistedInject constructor( ) } } - is PermalinkData.GroupLink -> { - // not yet supported - _viewEvents.post(UserCodeShareViewEvents.ToastMessage(stringProvider.getString(R.string.not_implemented))) - } + is PermalinkData.RoomEmailInviteLink, is PermalinkData.FallbackLink -> { // not yet supported _viewEvents.post(UserCodeShareViewEvents.ToastMessage(stringProvider.getString(R.string.not_implemented))) } - is PermalinkData.RoomEmailInviteLink -> Unit } _viewEvents.post(UserCodeShareViewEvents.HideWaitingScreen) } diff --git a/vector/src/main/res/layout/item_group.xml b/vector/src/main/res/layout/item_group.xml deleted file mode 100644 index 81fa43d072..0000000000 --- a/vector/src/main/res/layout/item_group.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 3b094ed7c2..eed6269e65 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -174,7 +174,8 @@ Initial sync:\nLoading your conversations\nIf you\'ve joined lots of rooms, this might take a while Initial sync:\nImporting invited rooms Initial sync:\nImporting left rooms - Initial sync:\nImporting communities + + Initial sync:\nImporting communities Initial sync:\nImporting account data Initial sync request @@ -442,7 +443,8 @@ Show all rooms in the room directory, including rooms with explicit content. - Communities + + Communities Spaces @@ -1614,7 +1616,8 @@ No network. Please check your Internet connection. "Change network" "Please wait…" - "All Communities" + + "All Communities" "This room can't be previewed" This room is not accessible at this time.\nTry again later, or ask a room admin to check if you have access. @@ -2084,6 +2087,7 @@ The current session is for user %1$s and you provide credentials for user %2$s. This is not supported by ${app_name}.\nPlease first clear data, then sign in again on another account. Your matrix.to link was malformed + Cannot open this link: communities have been replaced by spaces The description is too short Initial Sync… From e8bd7ea967b1379908132de531a17dfd8be5f4d5 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 13 Jul 2022 11:47:48 +0200 Subject: [PATCH 127/131] fix olm session proliferation --- changelog.d/6534.bugfix | 1 + .../sdk/internal/crypto/UnwedgingTest.kt | 1 - .../sdk/internal/crypto/EventDecryptor.kt | 42 +++++++++++++------ 3 files changed, 30 insertions(+), 14 deletions(-) create mode 100644 changelog.d/6534.bugfix diff --git a/changelog.d/6534.bugfix b/changelog.d/6534.bugfix new file mode 100644 index 0000000000..721b61a2d5 --- /dev/null +++ b/changelog.d/6534.bugfix @@ -0,0 +1 @@ +Unwedging could cause the SDK to force creating a new olm session every hour diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt index e8a474a54a..03e19f0bbb 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt @@ -60,7 +60,6 @@ import kotlin.coroutines.resume */ @RunWith(AndroidJUnit4::class) @FixMethodOrder(MethodSorters.JVM) -@Ignore class UnwedgingTest : InstrumentedTest { private lateinit var messagesReceivedByBob: List diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/EventDecryptor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/EventDecryptor.kt index c1d04eb22b..bc3309132a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/EventDecryptor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/EventDecryptor.kt @@ -18,6 +18,8 @@ package org.matrix.android.sdk.internal.crypto import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.MatrixCoroutineDispatchers @@ -68,6 +70,7 @@ internal class EventDecryptor @Inject constructor( val senderKey: String? ) + private val wedgedMutex = Mutex() private val wedgedDevices = mutableListOf() /** @@ -151,11 +154,13 @@ internal class EventDecryptor @Inject constructor( } } - private fun markOlmSessionForUnwedging(senderId: String, senderKey: String) { - val info = WedgedDeviceInfo(senderId, senderKey) - if (!wedgedDevices.contains(info)) { - Timber.tag(loggerTag.value).d("Marking device from $senderId key:$senderKey as wedged") - wedgedDevices.add(info) + private suspend fun markOlmSessionForUnwedging(senderId: String, senderKey: String) { + wedgedMutex.withLock { + val info = WedgedDeviceInfo(senderId, senderKey) + if (!wedgedDevices.contains(info)) { + Timber.tag(loggerTag.value).d("Marking device from $senderId key:$senderKey as wedged") + wedgedDevices.add(info) + } } } @@ -167,15 +172,17 @@ internal class EventDecryptor @Inject constructor( Timber.tag(loggerTag.value).v("Unwedging: ${wedgedDevices.size} are wedged") // get the one that should be retried according to rate limit val now = clock.epochMillis() - val toUnwedge = wedgedDevices.filter { - val lastForcedDate = lastNewSessionForcedDates[it] ?: 0 - if (now - lastForcedDate < DefaultCryptoService.CRYPTO_MIN_FORCE_SESSION_PERIOD_MILLIS) { - Timber.tag(loggerTag.value).d("Unwedging, New session for $it already forced with device at $lastForcedDate") - return@filter false + val toUnwedge = wedgedMutex.withLock { + wedgedDevices.filter { + val lastForcedDate = lastNewSessionForcedDates[it] ?: 0 + if (now - lastForcedDate < DefaultCryptoService.CRYPTO_MIN_FORCE_SESSION_PERIOD_MILLIS) { + Timber.tag(loggerTag.value).d("Unwedging, New session for $it already forced with device at $lastForcedDate") + return@filter false + } + // let's already mark that we tried now + lastNewSessionForcedDates[it] = now + true } - // let's already mark that we tried now - lastNewSessionForcedDates[it] = now - true } if (toUnwedge.isEmpty()) { @@ -230,6 +237,15 @@ internal class EventDecryptor @Inject constructor( withContext(coroutineDispatchers.io) { sendToDeviceTask.executeRetry(sendToDeviceParams, remainingRetry = SEND_TO_DEVICE_RETRY_COUNT) } + + deviceList.values.flatten().forEach { deviceInfo -> + wedgedMutex.withLock { + wedgedDevices.removeAll { + it.senderKey == deviceInfo.identityKey() && + it.userId == deviceInfo.userId + } + } + } } catch (failure: Throwable) { deviceList.flatMap { it.value }.joinToString { it.shortDebugString() }.let { Timber.tag(loggerTag.value).e(failure, "## Failed to unwedge devices: $it}") From 4c554e4e85a26166897c551f46b7596a12cc32ef Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 15 Jul 2022 14:18:35 +0200 Subject: [PATCH 128/131] fix unused import --- .../java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt index 03e19f0bbb..5fe7376184 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt @@ -21,7 +21,6 @@ import org.amshove.kluent.shouldBe import org.junit.Assert import org.junit.Before import org.junit.FixMethodOrder -import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters From cda100e596f99dd4956c6eaf34cf90ad90561862 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 13 Jul 2022 16:21:12 +0200 Subject: [PATCH 129/131] Using same string key for stop + fix insets in button styles --- .../src/main/res/values/styles_location.xml | 15 ++++++++++++--- .../item_live_location_users_bottom_sheet.xml | 3 +-- .../layout/view_location_live_message_banner.xml | 10 +++++----- .../main/res/layout/view_location_live_status.xml | 2 +- vector/src/main/res/values/strings.xml | 3 ++- 5 files changed, 21 insertions(+), 12 deletions(-) diff --git a/library/ui-styles/src/main/res/values/styles_location.xml b/library/ui-styles/src/main/res/values/styles_location.xml index 6777450a63..41ddbc73ca 100644 --- a/library/ui-styles/src/main/res/values/styles_location.xml +++ b/library/ui-styles/src/main/res/values/styles_location.xml @@ -5,8 +5,11 @@ ?selectableItemBackground @android:color/transparent 12sp - 0dp center + 0dp + 0dp + 8dp + 8dp