From 527258789763e002f159470b48158842bb01b44f Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 6 May 2025 22:39:18 +0200 Subject: [PATCH] change (member moderation) : extract in a separate module --- features/roomdetails/impl/build.gradle.kts | 1 + .../roomdetails/impl/di/RoomDetailsModule.kt | 23 --- .../impl/members/RoomMemberListNode.kt | 14 ++ .../impl/members/RoomMemberListPresenter.kt | 16 +- .../impl/members/RoomMemberListState.kt | 4 +- .../members/RoomMemberListStateProvider.kt | 23 ++- .../impl/members/RoomMemberListView.kt | 11 +- .../moderation/ConfirmingRoomMemberAction.kt | 15 -- .../moderation/RoomMembersModerationEvents.kt | 21 --- .../moderation/RoomMembersModerationState.kt | 30 ---- .../RoomMembersModerationStateProvider.kt | 95 ------------ .../roommembermoderation/api/build.gradle.kts | 21 +++ .../api/RoomMemberModerationEvents.kt | 15 ++ .../api/RoomMemberModerationRenderer.kt | 20 +++ .../api/RoomMemberModerationState.kt | 23 +++ .../impl/build.gradle.kts | 39 +++++ .../DefaultRoomMemberModerationRenderer.kt | 37 +++++ .../InternalRoomMemberModerationEvents.kt | 17 +++ .../impl/InternalRoomMemberModerationState.kt | 32 ++++ .../impl/RoomMemberModerationPresenter.kt} | 144 ++++++++++-------- .../impl/RoomMemberModerationStateProvider.kt | 94 ++++++++++++ .../impl/RoomMemberModerationView.kt} | 110 +++++++------ .../impl/di/RoomMemberModerationModule.kt | 24 +++ .../src/main/res/values-be/translations.xml | 18 +++ .../src/main/res/values-cs/translations.xml | 21 +++ .../src/main/res/values-cy/translations.xml | 21 +++ .../src/main/res/values-de/translations.xml | 21 +++ .../src/main/res/values-el/translations.xml | 21 +++ .../src/main/res/values-es/translations.xml | 18 +++ .../src/main/res/values-et/translations.xml | 21 +++ .../src/main/res/values-eu/translations.xml | 16 ++ .../src/main/res/values-fa/translations.xml | 21 +++ .../src/main/res/values-fi/translations.xml | 21 +++ .../src/main/res/values-fr/translations.xml | 21 +++ .../src/main/res/values-hu/translations.xml | 21 +++ .../src/main/res/values-it/translations.xml | 18 +++ .../src/main/res/values-ka/translations.xml | 18 +++ .../src/main/res/values-nb/translations.xml | 21 +++ .../src/main/res/values-nl/translations.xml | 18 +++ .../src/main/res/values-pl/translations.xml | 21 +++ .../main/res/values-pt-rBR/translations.xml | 18 +++ .../src/main/res/values-pt/translations.xml | 19 +++ .../src/main/res/values-ro/translations.xml | 18 +++ .../src/main/res/values-ru/translations.xml | 20 +++ .../src/main/res/values-sk/translations.xml | 21 +++ .../src/main/res/values-sv/translations.xml | 21 +++ .../src/main/res/values-tr/translations.xml | 18 +++ .../src/main/res/values-uk/translations.xml | 21 +++ .../main/res/values-zh-rTW/translations.xml | 21 +++ .../src/main/res/values-zh/translations.xml | 21 +++ .../impl/src/main/res/values/localazy.xml | 21 +++ .../src/main/res/values-be/translations.xml | 9 -- .../src/main/res/values-cs/translations.xml | 12 -- .../src/main/res/values-cy/translations.xml | 12 -- .../src/main/res/values-de/translations.xml | 12 -- .../src/main/res/values-el/translations.xml | 12 -- .../src/main/res/values-es/translations.xml | 9 -- .../src/main/res/values-et/translations.xml | 12 -- .../src/main/res/values-eu/translations.xml | 8 - .../src/main/res/values-fa/translations.xml | 12 -- .../src/main/res/values-fi/translations.xml | 12 -- .../src/main/res/values-fr/translations.xml | 12 -- .../src/main/res/values-hu/translations.xml | 12 -- .../src/main/res/values-in/translations.xml | 9 -- .../src/main/res/values-it/translations.xml | 9 -- .../src/main/res/values-ka/translations.xml | 9 -- .../src/main/res/values-nb/translations.xml | 12 -- .../src/main/res/values-nl/translations.xml | 9 -- .../src/main/res/values-pl/translations.xml | 12 -- .../main/res/values-pt-rBR/translations.xml | 9 -- .../src/main/res/values-pt/translations.xml | 10 -- .../src/main/res/values-ro/translations.xml | 9 -- .../src/main/res/values-ru/translations.xml | 11 -- .../src/main/res/values-sk/translations.xml | 12 -- .../src/main/res/values-sv/translations.xml | 12 -- .../src/main/res/values-tr/translations.xml | 9 -- .../src/main/res/values-uk/translations.xml | 12 -- .../main/res/values-zh-rTW/translations.xml | 12 -- .../src/main/res/values-zh/translations.xml | 12 -- tools/localazy/config.json | 8 + 80 files changed, 1062 insertions(+), 633 deletions(-) delete mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/di/RoomDetailsModule.kt delete mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/ConfirmingRoomMemberAction.kt delete mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationEvents.kt delete mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationState.kt delete mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationStateProvider.kt create mode 100644 features/roommembermoderation/api/build.gradle.kts create mode 100644 features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationEvents.kt create mode 100644 features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationRenderer.kt create mode 100644 features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationState.kt create mode 100644 features/roommembermoderation/impl/build.gradle.kts create mode 100644 features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/DefaultRoomMemberModerationRenderer.kt create mode 100644 features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/InternalRoomMemberModerationEvents.kt create mode 100644 features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/InternalRoomMemberModerationState.kt rename features/{roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationPresenter.kt => roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationPresenter.kt} (53%) create mode 100644 features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationStateProvider.kt rename features/{roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationView.kt => roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt} (72%) create mode 100644 features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/di/RoomMemberModerationModule.kt create mode 100644 features/roommembermoderation/impl/src/main/res/values-be/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-cs/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-cy/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-de/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-el/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-es/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-et/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-eu/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-fa/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-fi/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-fr/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-hu/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-it/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-ka/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-nb/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-nl/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-pl/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-pt/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-ro/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-ru/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-sk/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-sv/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-tr/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-uk/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-zh-rTW/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-zh/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values/localazy.xml diff --git a/features/roomdetails/impl/build.gradle.kts b/features/roomdetails/impl/build.gradle.kts index 87ca1afe4d..a23997b43d 100644 --- a/features/roomdetails/impl/build.gradle.kts +++ b/features/roomdetails/impl/build.gradle.kts @@ -54,6 +54,7 @@ dependencies { implementation(projects.features.knockrequests.api) implementation(projects.features.verifysession.api) implementation(projects.features.reportroom.api) + implementation(projects.features.roommembermoderation.api) testImplementation(libs.test.junit) testImplementation(libs.coroutines.test) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/di/RoomDetailsModule.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/di/RoomDetailsModule.kt deleted file mode 100644 index 0361cfb2ca..0000000000 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/di/RoomDetailsModule.kt +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2024 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.features.roomdetails.impl.di - -import com.squareup.anvil.annotations.ContributesTo -import dagger.Binds -import dagger.Module -import io.element.android.features.roomdetails.impl.members.moderation.RoomMembersModerationPresenter -import io.element.android.features.roomdetails.impl.members.moderation.RoomMembersModerationState -import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.di.RoomScope - -@Module -@ContributesTo(RoomScope::class) -interface RoomDetailsModule { - @Binds - fun bindRoomMembersModerationPresenter(presenter: RoomMembersModerationPresenter): Presenter -} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListNode.kt index b1eb471391..05a35fad88 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListNode.kt @@ -18,6 +18,9 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedInject import im.vector.app.features.analytics.plan.MobileScreen import io.element.android.anvilannotations.ContributesNode +import io.element.android.features.roommembermoderation.api.ModerationAction +import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents +import io.element.android.features.roommembermoderation.api.RoomMemberModerationRenderer import io.element.android.libraries.di.RoomScope import io.element.android.libraries.matrix.api.core.UserId import io.element.android.services.analytics.api.AnalyticsService @@ -28,6 +31,7 @@ class RoomMemberListNode @AssistedInject constructor( @Assisted plugins: List, presenterFactory: RoomMemberListPresenter.Factory, private val analyticsService: AnalyticsService, + private val roomMemberModerationRenderer: RoomMemberModerationRenderer, ) : Node(buildContext, plugins = plugins), RoomMemberListNavigator { interface Callback : Plugin { fun openRoomMemberDetails(roomMemberId: UserId) @@ -69,6 +73,16 @@ class RoomMemberListNode @AssistedInject constructor( modifier = modifier, navigator = this, ) + roomMemberModerationRenderer.Render( + state = state.moderationState, + onSelectAction = { action -> + when (action) { + is ModerationAction.DisplayProfile -> openRoomMemberDetails(action.member.userId) + else -> state.moderationState.eventSink(RoomMemberModerationEvents.ProcessAction(action)) + } + }, + modifier = Modifier, + ) } } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListPresenter.kt index e2527444aa..07688387e3 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListPresenter.kt @@ -19,8 +19,9 @@ import androidx.compose.runtime.setValue import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import io.element.android.features.roomdetails.impl.members.moderation.RoomMembersModerationEvents -import io.element.android.features.roomdetails.impl.members.moderation.RoomMembersModerationState +import io.element.android.features.roommembermoderation.api.ModerationAction +import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents +import io.element.android.features.roommembermoderation.api.RoomMemberModerationState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.CoroutineDispatchers @@ -34,6 +35,7 @@ import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.RoomMembershipState import io.element.android.libraries.matrix.api.room.roomMembers import io.element.android.libraries.matrix.ui.room.canInviteAsState +import io.element.android.libraries.matrix.ui.room.isDmAsState import io.element.android.libraries.matrix.ui.room.roomMemberIdentityStateChange import kotlinx.collections.immutable.ImmutableMap import kotlinx.collections.immutable.persistentMapOf @@ -48,7 +50,7 @@ class RoomMemberListPresenter @AssistedInject constructor( private val room: JoinedRoom, private val roomMemberListDataSource: RoomMemberListDataSource, private val coroutineDispatchers: CoroutineDispatchers, - private val roomMembersModerationPresenter: Presenter, + private val roomMembersModerationPresenter: Presenter, private val encryptionService: EncryptionService, @Assisted private val navigator: RoomMemberListNavigator, ) : Presenter { @@ -69,7 +71,7 @@ class RoomMemberListPresenter @AssistedInject constructor( val membersState by room.membersStateFlow.collectAsState() val syncUpdateFlow = room.syncUpdateFlow.collectAsState() val canInvite by room.canInviteAsState(syncUpdateFlow.value) - + val isDm = room.isDmAsState() val roomModerationState = roomMembersModerationPresenter.present() val roomMemberIdentityStates by produceState(persistentMapOf()) { @@ -163,8 +165,10 @@ class RoomMemberListPresenter @AssistedInject constructor( is RoomMemberListEvents.OnSearchActiveChanged -> isSearchActive = event.active is RoomMemberListEvents.UpdateSearchQuery -> searchQuery = event.query is RoomMemberListEvents.RoomMemberSelected -> - if (roomModerationState.canDisplayModerationActions) { - roomModerationState.eventSink(RoomMembersModerationEvents.SelectRoomMember(event.roomMember)) + if (event.roomMember.membership == RoomMembershipState.BAN) { + roomModerationState.eventSink(RoomMemberModerationEvents.ProcessAction(ModerationAction.UnbanUser(event.roomMember))) + } else if (!isDm.value && (roomModerationState.canBan || roomModerationState.canKick)) { + roomModerationState.eventSink(RoomMemberModerationEvents.RenderActions(event.roomMember)) } else { navigator.openRoomMemberDetails(event.roomMember.userId) } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListState.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListState.kt index b5fa6c37a9..8e492e5371 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListState.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListState.kt @@ -7,7 +7,7 @@ package io.element.android.features.roomdetails.impl.members -import io.element.android.features.roomdetails.impl.members.moderation.RoomMembersModerationState +import io.element.android.features.roommembermoderation.api.RoomMemberModerationState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.theme.components.SearchBarResultState import io.element.android.libraries.matrix.api.encryption.identity.IdentityState @@ -20,7 +20,7 @@ data class RoomMemberListState( val searchResults: SearchBarResultState>, val isSearchActive: Boolean, val canInvite: Boolean, - val moderationState: RoomMembersModerationState, + val moderationState: RoomMemberModerationState, val eventSink: (RoomMemberListEvents) -> Unit, ) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt index 6fec01c675..09a7d9c910 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt @@ -8,8 +8,8 @@ package io.element.android.features.roomdetails.impl.members import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import io.element.android.features.roomdetails.impl.members.moderation.RoomMembersModerationState -import io.element.android.features.roomdetails.impl.members.moderation.aRoomMembersModerationState +import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents +import io.element.android.features.roommembermoderation.api.RoomMemberModerationState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.theme.components.SearchBarResultState import io.element.android.libraries.matrix.api.core.UserId @@ -87,7 +87,7 @@ internal class RoomMemberListStateBannedProvider : PreviewParameterProvider = AsyncData.Loading(), searchResults: SearchBarResultState> = SearchBarResultState.Initial(), - moderationState: RoomMembersModerationState = aRoomMembersModerationState(), + moderationState: RoomMemberModerationState = aRoomMemberModerationState(), ) = RoomMemberListState( roomMembers = roomMembers, searchQuery = "", @@ -130,6 +130,17 @@ internal fun aRoomMemberListState( eventSink = {} ) +fun aRoomMemberModerationState( + canBan: Boolean = false, + canKick: Boolean = false, +): RoomMemberModerationState { + return object : RoomMemberModerationState { + override val canKick: Boolean = canKick + override val canBan: Boolean = canBan + override val eventSink: (RoomMemberModerationEvents) -> Unit = {} + } +} + fun aRoomMember( userId: UserId = UserId("@alice:server.org"), displayName: String? = null, diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListView.kt index 875606f948..fab12adb4a 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListView.kt @@ -45,7 +45,7 @@ import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.roomdetails.impl.R -import io.element.android.features.roomdetails.impl.members.moderation.RoomMembersModerationView +import io.element.android.features.roommembermoderation.api.RoomMemberModerationState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.button.BackButton @@ -99,7 +99,7 @@ fun RoomMemberListView( } ) { padding -> var selectedSection by remember { mutableStateOf(SelectedSection.entries[initialSelectedSectionIndex]) } - if (!state.moderationState.canDisplayBannedUsers && selectedSection == SelectedSection.BANNED) { + if (!state.moderationState.canBan && selectedSection == SelectedSection.BANNED) { SideEffect { selectedSection = SelectedSection.MEMBERS } @@ -127,7 +127,7 @@ fun RoomMemberListView( RoomMemberList( roomMembers = state.roomMembers, showMembersCount = true, - canDisplayBannedUsersControls = state.moderationState.canDisplayBannedUsers, + canDisplayBannedUsersControls = state.moderationState.canBan, selectedSection = selectedSection, onSelectedSectionChange = { selectedSection = it }, onSelectUser = ::onSelectUser, @@ -135,11 +135,6 @@ fun RoomMemberListView( } } } - - RoomMembersModerationView( - state = state.moderationState, - onDisplayMemberProfile = navigator::openRoomMemberDetails - ) } @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/ConfirmingRoomMemberAction.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/ConfirmingRoomMemberAction.kt deleted file mode 100644 index b561dc9ac7..0000000000 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/ConfirmingRoomMemberAction.kt +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2024 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.features.roomdetails.impl.members.moderation - -import io.element.android.libraries.architecture.AsyncAction -import io.element.android.libraries.matrix.api.room.RoomMember - -data class ConfirmingRoomMemberAction( - val roomMember: RoomMember, -) : AsyncAction.Confirming diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationEvents.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationEvents.kt deleted file mode 100644 index eaabc8e4c2..0000000000 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationEvents.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2024 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.features.roomdetails.impl.members.moderation - -import io.element.android.libraries.matrix.api.core.UserId -import io.element.android.libraries.matrix.api.room.RoomMember - -sealed interface RoomMembersModerationEvents { - data class SelectRoomMember(val roomMember: RoomMember) : RoomMembersModerationEvents - data object KickUser : RoomMembersModerationEvents - data class DoKickUser(val reason: String) : RoomMembersModerationEvents - data object BanUser : RoomMembersModerationEvents - data class DoBanUser(val reason: String) : RoomMembersModerationEvents - data class UnbanUser(val userId: UserId) : RoomMembersModerationEvents - data object Reset : RoomMembersModerationEvents -} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationState.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationState.kt deleted file mode 100644 index a6c9a3e704..0000000000 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationState.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2024 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.features.roomdetails.impl.members.moderation - -import io.element.android.libraries.architecture.AsyncAction -import io.element.android.libraries.matrix.api.core.UserId -import io.element.android.libraries.matrix.api.room.RoomMember -import kotlinx.collections.immutable.ImmutableList - -data class RoomMembersModerationState( - val canDisplayModerationActions: Boolean, - val selectedRoomMember: RoomMember?, - val actions: ImmutableList, - val kickUserAsyncAction: AsyncAction, - val banUserAsyncAction: AsyncAction, - val unbanUserAsyncAction: AsyncAction, - val canDisplayBannedUsers: Boolean, - val eventSink: (RoomMembersModerationEvents) -> Unit, -) - -sealed interface ModerationAction { - data class DisplayProfile(val userId: UserId) : ModerationAction - data class KickUser(val userId: UserId) : ModerationAction - data class BanUser(val userId: UserId) : ModerationAction -} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationStateProvider.kt deleted file mode 100644 index 9139100980..0000000000 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationStateProvider.kt +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2024 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.features.roomdetails.impl.members.moderation - -import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import io.element.android.features.roomdetails.impl.members.anAlice -import io.element.android.libraries.architecture.AsyncAction -import io.element.android.libraries.matrix.api.room.RoomMember -import kotlinx.collections.immutable.toPersistentList - -class RoomMembersModerationStateProvider : PreviewParameterProvider { - override val values: Sequence - get() = sequenceOf( - aRoomMembersModerationState( - selectedRoomMember = anAlice(), - actions = listOf( - ModerationAction.DisplayProfile(anAlice().userId), - ), - ), - aRoomMembersModerationState( - selectedRoomMember = anAlice(), - actions = listOf( - ModerationAction.DisplayProfile(anAlice().userId), - ModerationAction.KickUser(userId = anAlice().userId), - ), - ), - aRoomMembersModerationState( - selectedRoomMember = anAlice(), - actions = listOf( - ModerationAction.DisplayProfile(anAlice().userId), - ModerationAction.KickUser(userId = anAlice().userId), - ModerationAction.BanUser(userId = anAlice().userId), - ), - ), - aRoomMembersModerationState( - selectedRoomMember = anAlice(), - kickUserAsyncAction = AsyncAction.ConfirmingNoParams, - ), - aRoomMembersModerationState( - selectedRoomMember = anAlice(), - kickUserAsyncAction = AsyncAction.Loading, - ), - aRoomMembersModerationState( - selectedRoomMember = anAlice(), - banUserAsyncAction = AsyncAction.ConfirmingNoParams, - ), - aRoomMembersModerationState( - selectedRoomMember = anAlice(), - banUserAsyncAction = AsyncAction.Loading, - ), - aRoomMembersModerationState( - selectedRoomMember = anAlice(), - unbanUserAsyncAction = AsyncAction.Loading, - ), - aRoomMembersModerationState( - kickUserAsyncAction = AsyncAction.Failure(Exception("Failed to kick user")), - banUserAsyncAction = AsyncAction.Failure(Exception("Failed to ban user")), - unbanUserAsyncAction = AsyncAction.Failure(Exception("Failed to unban user")), - ), - aRoomMembersModerationState( - selectedRoomMember = anAlice(), - unbanUserAsyncAction = ConfirmingRoomMemberAction(anAlice()), - ), - aRoomMembersModerationState( - kickUserAsyncAction = AsyncAction.Success(Unit), - banUserAsyncAction = AsyncAction.Success(Unit), - unbanUserAsyncAction = AsyncAction.Success(Unit), - ), - ) -} - -fun aRoomMembersModerationState( - canDisplayModerationActions: Boolean = false, - selectedRoomMember: RoomMember? = null, - actions: List = emptyList(), - kickUserAsyncAction: AsyncAction = AsyncAction.Uninitialized, - banUserAsyncAction: AsyncAction = AsyncAction.Uninitialized, - unbanUserAsyncAction: AsyncAction = AsyncAction.Uninitialized, - canDisplayBannedUsers: Boolean = false, - eventSink: (RoomMembersModerationEvents) -> Unit = {}, -) = RoomMembersModerationState( - canDisplayModerationActions = canDisplayModerationActions, - selectedRoomMember = selectedRoomMember, - actions = actions.toPersistentList(), - kickUserAsyncAction = kickUserAsyncAction, - banUserAsyncAction = banUserAsyncAction, - unbanUserAsyncAction = unbanUserAsyncAction, - canDisplayBannedUsers = canDisplayBannedUsers, - eventSink = eventSink, -) diff --git a/features/roommembermoderation/api/build.gradle.kts b/features/roommembermoderation/api/build.gradle.kts new file mode 100644 index 0000000000..aeea031757 --- /dev/null +++ b/features/roommembermoderation/api/build.gradle.kts @@ -0,0 +1,21 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +plugins { + id("io.element.android-compose-library") +} + +android { + namespace = "io.element.android.features.roommembermoderation.api" +} + +dependencies { + implementation(projects.libraries.architecture) + implementation(projects.libraries.designsystem) + implementation(projects.libraries.uiStrings) + implementation(projects.libraries.matrix.api) +} diff --git a/features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationEvents.kt b/features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationEvents.kt new file mode 100644 index 0000000000..265a59a125 --- /dev/null +++ b/features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationEvents.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.roommembermoderation.api + +import io.element.android.libraries.matrix.api.room.RoomMember + +interface RoomMemberModerationEvents { + data class RenderActions(val roomMember: RoomMember) : RoomMemberModerationEvents + data class ProcessAction(val action: ModerationAction): RoomMemberModerationEvents +} diff --git a/features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationRenderer.kt b/features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationRenderer.kt new file mode 100644 index 0000000000..2911bf1b8b --- /dev/null +++ b/features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationRenderer.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.roommembermoderation.api + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier + +interface RoomMemberModerationRenderer { + @Composable + fun Render( + state: RoomMemberModerationState, + onSelectAction: (ModerationAction) -> Unit, + modifier: Modifier, + ) +} diff --git a/features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationState.kt b/features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationState.kt new file mode 100644 index 0000000000..410b8d6423 --- /dev/null +++ b/features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationState.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.roommembermoderation.api + +import io.element.android.libraries.matrix.api.room.RoomMember + +interface RoomMemberModerationState { + val canKick: Boolean + val canBan: Boolean + val eventSink: (RoomMemberModerationEvents) -> Unit +} + +sealed interface ModerationAction { + data class DisplayProfile(val member: RoomMember) : ModerationAction + data class KickUser(val member: RoomMember) : ModerationAction + data class BanUser(val member: RoomMember) : ModerationAction + data class UnbanUser(val member: RoomMember) : ModerationAction +} diff --git a/features/roommembermoderation/impl/build.gradle.kts b/features/roommembermoderation/impl/build.gradle.kts new file mode 100644 index 0000000000..3d566077eb --- /dev/null +++ b/features/roommembermoderation/impl/build.gradle.kts @@ -0,0 +1,39 @@ +import extension.setupAnvil + +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +plugins { + id("io.element.android-compose-library") +} + +android { + namespace = "io.element.android.features.roommembermoderation.impl" +} + +setupAnvil() + +dependencies { + implementation(projects.libraries.core) + implementation(projects.libraries.architecture) + implementation(projects.libraries.matrix.api) + implementation(projects.libraries.matrixui) + api(projects.features.roommembermoderation.api) + implementation(projects.libraries.designsystem) + implementation(projects.libraries.uiStrings) + implementation(projects.services.analytics.compose) + + testImplementation(libs.test.junit) + testImplementation(libs.coroutines.test) + testImplementation(libs.coroutines.core) + testImplementation(libs.molecule.runtime) + testImplementation(libs.test.truth) + testImplementation(libs.test.turbine) + testImplementation(projects.libraries.matrix.test) + testImplementation(projects.tests.testutils) + testImplementation(projects.services.analytics.test) +} diff --git a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/DefaultRoomMemberModerationRenderer.kt b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/DefaultRoomMemberModerationRenderer.kt new file mode 100644 index 0000000000..9a9cce3eb7 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/DefaultRoomMemberModerationRenderer.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.roommembermoderation.impl + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect +import androidx.compose.ui.Modifier +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.features.roommembermoderation.api.ModerationAction +import io.element.android.features.roommembermoderation.api.RoomMemberModerationRenderer +import io.element.android.features.roommembermoderation.api.RoomMemberModerationState +import io.element.android.libraries.di.RoomScope +import timber.log.Timber +import javax.inject.Inject + +@ContributesBinding(RoomScope::class) +class DefaultRoomMemberModerationRenderer @Inject constructor() : RoomMemberModerationRenderer { + @Composable + override fun Render( + state: RoomMemberModerationState, + onSelectAction: (ModerationAction) -> Unit, + modifier: Modifier + ) { + if (state is InternalRoomMemberModerationState) { + RoomMemberModerationView(state, onSelectAction, modifier) + } else { + SideEffect { + Timber.d("RoomMemberModerationRenderer: Render called with unsupported state: $state") + } + } + } +} diff --git a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/InternalRoomMemberModerationEvents.kt b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/InternalRoomMemberModerationEvents.kt new file mode 100644 index 0000000000..206a379698 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/InternalRoomMemberModerationEvents.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.roommembermoderation.impl + +import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents + +sealed interface InternalRoomMemberModerationEvents: RoomMemberModerationEvents { + data class DoKickUser(val reason: String) : InternalRoomMemberModerationEvents + data class DoBanUser(val reason: String) : InternalRoomMemberModerationEvents + data object DoUnbanUser : InternalRoomMemberModerationEvents + data object Reset : InternalRoomMemberModerationEvents +} diff --git a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/InternalRoomMemberModerationState.kt b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/InternalRoomMemberModerationState.kt new file mode 100644 index 0000000000..e6258f2003 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/InternalRoomMemberModerationState.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.roommembermoderation.impl + +import io.element.android.features.roommembermoderation.api.ModerationAction +import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents +import io.element.android.features.roommembermoderation.api.RoomMemberModerationState +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.matrix.api.room.RoomMember +import kotlinx.collections.immutable.ImmutableList + +data class InternalRoomMemberModerationState( + override val canKick: Boolean, + override val canBan: Boolean, + val selectedRoomMember: AsyncData, + val actions: ImmutableList, + val kickUserAsyncAction: AsyncAction, + val banUserAsyncAction: AsyncAction, + val unbanUserAsyncAction: AsyncAction, + override val eventSink: (RoomMemberModerationEvents) -> Unit, +) : RoomMemberModerationState { + + val canOnlyDisplayProfile = actions.size == 1 && actions.first() is ModerationAction.DisplayProfile + val canDisplayActions = actions.isNotEmpty() && !canOnlyDisplayProfile +} + diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationPresenter.kt b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationPresenter.kt similarity index 53% rename from features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationPresenter.kt rename to features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationPresenter.kt index af71e21dff..5f7fa80c60 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationPresenter.kt +++ b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationPresenter.kt @@ -5,31 +5,34 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.roomdetails.impl.members.moderation +package io.element.android.features.roommembermoderation.impl import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import im.vector.app.features.analytics.plan.RoomModeration +import io.element.android.features.roommembermoderation.api.ModerationAction +import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents +import io.element.android.features.roommembermoderation.api.RoomMemberModerationState import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.runUpdatingState import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.RoomMember -import io.element.android.libraries.matrix.api.room.RoomMembershipState import io.element.android.libraries.matrix.ui.room.canBanAsState import io.element.android.libraries.matrix.ui.room.canKickAsState -import io.element.android.libraries.matrix.ui.room.isDmAsState import io.element.android.libraries.matrix.ui.room.userPowerLevelAsState import io.element.android.services.analytics.api.AnalyticsService +import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.drop @@ -37,45 +40,20 @@ import kotlinx.coroutines.flow.take import kotlinx.coroutines.launch import javax.inject.Inject -class RoomMembersModerationPresenter @Inject constructor( +class RoomMemberModerationPresenter @Inject constructor( private val room: JoinedRoom, private val dispatchers: CoroutineDispatchers, private val analyticsService: AnalyticsService, -) : Presenter { - private var selectedMember by mutableStateOf(null) +) : Presenter { + private var selectedMember by mutableStateOf>(AsyncData.Uninitialized) @Composable - override fun present(): RoomMembersModerationState { + override fun present(): RoomMemberModerationState { val coroutineScope = rememberCoroutineScope() val syncUpdateFlow = room.syncUpdateFlow.collectAsState() - val canBan by room.canBanAsState(syncUpdateFlow.value) - val canKick by room.canKickAsState(syncUpdateFlow.value) - val isDm by room.isDmAsState() - val currentUserMemberPowerLevel by room.userPowerLevelAsState(syncUpdateFlow.value) - - val canDisplayModerationActions by remember { - derivedStateOf { !isDm && (canBan || canKick) } - } - val canDisplayBannedUsers by remember { - derivedStateOf { !isDm && canBan } - } - val moderationActions by remember { - derivedStateOf { - buildList { - selectedMember?.let { roomMember -> - add(ModerationAction.DisplayProfile(roomMember.userId)) - if (currentUserMemberPowerLevel > roomMember.powerLevel) { - if (canKick) { - add(ModerationAction.KickUser(roomMember.userId)) - } - if (canBan) { - add(ModerationAction.BanUser(roomMember.userId)) - } - } - } - }.toPersistentList() - } - } + val canBan = room.canBanAsState(syncUpdateFlow.value) + val canKick = room.canKickAsState(syncUpdateFlow.value) + val currentUserMemberPowerLevel = room.userPowerLevelAsState(syncUpdateFlow.value) val kickUserAsyncAction = remember { mutableStateOf(AsyncAction.Uninitialized as AsyncAction) } @@ -84,60 +62,92 @@ class RoomMembersModerationPresenter @Inject constructor( val unbanUserAsyncAction = remember { mutableStateOf(AsyncAction.Uninitialized as AsyncAction) } - fun handleEvent(event: RoomMembersModerationEvents) { + val moderationActions = remember { mutableStateOf(persistentListOf()) } + + fun handleEvent(event: RoomMemberModerationEvents) { when (event) { - is RoomMembersModerationEvents.SelectRoomMember -> { - if (event.roomMember.membership == RoomMembershipState.BAN && canBan) { - // In this case the view will render a dialog to confirm the unbanning of the user - unbanUserAsyncAction.value = ConfirmingRoomMemberAction(event.roomMember) - } else { - // In this case the view will render a bottom sheet. - selectedMember = event.roomMember + is RoomMemberModerationEvents.RenderActions -> { + selectedMember = AsyncData.Success(event.roomMember) + moderationActions.value = computeModerationActions( + member = event.roomMember, + canKick = canKick.value, + canBan = canBan.value, + currentUserMemberPowerLevel = currentUserMemberPowerLevel.value, + ) + } + is RoomMemberModerationEvents.ProcessAction -> { + when(val action = event.action) { + is ModerationAction.DisplayProfile -> Unit + is ModerationAction.KickUser -> { + selectedMember = AsyncData.Success(action.member) + kickUserAsyncAction.value = AsyncAction.ConfirmingNoParams + } + is ModerationAction.BanUser -> { + selectedMember = AsyncData.Success(action.member) + banUserAsyncAction.value = AsyncAction.ConfirmingNoParams + } + is ModerationAction.UnbanUser -> { + selectedMember = AsyncData.Success(action.member) + unbanUserAsyncAction.value = AsyncAction.ConfirmingNoParams + } } } - is RoomMembersModerationEvents.KickUser -> { - kickUserAsyncAction.value = AsyncAction.ConfirmingNoParams - } - is RoomMembersModerationEvents.DoKickUser -> { - selectedMember?.let { + is InternalRoomMemberModerationEvents.DoKickUser -> { + selectedMember.dataOrNull()?.let { coroutineScope.kickUser(it.userId, event.reason, kickUserAsyncAction) } - selectedMember = null + selectedMember = AsyncData.Uninitialized } - is RoomMembersModerationEvents.BanUser -> { - banUserAsyncAction.value = AsyncAction.ConfirmingNoParams - } - is RoomMembersModerationEvents.DoBanUser -> { - selectedMember?.let { + is InternalRoomMemberModerationEvents.DoBanUser -> { + selectedMember.dataOrNull()?.let { coroutineScope.banUser(it.userId, event.reason, banUserAsyncAction) } - selectedMember = null + selectedMember = AsyncData.Uninitialized } - is RoomMembersModerationEvents.UnbanUser -> { - // We are already confirming when we are reaching this point - coroutineScope.unbanUser(event.userId, unbanUserAsyncAction) - } - is RoomMembersModerationEvents.Reset -> { - selectedMember = null + is InternalRoomMemberModerationEvents.Reset -> { + selectedMember = AsyncData.Uninitialized kickUserAsyncAction.value = AsyncAction.Uninitialized banUserAsyncAction.value = AsyncAction.Uninitialized unbanUserAsyncAction.value = AsyncAction.Uninitialized } + is InternalRoomMemberModerationEvents.DoUnbanUser -> { + selectedMember.dataOrNull()?.let { + coroutineScope.unbanUser(it.userId, unbanUserAsyncAction) + } + selectedMember = AsyncData.Uninitialized + } } } - return RoomMembersModerationState( - canDisplayModerationActions = canDisplayModerationActions, + return InternalRoomMemberModerationState( + canKick = canKick.value, + canBan = canBan.value, selectedRoomMember = selectedMember, - actions = moderationActions, + actions = moderationActions.value, kickUserAsyncAction = kickUserAsyncAction.value, banUserAsyncAction = banUserAsyncAction.value, unbanUserAsyncAction = unbanUserAsyncAction.value, - canDisplayBannedUsers = canDisplayBannedUsers, eventSink = { handleEvent(it) }, ) } + private fun computeModerationActions( + member: RoomMember, + canKick: Boolean, + canBan: Boolean, + currentUserMemberPowerLevel: Long, + ): PersistentList { + return buildList { + add(ModerationAction.DisplayProfile(member)) + if (canKick && member.powerLevel < currentUserMemberPowerLevel) { + add(ModerationAction.KickUser(member)) + } + if (canBan && member.powerLevel < currentUserMemberPowerLevel) { + add(ModerationAction.BanUser(member)) + } + }.toPersistentList() + } + private fun CoroutineScope.kickUser( userId: UserId, reason: String, @@ -167,7 +177,7 @@ class RoomMembersModerationPresenter @Inject constructor( unbanUserAction: MutableState>, ) = runActionAndWaitForMembershipChange(unbanUserAction) { analyticsService.capture(RoomModeration(RoomModeration.Action.UnbanMember)) - room.unbanUser(userId) + room.unbanUser(userId = userId) } private fun CoroutineScope.runActionAndWaitForMembershipChange( diff --git a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationStateProvider.kt b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationStateProvider.kt new file mode 100644 index 0000000000..b705e5217d --- /dev/null +++ b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationStateProvider.kt @@ -0,0 +1,94 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.roommembermoderation.impl + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.features.roommembermoderation.api.ModerationAction +import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.room.RoomMember +import io.element.android.libraries.matrix.api.room.RoomMembershipState +import kotlinx.collections.immutable.toPersistentList + +class RoomMemberModerationStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aRoomMembersModerationState( + selectedRoomMember = AsyncData.Success(anAlice()), + actions = listOf( + ModerationAction.DisplayProfile(anAlice()), + ), + ), + aRoomMembersModerationState( + selectedRoomMember = AsyncData.Success(anAlice()), + actions = listOf( + ModerationAction.DisplayProfile(anAlice()), + ModerationAction.KickUser(anAlice()), + ), + ), + aRoomMembersModerationState( + selectedRoomMember = AsyncData.Success(anAlice()), + actions = listOf( + ModerationAction.DisplayProfile(anAlice()), + ModerationAction.KickUser(anAlice()), + ModerationAction.BanUser(anAlice()), + ), + ), + aRoomMembersModerationState( + selectedRoomMember = AsyncData.Success(anAlice()), + kickUserAsyncAction = AsyncAction.ConfirmingNoParams, + ), + aRoomMembersModerationState( + selectedRoomMember = AsyncData.Success(anAlice()), + kickUserAsyncAction = AsyncAction.Loading, + ), + aRoomMembersModerationState( + selectedRoomMember = AsyncData.Success(anAlice()), + banUserAsyncAction = AsyncAction.ConfirmingNoParams, + ), + aRoomMembersModerationState( + selectedRoomMember = AsyncData.Success(anAlice()), + banUserAsyncAction = AsyncAction.Loading, + ), + ) +} + +fun anAlice() = RoomMember( + UserId(value = "@alice:server.org"), + displayName = "Alice", + avatarUrl = null, + role = RoomMember.Role.forPowerLevel(100L), + membership = RoomMembershipState.JOIN, + isNameAmbiguous = false, + powerLevel = 100L, + normalizedPowerLevel = 100L, + isIgnored = false, + membershipChangeReason = null, +) + +fun aRoomMembersModerationState( + canKick: Boolean = false, + canBan: Boolean = false, + selectedRoomMember: AsyncData = AsyncData.Uninitialized, + actions: List = emptyList(), + kickUserAsyncAction: AsyncAction = AsyncAction.Uninitialized, + banUserAsyncAction: AsyncAction = AsyncAction.Uninitialized, + unbanUserAsyncAction: AsyncAction = AsyncAction.Uninitialized, + eventSink: (RoomMemberModerationEvents) -> Unit = {}, +) = InternalRoomMemberModerationState( + canKick = canKick, + canBan = canBan, + selectedRoomMember = selectedRoomMember, + actions = actions.toPersistentList(), + kickUserAsyncAction = kickUserAsyncAction, + banUserAsyncAction = banUserAsyncAction, + unbanUserAsyncAction = unbanUserAsyncAction, + eventSink = eventSink, +) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationView.kt b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt similarity index 72% rename from features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationView.kt rename to features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt index 535a3fc5b7..ff949fde59 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationView.kt +++ b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.roomdetails.impl.members.moderation +package io.element.android.features.roommembermoderation.impl import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -20,7 +20,9 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource @@ -30,7 +32,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons -import io.element.android.features.roomdetails.impl.R +import io.element.android.features.roommembermoderation.api.ModerationAction import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.designsystem.components.async.AsyncIndicator import io.element.android.libraries.designsystem.components.async.AsyncIndicatorHost @@ -47,7 +49,6 @@ import io.element.android.libraries.designsystem.theme.components.ListItem import io.element.android.libraries.designsystem.theme.components.ListItemStyle import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet import io.element.android.libraries.designsystem.theme.components.Text -import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.getBestName import io.element.android.libraries.matrix.ui.model.getAvatarData @@ -57,32 +58,27 @@ import kotlinx.coroutines.launch import timber.log.Timber @Composable -fun RoomMembersModerationView( - state: RoomMembersModerationState, - onDisplayMemberProfile: (UserId) -> Unit, +fun RoomMemberModerationView( + state: InternalRoomMemberModerationState, + onSelectAction: (ModerationAction) -> Unit, modifier: Modifier = Modifier, ) { + val selectedRoomMember = state.selectedRoomMember.dataOrNull() Box(modifier = modifier) { - if (state.selectedRoomMember != null && state.actions.isNotEmpty()) { + if (selectedRoomMember != null && state.canDisplayActions) { RoomMemberActionsBottomSheet( - roomMember = state.selectedRoomMember, + roomMember = selectedRoomMember, actions = state.actions, - onSelectAction = { action -> - when (action) { - is ModerationAction.DisplayProfile -> { - onDisplayMemberProfile(action.userId) - } - is ModerationAction.KickUser -> { - state.eventSink(RoomMembersModerationEvents.KickUser) - } - is ModerationAction.BanUser -> { - state.eventSink(RoomMembersModerationEvents.BanUser) - } - } - }, - onDismiss = { state.eventSink(RoomMembersModerationEvents.Reset) }, + onSelectAction = onSelectAction, + onDismiss = { state.eventSink(InternalRoomMemberModerationEvents.Reset) }, ) } + val onSelectAction by rememberUpdatedState(onSelectAction) + LaunchedEffect(state.canOnlyDisplayProfile) { + if (state.canOnlyDisplayProfile) { + onSelectAction(state.actions.first()) + } + } val asyncIndicatorState = rememberAsyncIndicatorState() AsyncIndicatorHost(modifier = Modifier.statusBarsPadding(), state = asyncIndicatorState) @@ -90,23 +86,23 @@ fun RoomMembersModerationView( when (val action = state.kickUserAsyncAction) { is AsyncAction.Confirming -> { TextFieldDialog( - title = stringResource(CommonStrings.screen_bottom_sheet_manage_room_member_kick_member_confirmation_title), - submitText = stringResource(CommonStrings.screen_bottom_sheet_manage_room_member_kick_member_confirmation_action), + title = stringResource(R.string.screen_bottom_sheet_manage_room_member_kick_member_confirmation_title), + submitText = stringResource(R.string.screen_bottom_sheet_manage_room_member_kick_member_confirmation_action), onSubmit = { reason -> - state.eventSink(RoomMembersModerationEvents.DoKickUser(reason = reason)) + state.eventSink(InternalRoomMemberModerationEvents.DoKickUser(reason = reason)) }, - onDismissRequest = { state.eventSink(RoomMembersModerationEvents.Reset) }, + onDismissRequest = { state.eventSink(InternalRoomMemberModerationEvents.Reset) }, placeholder = stringResource(id = CommonStrings.common_reason), label = stringResource(id = CommonStrings.common_reason), - content = stringResource(CommonStrings.screen_bottom_sheet_manage_room_member_kick_member_confirmation_description), + content = stringResource(R.string.screen_bottom_sheet_manage_room_member_kick_member_confirmation_description), value = "", ) } is AsyncAction.Loading -> { LaunchedEffect(action) { - val userDisplayName = state.selectedRoomMember?.getBestName().orEmpty() + val userDisplayName = selectedRoomMember?.getBestName().orEmpty() asyncIndicatorState.enqueue { - AsyncIndicator.Loading(text = stringResource(CommonStrings.screen_bottom_sheet_manage_room_member_removing_user, userDisplayName)) + AsyncIndicator.Loading(text = stringResource(R.string.screen_bottom_sheet_manage_room_member_removing_user, userDisplayName)) } } } @@ -129,23 +125,23 @@ fun RoomMembersModerationView( when (val action = state.banUserAsyncAction) { is AsyncAction.Confirming -> { TextFieldDialog( - title = stringResource(CommonStrings.screen_bottom_sheet_manage_room_member_ban_member_confirmation_title), - submitText = stringResource(CommonStrings.screen_bottom_sheet_manage_room_member_ban_member_confirmation_action), + title = stringResource(R.string.screen_bottom_sheet_manage_room_member_ban_member_confirmation_title), + submitText = stringResource(R.string.screen_bottom_sheet_manage_room_member_ban_member_confirmation_action), onSubmit = { reason -> - state.eventSink(RoomMembersModerationEvents.DoBanUser(reason = reason)) + state.eventSink(InternalRoomMemberModerationEvents.DoBanUser(reason = reason)) }, - onDismissRequest = { state.eventSink(RoomMembersModerationEvents.Reset) }, + onDismissRequest = { state.eventSink(InternalRoomMemberModerationEvents.Reset) }, placeholder = stringResource(id = CommonStrings.common_reason), label = stringResource(id = CommonStrings.common_reason), - content = stringResource(CommonStrings.screen_bottom_sheet_manage_room_member_ban_member_confirmation_description), + content = stringResource(R.string.screen_bottom_sheet_manage_room_member_ban_member_confirmation_description), value = "", ) } is AsyncAction.Loading -> { LaunchedEffect(action) { - val userDisplayName = state.selectedRoomMember?.getBestName().orEmpty() + val userDisplayName = selectedRoomMember?.getBestName().orEmpty() asyncIndicatorState.enqueue { - AsyncIndicator.Loading(text = stringResource(CommonStrings.screen_bottom_sheet_manage_room_member_banning_user, userDisplayName)) + AsyncIndicator.Loading(text = stringResource(R.string.screen_bottom_sheet_manage_room_member_banning_user, userDisplayName)) } } } @@ -164,24 +160,21 @@ fun RoomMembersModerationView( } else -> Unit } - when (val action = state.unbanUserAsyncAction) { is AsyncAction.Confirming -> { - if (action is ConfirmingRoomMemberAction) { - ConfirmationDialog( - title = stringResource(R.string.screen_room_member_list_manage_member_unban_title), - content = stringResource(R.string.screen_room_member_list_manage_member_unban_message), - submitText = stringResource(R.string.screen_room_member_list_manage_member_unban_action), - onSubmitClick = { - val userDisplayName = action.roomMember.getBestName() - asyncIndicatorState.enqueue { - AsyncIndicator.Loading(text = stringResource(R.string.screen_room_member_list_unbanning_user, userDisplayName)) - } - state.eventSink(RoomMembersModerationEvents.UnbanUser(action.roomMember.userId)) - }, - onDismiss = { state.eventSink(RoomMembersModerationEvents.Reset) }, - ) - } + ConfirmationDialog( + title = stringResource(R.string.screen_room_member_list_manage_member_unban_title), + content = stringResource(R.string.screen_room_member_list_manage_member_unban_message), + submitText = stringResource(R.string.screen_room_member_list_manage_member_unban_action), + onSubmitClick = { + val userDisplayName = selectedRoomMember?.getBestName().orEmpty() + asyncIndicatorState.enqueue { + AsyncIndicator.Loading(text = stringResource(R.string.screen_room_member_list_unbanning_user, userDisplayName)) + } + state.eventSink(InternalRoomMemberModerationEvents.DoUnbanUser) + }, + onDismiss = { state.eventSink(InternalRoomMemberModerationEvents.Reset) }, + ) } is AsyncAction.Failure -> { Timber.e(action.error, "Failed to unban user.") @@ -260,7 +253,7 @@ private fun RoomMemberActionsBottomSheet( when (action) { is ModerationAction.DisplayProfile -> { ListItem( - headlineContent = { Text(stringResource(CommonStrings.screen_bottom_sheet_manage_room_member_member_user_info)) }, + headlineContent = { Text(stringResource(R.string.screen_bottom_sheet_manage_room_member_member_user_info)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Info())), onClick = { coroutineScope.launch { @@ -272,7 +265,7 @@ private fun RoomMemberActionsBottomSheet( } is ModerationAction.KickUser -> { ListItem( - headlineContent = { Text(stringResource(CommonStrings.screen_bottom_sheet_manage_room_member_remove)) }, + headlineContent = { Text(stringResource(R.string.screen_bottom_sheet_manage_room_member_remove)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Block())), onClick = { coroutineScope.launch { @@ -284,7 +277,7 @@ private fun RoomMemberActionsBottomSheet( } is ModerationAction.BanUser -> { ListItem( - headlineContent = { Text(stringResource(R.string.screen_room_member_list_manage_member_remove_confirmation_ban)) }, + headlineContent = { Text(stringResource(R.string.screen_bottom_sheet_manage_room_member_ban)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Block())), style = ListItemStyle.Destructive, onClick = { @@ -295,6 +288,7 @@ private fun RoomMemberActionsBottomSheet( } ) } + is ModerationAction.UnbanUser -> Unit } } } @@ -303,16 +297,16 @@ private fun RoomMemberActionsBottomSheet( @PreviewsDayNight @Composable -internal fun RoomMembersModerationViewPreview(@PreviewParameter(RoomMembersModerationStateProvider::class) state: RoomMembersModerationState) { +internal fun RoomMembersModerationViewPreview(@PreviewParameter(RoomMemberModerationStateProvider::class) state: InternalRoomMemberModerationState) { ElementPreview { Box( modifier = Modifier .fillMaxWidth() .heightIn(min = 64.dp) ) { - RoomMembersModerationView( + RoomMemberModerationView( state = state, - onDisplayMemberProfile = {}, + onSelectAction = {}, ) } } diff --git a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/di/RoomMemberModerationModule.kt b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/di/RoomMemberModerationModule.kt new file mode 100644 index 0000000000..d8caadd71f --- /dev/null +++ b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/di/RoomMemberModerationModule.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.roommembermoderation.impl.di + +import com.squareup.anvil.annotations.ContributesTo +import dagger.Binds +import dagger.Module +import io.element.android.features.roommembermoderation.api.RoomMemberModerationState +import io.element.android.features.roommembermoderation.impl.RoomMemberModerationPresenter +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.di.RoomScope +import io.element.android.libraries.di.SessionScope + +@ContributesTo(RoomScope::class) +@Module +interface RoomMemberModerationModule { + @Binds + fun bindRoomMemberModerationPresenter(presenter: RoomMemberModerationPresenter): Presenter +} diff --git a/features/roommembermoderation/impl/src/main/res/values-be/translations.xml b/features/roommembermoderation/impl/src/main/res/values-be/translations.xml new file mode 100644 index 0000000000..8a488cf10c --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-be/translations.xml @@ -0,0 +1,18 @@ + + + "Выдаліць і заблакіраваць удзельніка" + "Заблакіраваць" + "Яны не змогуць зноў далучыцца да гэтага пакоя, калі іх запросяць." + "Вы ўпэўнены, што хочаце заблакіраваць гэтага карыстальніка?" + "Блакіроўка %1$s" + "Прагляд профілю" + "Выдаліць удзельніка з пакоя" + "Выдаліць удзельніка і забараніць далучацца ў будучыні?" + "Выдаленне %1$s…" + "Выдаліць і заблакіраваць удзельніка" + "Толькі выдаліць удзельніка" + "Разблакіраваць" + "Яны змогуць зноў далучыцца да гэтага пакоя, калі іх запросяць." + "Разблакіраваць удзельніка" + "Разблакіроўка %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-cs/translations.xml b/features/roommembermoderation/impl/src/main/res/values-cs/translations.xml new file mode 100644 index 0000000000..490671e9ff --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-cs/translations.xml @@ -0,0 +1,21 @@ + + + "Odebrat a vykázat člena" + "Vykázat" + "Nebudou se moci znovu připojit k této místnosti, pokud budou pozváni." + "Jste si jisti, že chcete vykázat tohoto člena?" + "Vykazování %1$s" + "Odebrat" + "Budou moci znovu vstoupit do této místnosti, pokud budou pozváni." + "Opravdu chcete tohoto člena odebrat?" + "Zobrazit profil" + "Odebrat z místnosti" + "Odebrat člena a zakázat mu připojení v budoucnu?" + "Odstraňování %1$s…" + "Odebrat a vykázat člena" + "Pouze odebrat člena" + "Zrušit vykázání" + "Pokud budou pozváni, budou se moci do této místnosti znovu připojit." + "Zrušit vykázání uživatele" + "Rušení vykázání %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-cy/translations.xml b/features/roommembermoderation/impl/src/main/res/values-cy/translations.xml new file mode 100644 index 0000000000..55fc68adf0 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-cy/translations.xml @@ -0,0 +1,21 @@ + + + "Gwahardd o ystafell" + "Atal" + "Fyddan nhw ddim yn gallu ymuno â\'r ystafell hon eto os cân nhw wahoddiad." + "Ydych chi\'n siŵr eich bod am wahardd yr aelod hwn?" + "Yn gwahardd %1$s" + "Tynnu" + "Fyddan nhw yn gallu ymuno â\'r ystafell hon eto os cân nhw wahoddiad." + "Ydych chi\'n siŵr eich bod am ddileu\'r aelod hwn?" + "Gweld proffil" + "Tynnu o\'r ystafell" + "Dileu aelod a\'u gwahardd rhag ymuno yn y dyfodol?" + "Wrthi\'n dileu %1$s…" + "Gwahardd o ystafell" + "Dileu aelod yn unig" + "Adfer" + "Fyddan nhw yn gallu ymuno â\'r ystafell hon eto os cân nhw wahoddiad." + "Gwahardd defnyddiwr" + "Dad-wahardd %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-de/translations.xml b/features/roommembermoderation/impl/src/main/res/values-de/translations.xml new file mode 100644 index 0000000000..c1fb73626d --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-de/translations.xml @@ -0,0 +1,21 @@ + + + "Mitglied entfernen und sperren" + "Sperren" + "Sie können dem Raum nicht mehr beitreten, selbst wenn sie eingeladen werden." + "Bist du sicher, dass du dieses Mitglied sperren möchtest?" + "%1$s wird gesperrt." + "Entfernen" + "Sie können diesen Raum wieder betreten, wenn sie eingeladen werden." + "Möchten Sie dieses Mitglied wirklich entfernen?" + "Benutzerinformationen anzeigen" + "Mitglied entfernen" + "Mitglied entfernen und den erneuten Beitritt sperren?" + "%1$s wird entfernt." + "Mitglied entfernen und sperren" + "Mitglied nur entfernen" + "Sperre aufheben" + "Die Nutzer können den Raum wieder beitreten, wenn sie dazu eingeladen werden." + "Benutzer entsperren" + "%1$s wird entsperrt." + diff --git a/features/roommembermoderation/impl/src/main/res/values-el/translations.xml b/features/roommembermoderation/impl/src/main/res/values-el/translations.xml new file mode 100644 index 0000000000..85ea09cae4 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-el/translations.xml @@ -0,0 +1,21 @@ + + + "Αφαίρεση και αποκλεισμός μέλους" + "Αποκλεισμός" + "Δεν θα μπορεί να συμμετέχει ξανά σε αυτό το δωμάτιο εάν προσκληθεί." + "Θες σίγουρα να αποκλείσεις αυτό το μέλος;" + "Αποκλεισμός %1$s" + "Αφαίρεση" + "Θα μπορούν να συμμετάσχουν ξανά σε αυτό το δωμάτιο εάν προσκληθούν." + "Είστε βέβαιοι ότι θέλετε να αφαιρέσετε αυτό το μέλος;" + "Προβολή προφίλ" + "Αφαίρεση από το δωμάτιο" + "Αφαίρεση μέλους και απαγόρευση συμμετοχής στο μέλλον;" + "Αφαίρεση %1$s…" + "Αφαίρεση και αποκλεισμός μέλους" + "Μόνο αφαίρεση μέλους" + "Αναίρεση αποκλεισμού" + "Θα μπορεί να συμμετάσχει ξανά στο δωμάτιο εάν προσκληθεί." + "Άρση αποκλεισμού χρήστη" + "Άρση αποκλεισμού %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-es/translations.xml b/features/roommembermoderation/impl/src/main/res/values-es/translations.xml new file mode 100644 index 0000000000..08a49a1425 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-es/translations.xml @@ -0,0 +1,18 @@ + + + "Sacar y vetar a un miembro" + "Vetar" + "No podrán volver a unirse a esta sala si son invitados." + "¿Estás seguro de que quieres vetar a este miembro?" + "Vetando a %1$s" + "Ver perfil" + "Sacar de la sala" + "¿Sacar al miembro y prohibirle unirse en el futuro?" + "Eliminando %1$s…" + "Sacar y vetar a un miembro" + "Solo eliminar miembro" + "Quitar veto" + "Podrán volver a unirse a esta sala si son invitados de nuevo." + "Quitar veto al usuario" + "Levantando veto a %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-et/translations.xml b/features/roommembermoderation/impl/src/main/res/values-et/translations.xml new file mode 100644 index 0000000000..98a05ea6b6 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-et/translations.xml @@ -0,0 +1,21 @@ + + + "Eemalda ja sea suhtluskeeld" + "Sea suhtluskeeld" + "Ta ei saa selle jututoaga liituda isegi kutse olemasolul." + "Kas sa oled kindel, et soovid sellele kasutajale seada suhtluskeelu?" + "Seame kasutajale %1$s suhtluskeelu" + "Eemalda" + "Uue kutse saamisel on tal võimalik selle jututoaga uuesti liituda." + "Kas sa oled kindel, et soovid selle osaleja eemaldada?" + "Vaata profiili" + "Eemalda kasutaja jututoast" + "Kas eemaldama kasutaja ja seame talle tulevikuks suhtluskeelu?" + "Eemaldame kasutajat %1$s…" + "Eemalda ja sea suhtluskeeld" + "Ainult eemalda kasutaja" + "Eemalda suhtluskeeld" + "Kutse olemasolul saab ta nüüd jututoaga uuesti liituda" + "Eemalda kasutaja suhtluskeeld" + "Eemaldame suhtluskeelu kasutajalt %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-eu/translations.xml b/features/roommembermoderation/impl/src/main/res/values-eu/translations.xml new file mode 100644 index 0000000000..c3d1f7c5a8 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-eu/translations.xml @@ -0,0 +1,16 @@ + + + "Kendu kidea eta ezarri debekua" + "Ezarri debekua" + "Ziur kide honi debekua ezarri nahi diozula?" + "%1$s(r)i debekua ezartzen" + "Ikusi profila" + "Kendu gelatik" + "Kidea kendu eta etorkizunean sartzea debekatu?" + "%1$s kentzen…" + "Kendu kidea eta ezarri debekua" + "Kendu kidea soilik" + "Kendu debekua" + "Kendu debekua erabiltzaileari" + "%1$s(r)i debekua kentzen" + diff --git a/features/roommembermoderation/impl/src/main/res/values-fa/translations.xml b/features/roommembermoderation/impl/src/main/res/values-fa/translations.xml new file mode 100644 index 0000000000..d1b986598a --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-fa/translations.xml @@ -0,0 +1,21 @@ + + + "برداشت و تحریم عضو" + "تحریم" + "در صورت دعوت نمی‌تواند دوباره به اتاق بپیوندد." + "مطمئنید می‌خواهید این عضو را تحریم کنید؟" + "تحریم کردن %1$s" + "برداشتن" + "در صورت دعوت می‌تواند دوباره به اتاق بپیوندد." + "مطمئنید می‌خواهید این عضو را بردارید؟" + "دیدن نمایه" + "برداشتن از اتاق" + "برداشتن عضو و تحریم پیوستن در آینده؟" + "برداشتن %1$s…" + "برداشت و تحریم عضو" + "تنها برداشتن عضو" + "رفع انسداد" + "در صورت دعوت می‌تواند دوباره به اتاق بپیوندد." + "تحریم نکردن کاربر" + "رفع تحریم %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-fi/translations.xml b/features/roommembermoderation/impl/src/main/res/values-fi/translations.xml new file mode 100644 index 0000000000..050d20600a --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-fi/translations.xml @@ -0,0 +1,21 @@ + + + "Poista jäsen huoneesta ja anna porttikielto" + "Anna porttikielto" + "He eivät voi enää liittyä tähän huoneeseen, jos heidät kutsutaan." + "Haluatko varmasti antaa tälle jäsenelle porttikiellon?" + "Annetaan porttikieltoa käyttäjälle %1$s" + "Poista" + "He voivat liittyä tähän huoneeseen uudelleen, jos heidät kutsutaan." + "Haluatko varmasti poistaa tämän jäsenen?" + "Näytä profiili" + "Poista huoneesta" + "Poistetaanko jäsen huoneesta ja kielletäänkö heitä liittymästä tulevaisuudessa?" + "Poistetaan käyttäjää %1$s huoneesta…" + "Poista jäsen huoneesta ja anna porttikielto" + "Poista vain jäsen huoneesta" + "Poista porttikielto" + "He voivat liittyä tähän huoneeseen uudelleen, jos heidät kutsutaan." + "Poista käyttäjän porttikielto" + "Poistetaan käyttäjän %1$s porttikieltoa" + diff --git a/features/roommembermoderation/impl/src/main/res/values-fr/translations.xml b/features/roommembermoderation/impl/src/main/res/values-fr/translations.xml new file mode 100644 index 0000000000..88cfd7b309 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-fr/translations.xml @@ -0,0 +1,21 @@ + + + "Retirer et bannir ce membre" + "Bannir" + "Il ne pourra pas rejoindre le salon à nouveau, même si il est invité." + "Êtes-vous certain de vouloir bannir ce membre ?" + "Bannissement de %1$s" + "Retirer" + "Cet utilisateur pourra rejoindre le salon à nouveau si il est invité." + "Voulez-vous vraiment supprimer ce membre ?" + "Voir le profil" + "Retirer le membre du salon" + "Retirer le membre et interdire l’adhésion à l’avenir ?" + "Enlever %1$s…" + "Retirer et bannir ce membre" + "Retirer le membre uniquement" + "Débannir" + "Il pourra rejoindre le salon à nouveau si il est invité." + "Débannir l’utilisateur" + "Débannissement de %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-hu/translations.xml b/features/roommembermoderation/impl/src/main/res/values-hu/translations.xml new file mode 100644 index 0000000000..bb2123e479 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-hu/translations.xml @@ -0,0 +1,21 @@ + + + "Eltávolítás és a tag kitiltása" + "Kitiltás" + "Többé nem csatlakozhat ehhez a szobához, akkor sem, ha meghívják." + "Biztos, hogy kitiltja ezt a tagot?" + "%1$s kitiltása" + "Eltávolítás" + "Ehhez a szobához is csatlakozhat, ha meghívják." + "Biztos, hogy eltávolítja ezt a tagot?" + "Profil megtekintése" + "Eltávolítás a szobából" + "Eltávolítja a tagot, és megtiltja a jövőbeni csatlakozást?" + "%1$s eltávolítása…" + "Eltávolítás és a tag kitiltása" + "Csak a tag eltávolítása" + "Tiltás feloldása" + "Ehhez a szobához is csatlakozhat, ha meghívják." + "Felhasználó tiltásának feloldása" + "%1$s tiltásának feloldása" + diff --git a/features/roommembermoderation/impl/src/main/res/values-it/translations.xml b/features/roommembermoderation/impl/src/main/res/values-it/translations.xml new file mode 100644 index 0000000000..a1bdeed0b0 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-it/translations.xml @@ -0,0 +1,18 @@ + + + "Rimuovi ed escludi" + "Escludi" + "Non potrà entrare nuovamente in questa stanza se invitato." + "Vuoi davvero escludere questo membro?" + "Esclusione di %1$s" + "Visualizza profilo" + "Rimuovi dalla stanza" + "Rimuovere e vietare l\'accesso in futuro?" + "Rimozione di %1$s…" + "Rimuovi ed escludi" + "Rimuovi soltanto" + "Riammetti" + "Potrà entrare nuovamente in questa stanza se invitato." + "Riammetti utente" + "Riammissione di %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-ka/translations.xml b/features/roommembermoderation/impl/src/main/res/values-ka/translations.xml new file mode 100644 index 0000000000..730fff2714 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-ka/translations.xml @@ -0,0 +1,18 @@ + + + "წევრის წაშლა და დაბლოკვა" + "დაბლოკვა" + "მოწვევის შემთხვევაში ამ ოთახში კვლავ გაწევრიანებას ვერ შეძლებენ." + "დარწმუნებული ხართ, რომ ამ წევრის დაბლოკვა გსურთ?" + "%1$s-ს დაბლოკვა" + "პროფილის ნახვა" + "ოთახიდან გაგდება" + "გსურთ წევრის გაგდება და მომავალში გაწევრიანების აკრძალვა?" + "%1$s-ს გაგდება…" + "წევრის წაშლა და დაბლოკვა" + "მხოლოდ წევრის წაშლა" + "განბლოკვა" + "მოწვევის შემთხვევაში განბლოკილი მომხმარებელი ისევ შეძლებს ოთახს შეუერთდეს." + "მომხმარებლის განბლოკვა" + "%1$s-ს განბლოკვა" + diff --git a/features/roommembermoderation/impl/src/main/res/values-nb/translations.xml b/features/roommembermoderation/impl/src/main/res/values-nb/translations.xml new file mode 100644 index 0000000000..b25be530ec --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-nb/translations.xml @@ -0,0 +1,21 @@ + + + "Fjern og utesteng medlem" + "Utesteng" + "De vil ikke kunne bli med i dette rommet igjen hvis de blir invitert." + "Er du sikker på at du vil utestenge dette medlemmet?" + "Utestenger %1$s" + "Fjern" + "De vil kunne bli med i dette rommet igjen hvis de blir invitert." + "Er du sikker på at du vil fjerne dette medlemmet?" + "Vis profil" + "Fjern fra rommet" + "Fjerne medlem og utestenge fra å bli med i fremtiden?" + "Fjerner %1$s…" + "Fjern og utesteng medlem" + "Bare fjern medlem" + "Opphev utestengelse" + "De vil kunne bli med i dette rommet igjen hvis de blir invitert." + "Opphev utestengelse av bruker" + "Oppheve utestengelsen av %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-nl/translations.xml b/features/roommembermoderation/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..f025cbb584 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,18 @@ + + + "Lid verwijderen en verbannen" + "Verbannen" + "Ze kunnen niet meer toetreden tot deze kamer als ze worden uitgenodigd." + "Weet je zeker dat je dit lid wilt verbannen?" + "%1$s verbannen" + "Profiel bekijken" + "Verwijderen uit kamer" + "Lid verwijderen en toekomstige deelname verbieden?" + "%1$s wordt verwijderd…" + "Lid verwijderen en verbannen" + "Alleen lid verwijderen" + "Ontbannen" + "Ze kunnen opnieuw tot de kamer toetreden als ze worden uitgenodigd." + "Ontban gebruiker" + "%1$s ontbannen" + diff --git a/features/roommembermoderation/impl/src/main/res/values-pl/translations.xml b/features/roommembermoderation/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..40bd309913 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,21 @@ + + + "Usuń i zbanuj członka" + "Zbanuj" + "Nie będą mogli ponownie dołączyć do tego pokoju, jeśli zostaną zaproszeni." + "Czy na pewno chcesz zbanować tego członka?" + "Banowanie %1$s" + "Usuń" + "Będą mogli ponownie dołączyć do pokoju, jeśli zostaną zaproszeni." + "Czy na pewno chcesz usunąć tego członka?" + "Wyświetl profil" + "Usuń z pokoju" + "Usunąć członka i zablokować możliwość dołączenia w przyszłości?" + "Usuwanie %1$s…" + "Usuń i zbanuj członka" + "Tylko usuń członka" + "Odbanuj" + "Będą mogli ponownie dołączyć do tego pokoju, jeśli zostaną zaproszeni." + "Odbanuj użytkownika" + "Odbanowanie %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-pt-rBR/translations.xml b/features/roommembermoderation/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..764c313a96 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,18 @@ + + + "Remover e banir membro" + "Banir" + "Eles não poderão entrar nesta sala novamente se forem convidados." + "Tem certeza de que quer banir este membro?" + "Banindo %1$s" + "Ver perfil" + "Remover da sala" + "Remover membro e banir de entrar novamente no futuro?" + "Removendo %1$s…" + "Remover e banir membro" + "Somente remover membro" + "Desbanir" + "Eles poderão entrar nesta sala novamente se forem convidados." + "Desbanir usuário" + "Desbanindo %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-pt/translations.xml b/features/roommembermoderation/impl/src/main/res/values-pt/translations.xml new file mode 100644 index 0000000000..89ddd6f5ba --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-pt/translations.xml @@ -0,0 +1,19 @@ + + + "Remover e banir participante" + "Banir" + "Não poderão voltar a entrar nesta sala, mesmo se forem convidados." + "Tens a certeza que queres banir este participante?" + "A banir %1$s" + "Poderão entrar na sala novamente se convidados." + "Ver perfil" + "Remover da sala" + "Remover participante e proibir que entre no futuro?" + "A remover %1$s…" + "Remover e banir participante" + "Remover apenas" + "Anular banimento" + "Poderão juntar-se novamente a esta sala se forem convidados." + "Anular banimento do utilizador" + "A anular banimento de %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-ro/translations.xml b/features/roommembermoderation/impl/src/main/res/values-ro/translations.xml new file mode 100644 index 0000000000..526db044db --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-ro/translations.xml @@ -0,0 +1,18 @@ + + + "Eliminați și interziceți membrul" + "Interzicere" + "Nu se vor putea alătura din nou acestei camere dacă sunt invitați." + "Sunteți sigur că doriți să interziceți acest membru?" + "Se interzice %1$s" + "Vizualizare profil" + "Înlăturați membrul" + "Înlăturați membrul și interziceți-i să se alăture în viitor?" + "Se elimină %1$s" + "Eliminați și interziceți membrul" + "Doar înlăturare" + "Anulare excludere" + "Se vor putea alătura din nou acestei săli dacă sunt invitați." + "Anulați interzicerea utilizatorului" + "Se anulează interzicerea lui %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-ru/translations.xml b/features/roommembermoderation/impl/src/main/res/values-ru/translations.xml new file mode 100644 index 0000000000..93fa22ac3f --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-ru/translations.xml @@ -0,0 +1,20 @@ + + + "Удалить и заблокировать участника" + "Заблокировать" + "Они не смогут снова присоединиться к этой комнате, если их пригласят." + "Вы уверены, что хотите заблокировать этого участника?" + "Блокировка %1$s" + "Удалить" + "Вы действительно хотите удалить этого участника?" + "Посмотреть профиль" + "Удалить участника из комнаты" + "Удалить участника и запретить присоединяться в будущем?" + "Удаление %1$s…" + "Удалить и заблокировать участника" + "Только удалить участника" + "Разблокировать" + "Они снова смогут присоединиться в эту комнату если их пригласят." + "Разбанить пользователя?" + "Разблокировка %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-sk/translations.xml b/features/roommembermoderation/impl/src/main/res/values-sk/translations.xml new file mode 100644 index 0000000000..8e7c4a1399 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-sk/translations.xml @@ -0,0 +1,21 @@ + + + "Odstrániť a zakázať člena" + "Zakázať" + "Nebudú sa môcť pripojiť k tejto miestnosti znova ani ak budú pozvaní." + "Ste si istý, že chcete zakázať tohto člena?" + "Zakazuje sa %1$s" + "Odstrániť" + "V prípade pozvania sa budú môcť znova pripojiť k tejto miestnosti." + "Ste si istý, že chcete odstrániť tohto člena?" + "Zobraziť profil" + "Odstrániť z miestnosti" + "Odstrániť člena a zakázať vstup v budúcnosti?" + "Odstraňuje sa %1$s…" + "Odstrániť a zakázať člena" + "Iba odstrániť člena" + "Zrušiť zákaz" + "V prípade pozvania sa budú môcť znova pripojiť k tejto miestnosti." + "Zrušiť zákaz používateľa" + "Zrušenie zákazu %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-sv/translations.xml b/features/roommembermoderation/impl/src/main/res/values-sv/translations.xml new file mode 100644 index 0000000000..bb512b1142 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-sv/translations.xml @@ -0,0 +1,21 @@ + + + "Ta bort och banna medlem" + "Banna" + "Denne kommer inte att kunna gå med i det här rummet igen om denne bjuds in." + "Är du säker på att du vill banna den här medlemmen?" + "Bannar %1$s" + "Ta bort" + "Denne kommer kunna gå med i rummet igen om denne bjuds in" + "Är du säker på att du vill ta bort den här medlemmen?" + "Visa profil" + "Ta bort från rummet" + "Ta bort medlem och banna från att gå med i framtiden?" + "Tar bort %1$s …" + "Ta bort och banna medlem" + "Ta bara bort medlem" + "Avbanna" + "Denne kommer kunna gå med i rummet igen om denne bjuds in" + "Avbanna användare" + "Avbannar %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-tr/translations.xml b/features/roommembermoderation/impl/src/main/res/values-tr/translations.xml new file mode 100644 index 0000000000..beee8fa720 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-tr/translations.xml @@ -0,0 +1,18 @@ + + + "Üyeyi çıkar ve yasakla" + "Yasakla" + "Davet edilseler bile bu odaya tekrar katılamazlar." + "Bu üyeyi yasaklamak istediğinize emin misiniz?" + "Yasaklanıyor %1$s" + "Profili görüntüle" + "Odadan çıkar" + "Üyeyi çıkarın ve gelecekte katılmasını yasaklayın?" + "Kaldırılıyor %1$s…" + "Üyeyi çıkar ve yasakla" + "Yalnızca üyeyi kaldır" + "Yasağı Kaldır" + "Davet edildikleri takdirde bu odaya tekrar katılabileceklerdir." + "Kullanıcının yasağını kaldır" + "Yasak kaldırılıyor %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-uk/translations.xml b/features/roommembermoderation/impl/src/main/res/values-uk/translations.xml new file mode 100644 index 0000000000..d6ca0625a8 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-uk/translations.xml @@ -0,0 +1,21 @@ + + + "Вилучити й заблокувати учасника" + "Заблокувати" + "Він не зможе приєднатися до цієї кімнати знову, якщо його запросять." + "Ви точно хочете заблокувати цього користувача?" + "Блокування %1$s" + "Вилучити" + "Вони зможуть знову приєднатися до цієї кімнати, якщо їх запросять." + "Ви дійсно хочете вилучити цього учасника?" + "Переглянути профіль" + "Вилучити з кімнати" + "Вилучити учасника та заборонити приєднання в майбутньому?" + "Вилучення %1$s…" + "Вилучити й заблокувати учасника" + "Лише вилучити учасника" + "Розблокувати" + "Вони зможуть знову приєднатися до цієї кімнати, якщо їх запросять." + "Розблокувати користувача" + "Розблокування %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-zh-rTW/translations.xml b/features/roommembermoderation/impl/src/main/res/values-zh-rTW/translations.xml new file mode 100644 index 0000000000..6f1ab7d548 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-zh-rTW/translations.xml @@ -0,0 +1,21 @@ + + + "踢出並加入黑名單" + "加入黑名單" + "即使收到邀請,他們仍然無法加入聊天室。" + "您確定要將此成員加入黑名單?" + "正在將 %1$s 加入黑名單" + "移除" + "若收到邀請,他們可以再次加入此聊天室。" + "您真的想要移除此成員嗎?" + "查看個人檔案" + "踢出聊天室" + "移除成員並禁止未來再度加入?" + "正在踢出 %1$s…" + "踢出並加入黑名單" + "僅移除成員" + "解除黑名單" + "如果收到邀請,他們能再次加入聊天室。" + "解除黑名單" + "正在解除黑名單 %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-zh/translations.xml b/features/roommembermoderation/impl/src/main/res/values-zh/translations.xml new file mode 100644 index 0000000000..cf89b13e06 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-zh/translations.xml @@ -0,0 +1,21 @@ + + + "移除并封禁成员" + "封禁" + "即使受到邀请,他们也无法再次加入聊天室。" + "您确定要封禁该成员吗?" + "封禁 %1$s" + "移除" + "如果受到邀请,他们可以重新加入聊天室。" + "您确定要移除此成员吗?" + "查看个人资料" + "从聊天室移除" + "删除成员并禁止重新加入?" + "正在移除 %1$s……" + "移除并封禁成员" + "仅移除成员" + "取消封禁" + "如果受到邀请,他们可以重新加入聊天室。" + "解封用户" + "解除封禁 %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values/localazy.xml b/features/roommembermoderation/impl/src/main/res/values/localazy.xml new file mode 100644 index 0000000000..8e9b3defc1 --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values/localazy.xml @@ -0,0 +1,21 @@ + + + "Ban from room" + "Ban" + "They won’t be able to join this room again if invited." + "Are you sure you want to ban this member?" + "Banning %1$s" + "Remove" + "They will be able to join this room again if invited." + "Are you sure you want to remove this member?" + "View profile" + "Remove from room" + "Remove member and ban from joining in the future?" + "Removing %1$s…" + "Ban from room" + "Only remove member" + "Unban" + "They will be able to join this room again if invited." + "Unban user" + "Unbanning %1$s" + diff --git a/libraries/ui-strings/src/main/res/values-be/translations.xml b/libraries/ui-strings/src/main/res/values-be/translations.xml index 6448bfb974..51a60d788f 100644 --- a/libraries/ui-strings/src/main/res/values-be/translations.xml +++ b/libraries/ui-strings/src/main/res/values-be/translations.xml @@ -289,15 +289,6 @@ "Гэй, пагавары са мной у %1$s: %2$s" "%1$s Android" "Паведаміць аб памылцы з дапамогай Rageshake" - "Выдаліць і заблакіраваць удзельніка" - "Заблакіраваць" - "Яны не змогуць зноў далучыцца да гэтага пакоя, калі іх запросяць." - "Вы ўпэўнены, што хочаце заблакіраваць гэтага карыстальніка?" - "Блакіроўка %1$s" - "Прагляд профілю" - "Выдаліць удзельніка з пакоя" - "Выдаліць удзельніка і забараніць далучацца ў будучыні?" - "Выдаленне %1$s…" "Не ўдалося выбраць носьбіт, паўтарыце спробу." "Не атрымалася апрацаваць медыяфайл для загрузкі, паспрабуйце яшчэ раз." "Не атрымалася загрузіць медыяфайлы, паспрабуйце яшчэ раз." diff --git a/libraries/ui-strings/src/main/res/values-cs/translations.xml b/libraries/ui-strings/src/main/res/values-cs/translations.xml index 4d7409e7c1..01bb2d1519 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -343,18 +343,6 @@ Opravdu chcete pokračovat?" "Ahoj, ozvi se mi na %1$s: %2$s" "%1$s Android" "Zatřeste zařízením pro nahlášení chyby" - "Odebrat a vykázat člena" - "Vykázat" - "Nebudou se moci znovu připojit k této místnosti, pokud budou pozváni." - "Jste si jisti, že chcete vykázat tohoto člena?" - "Vykazování %1$s" - "Odebrat" - "Budou moci znovu vstoupit do této místnosti, pokud budou pozváni." - "Opravdu chcete tohoto člena odebrat?" - "Zobrazit profil" - "Odebrat z místnosti" - "Odebrat člena a zakázat mu připojení v budoucnu?" - "Odstraňování %1$s…" "Výběr média se nezdařil, zkuste to prosím znovu." "Titulky nemusí být viditelné pro lidi, kteří používají starší aplikace." "Nahrání média se nezdařilo, zkuste to prosím znovu." diff --git a/libraries/ui-strings/src/main/res/values-cy/translations.xml b/libraries/ui-strings/src/main/res/values-cy/translations.xml index 262e145296..6cda9da5ff 100644 --- a/libraries/ui-strings/src/main/res/values-cy/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cy/translations.xml @@ -355,18 +355,6 @@ Ydych chi\'n siŵr eich bod am barhau?" "Hei, siaradwch â mi ar %1$s: %2$s" "Android %1$s" "Rageshake i adrodd gwall" - "Gwahardd o ystafell" - "Atal" - "Fyddan nhw ddim yn gallu ymuno â\'r ystafell hon eto os cân nhw wahoddiad." - "Ydych chi\'n siŵr eich bod am wahardd yr aelod hwn?" - "Yn gwahardd %1$s" - "Tynnu" - "Fyddan nhw yn gallu ymuno â\'r ystafell hon eto os cân nhw wahoddiad." - "Ydych chi\'n siŵr eich bod am ddileu\'r aelod hwn?" - "Gweld proffil" - "Tynnu o\'r ystafell" - "Dileu aelod a\'u gwahardd rhag ymuno yn y dyfodol?" - "Wrthi\'n dileu %1$s…" "Wedi methu dewis cyfrwng, ceisiwch eto." "Efallai na fydd capsiynau yn weladwy i bobl sy\'n defnyddio apiau hŷn." "Wedi methu â phrosesu cyfryngau i\'w llwytho, ceisiwch eto." diff --git a/libraries/ui-strings/src/main/res/values-de/translations.xml b/libraries/ui-strings/src/main/res/values-de/translations.xml index 8945b8cd6b..451d4bc140 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -339,18 +339,6 @@ Möchten Sie wirklich fortfahren?" "Hey, sprich mit mir auf %1$s: %2$s" "%1$s Android" "Schüttel heftig zum Melden von Fehlern" - "Mitglied entfernen und sperren" - "Sperren" - "Sie können dem Raum nicht mehr beitreten, selbst wenn sie eingeladen werden." - "Bist du sicher, dass du dieses Mitglied sperren möchtest?" - "%1$s wird gesperrt." - "Entfernen" - "Sie können diesen Raum wieder betreten, wenn sie eingeladen werden." - "Möchten Sie dieses Mitglied wirklich entfernen?" - "Benutzerinformationen anzeigen" - "Mitglied entfernen" - "Mitglied entfernen und den erneuten Beitritt sperren?" - "%1$s wird entfernt." "Medienauswahl fehlgeschlagen, bitte versuche es erneut." "Bildunterschriften sind für Nutzer älterer Apps möglicherweise nicht sichtbar." "Fehler beim Verarbeiten des hochgeladenen Mediums. Bitte versuche es erneut." diff --git a/libraries/ui-strings/src/main/res/values-el/translations.xml b/libraries/ui-strings/src/main/res/values-el/translations.xml index 24a92cad85..7b7c4ea183 100644 --- a/libraries/ui-strings/src/main/res/values-el/translations.xml +++ b/libraries/ui-strings/src/main/res/values-el/translations.xml @@ -339,18 +339,6 @@ "Γεια, μίλα μου στην εφαρμογή %1$s :%2$s" "%1$s Android" "Κούνησε δυνατά τη συσκευή σου για να αναφέρεις κάποιο σφάλμα" - "Αφαίρεση και αποκλεισμός μέλους" - "Αποκλεισμός" - "Δεν θα μπορεί να συμμετέχει ξανά σε αυτό το δωμάτιο εάν προσκληθεί." - "Θες σίγουρα να αποκλείσεις αυτό το μέλος;" - "Αποκλεισμός %1$s" - "Αφαίρεση" - "Θα μπορούν να συμμετάσχουν ξανά σε αυτό το δωμάτιο εάν προσκληθούν." - "Είστε βέβαιοι ότι θέλετε να αφαιρέσετε αυτό το μέλος;" - "Προβολή προφίλ" - "Αφαίρεση από το δωμάτιο" - "Αφαίρεση μέλους και απαγόρευση συμμετοχής στο μέλλον;" - "Αφαίρεση %1$s…" "Αποτυχία επιλογής πολυμέσου, δοκίμασε ξανά." "Οι λεζάντες ενδέχεται να μην είναι ορατές σε άτομα που χρησιμοποιούν παλαιότερες εφαρμογές." "Αποτυχία μεταφόρτωσης μέσου, δοκίμασε ξανά." diff --git a/libraries/ui-strings/src/main/res/values-es/translations.xml b/libraries/ui-strings/src/main/res/values-es/translations.xml index 1cf59dacbf..66ffa2aee3 100644 --- a/libraries/ui-strings/src/main/res/values-es/translations.xml +++ b/libraries/ui-strings/src/main/res/values-es/translations.xml @@ -316,15 +316,6 @@ Motivo: %1$s." "Hola, puedes hablar conmigo en %1$s: %2$s" "%1$s Android" "Agitar con fuerza para informar de un error" - "Sacar y vetar a un miembro" - "Vetar" - "No podrán volver a unirse a esta sala si son invitados." - "¿Estás seguro de que quieres vetar a este miembro?" - "Vetando a %1$s" - "Ver perfil" - "Sacar de la sala" - "¿Sacar al miembro y prohibirle unirse en el futuro?" - "Eliminando %1$s…" "Error al seleccionar archivos multimedia, por favor inténtalo de nuevo." "Es posible que las leyendas no sean visibles para las personas que usan aplicaciones más antiguas." "Error al procesar el contenido multimedia, por favor inténtalo de nuevo." diff --git a/libraries/ui-strings/src/main/res/values-et/translations.xml b/libraries/ui-strings/src/main/res/values-et/translations.xml index 4d0bc5c422..e1e7f809c6 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -339,18 +339,6 @@ Kas sa oled kindel, et soovid jätkata?" "Hei, suhtle minuga %1$s võrgus: %2$s" "%1$s Android" "Veast teatamiseks raputa nutiseadet ägedalt" - "Eemalda ja sea suhtluskeeld" - "Sea suhtluskeeld" - "Ta ei saa selle jututoaga liituda isegi kutse olemasolul." - "Kas sa oled kindel, et soovid sellele kasutajale seada suhtluskeelu?" - "Seame kasutajale %1$s suhtluskeelu" - "Eemalda" - "Uue kutse saamisel on tal võimalik selle jututoaga uuesti liituda." - "Kas sa oled kindel, et soovid selle osaleja eemaldada?" - "Vaata profiili" - "Eemalda kasutaja jututoast" - "Kas eemaldama kasutaja ja seame talle tulevikuks suhtluskeelu?" - "Eemaldame kasutajat %1$s…" "Meediafaili valimine ei õnnestunud. Palun proovi uuesti." "Selgitused ja alapealkirjad ei pruugi olla nähtavad vanemate rakenduste kasutajatele." "Meediafaili töötlemine enne üleslaadimist ei õnnestunud. Palun proovi uuesti." diff --git a/libraries/ui-strings/src/main/res/values-eu/translations.xml b/libraries/ui-strings/src/main/res/values-eu/translations.xml index e43f2d24f7..73d10a27e1 100644 --- a/libraries/ui-strings/src/main/res/values-eu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-eu/translations.xml @@ -312,14 +312,6 @@ Arrazoia: %1$s." "🔐️ Zatoz nirekin %1$s(e)ra" "%1$s Android" "Astindu erroreen berri emateko" - "Kendu kidea eta ezarri debekua" - "Ezarri debekua" - "Ziur kide honi debekua ezarri nahi diozula?" - "%1$s(r)i debekua ezartzen" - "Ikusi profila" - "Kendu gelatik" - "Kidea kendu eta etorkizunean sartzea debekatu?" - "%1$s kentzen…" "Huts egin du multimedia aukeratzeak, saiatu berriro." "Huts egin du multimedia igotzeak, saiatu berriro." "Finkatutako mezuak" diff --git a/libraries/ui-strings/src/main/res/values-fa/translations.xml b/libraries/ui-strings/src/main/res/values-fa/translations.xml index 50f98c1a19..4fb5ceea2d 100644 --- a/libraries/ui-strings/src/main/res/values-fa/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fa/translations.xml @@ -310,18 +310,6 @@ "🔐️ پییوستن به من روی %1$s" "درود. با من روی %1$s صحبت کن: %2$s" "%1$s اندروید" - "برداشت و تحریم عضو" - "تحریم" - "در صورت دعوت نمی‌تواند دوباره به اتاق بپیوندد." - "مطمئنید می‌خواهید این عضو را تحریم کنید؟" - "تحریم کردن %1$s" - "برداشتن" - "در صورت دعوت می‌تواند دوباره به اتاق بپیوندد." - "مطمئنید می‌خواهید این عضو را بردارید؟" - "دیدن نمایه" - "برداشتن از اتاق" - "برداشتن عضو و تحریم پیوستن در آینده؟" - "برداشتن %1$s…" "گزینش رسانه شکست خورد. لطفاً دوباره تلاش کنید." "پردازش رسانه برای بارگذاری شکست خورد. لطفاً دوباره تلاش کنید." "بارگذاری رسانه شکست خورد. لطفاً دوباره تلاش کنید." diff --git a/libraries/ui-strings/src/main/res/values-fi/translations.xml b/libraries/ui-strings/src/main/res/values-fi/translations.xml index 293b3a49e2..5dd5b6b3b2 100644 --- a/libraries/ui-strings/src/main/res/values-fi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fi/translations.xml @@ -339,18 +339,6 @@ Haluatko varmasti jatkaa?" "Hei, keskustele kanssani %1$s -sovelluksessa: %2$s" "%1$s Android" "Raivostunut ravistaminen ilmoittaa virheestä" - "Poista jäsen huoneesta ja anna porttikielto" - "Anna porttikielto" - "He eivät voi enää liittyä tähän huoneeseen, jos heidät kutsutaan." - "Haluatko varmasti antaa tälle jäsenelle porttikiellon?" - "Annetaan porttikieltoa käyttäjälle %1$s" - "Poista" - "He voivat liittyä tähän huoneeseen uudelleen, jos heidät kutsutaan." - "Haluatko varmasti poistaa tämän jäsenen?" - "Näytä profiili" - "Poista huoneesta" - "Poistetaanko jäsen huoneesta ja kielletäänkö heitä liittymästä tulevaisuudessa?" - "Poistetaan käyttäjää %1$s huoneesta…" "Median valinta epäonnistui, yritä uudelleen." "Kuvatekstit eivät välttämättä näy ihmisille, jotka käyttävät vanhempia sovelluksia." "Median käsittely epäonnistui, yritä uudelleen." diff --git a/libraries/ui-strings/src/main/res/values-fr/translations.xml b/libraries/ui-strings/src/main/res/values-fr/translations.xml index 27cac31aa0..1171f32df8 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -339,18 +339,6 @@ Raison : %1$s." "Salut, parle-moi sur %1$s : %2$s" "%1$s Android" "Rageshake pour signaler un problème" - "Retirer et bannir ce membre" - "Bannir" - "Il ne pourra pas rejoindre le salon à nouveau, même si il est invité." - "Êtes-vous certain de vouloir bannir ce membre ?" - "Bannissement de %1$s" - "Retirer" - "Cet utilisateur pourra rejoindre le salon à nouveau si il est invité." - "Voulez-vous vraiment supprimer ce membre ?" - "Voir le profil" - "Retirer le membre du salon" - "Retirer le membre et interdire l’adhésion à l’avenir ?" - "Enlever %1$s…" "Échec de la sélection du média, veuillez réessayer." "Les légendes peuvent ne pas être visibles pour les utilisateurs d’anciennes applications." "Échec du traitement des médias à télécharger, veuillez réessayer." diff --git a/libraries/ui-strings/src/main/res/values-hu/translations.xml b/libraries/ui-strings/src/main/res/values-hu/translations.xml index d304030e00..2704f8796b 100644 --- a/libraries/ui-strings/src/main/res/values-hu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml @@ -339,18 +339,6 @@ Biztos, hogy folytatja?" "Beszélgessünk itt: %1$s, %2$s" "%1$s Android" "Az eszköz rázása a hibajelentéshez" - "Eltávolítás és a tag kitiltása" - "Kitiltás" - "Többé nem csatlakozhat ehhez a szobához, akkor sem, ha meghívják." - "Biztos, hogy kitiltja ezt a tagot?" - "%1$s kitiltása" - "Eltávolítás" - "Ehhez a szobához is csatlakozhat, ha meghívják." - "Biztos, hogy eltávolítja ezt a tagot?" - "Profil megtekintése" - "Eltávolítás a szobából" - "Eltávolítja a tagot, és megtiltja a jövőbeni csatlakozást?" - "%1$s eltávolítása…" "Nem sikerült kiválasztani a médiát, próbálja újra." "Előfordulhat, hogy a feliratok nem láthatók a régebbi alkalmazásokat használók számára." "Nem sikerült feldolgozni a feltöltendő médiát, próbálja újra." diff --git a/libraries/ui-strings/src/main/res/values-in/translations.xml b/libraries/ui-strings/src/main/res/values-in/translations.xml index c32ce5f730..cec28f2ad4 100644 --- a/libraries/ui-strings/src/main/res/values-in/translations.xml +++ b/libraries/ui-strings/src/main/res/values-in/translations.xml @@ -304,15 +304,6 @@ Alasan: %1$s." "Hai, bicaralah dengan saya di %1$s: %2$s" "%1$s Android" "Rageshake untuk melaporkan kutu" - "Keluarkan dan cekal anggota" - "Cekal" - "Mereka tidak akan dapat bergabung ke ruangan ini lagi jika diundang." - "Apakah Anda yakin ingin mencekal anggota ini?" - "Mencekal %1$s" - "Tampilkan profil" - "Keluarkan dari ruangan" - "Keluarkan pengguna dan cekal pengguna bergabung lagi di masa mendatang?" - "Mengeluarkan %1$s…" "Gagal memilih media, silakan coba lagi." "Keterangan mungkin tidak terlihat oleh orang yang menggunakan aplikasi lama." "Gagal memproses media untuk diunggah, silakan coba lagi." diff --git a/libraries/ui-strings/src/main/res/values-it/translations.xml b/libraries/ui-strings/src/main/res/values-it/translations.xml index e9864e090d..bf11478b9e 100644 --- a/libraries/ui-strings/src/main/res/values-it/translations.xml +++ b/libraries/ui-strings/src/main/res/values-it/translations.xml @@ -326,15 +326,6 @@ Sei sicuro di voler continuare?" "Ehi, parliamo su %1$s: %2$s" "%1$s Android" "Scuoti per segnalare un problema" - "Rimuovi ed escludi" - "Escludi" - "Non potrà entrare nuovamente in questa stanza se invitato." - "Vuoi davvero escludere questo membro?" - "Esclusione di %1$s" - "Visualizza profilo" - "Rimuovi dalla stanza" - "Rimuovere e vietare l\'accesso in futuro?" - "Rimozione di %1$s…" "Selezione del file multimediale fallita, riprova." "Le didascalie potrebbero non essere visibili agli utenti di app meno recenti." "Elaborazione del file multimediale da caricare fallita, riprova." diff --git a/libraries/ui-strings/src/main/res/values-ka/translations.xml b/libraries/ui-strings/src/main/res/values-ka/translations.xml index 0405aa6235..88bd672c82 100644 --- a/libraries/ui-strings/src/main/res/values-ka/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ka/translations.xml @@ -247,15 +247,6 @@ "გაგიმარჯოს! მესაუბრე %1$s-ზე: %2$s" "%1$s Android" "შეცდომის შესატყობინებლად ტელეფონის შენჯღრევა" - "წევრის წაშლა და დაბლოკვა" - "დაბლოკვა" - "მოწვევის შემთხვევაში ამ ოთახში კვლავ გაწევრიანებას ვერ შეძლებენ." - "დარწმუნებული ხართ, რომ ამ წევრის დაბლოკვა გსურთ?" - "%1$s-ს დაბლოკვა" - "პროფილის ნახვა" - "ოთახიდან გაგდება" - "გსურთ წევრის გაგდება და მომავალში გაწევრიანების აკრძალვა?" - "%1$s-ს გაგდება…" "მედიის შერჩევა ვერ მოხერხდა, გთხოვთ, სცადოთ ხელახლა." "მედიის ატვირთვა ვერ მოხერხდა. გთხოვთ, სცადოთ ხელახლა." "მედიის ატვირთვა ვერ მოხერხდა, გთხოვთ, სცადოთ ხელახლა." diff --git a/libraries/ui-strings/src/main/res/values-nb/translations.xml b/libraries/ui-strings/src/main/res/values-nb/translations.xml index ce8d655b6a..df9d892f14 100644 --- a/libraries/ui-strings/src/main/res/values-nb/translations.xml +++ b/libraries/ui-strings/src/main/res/values-nb/translations.xml @@ -339,18 +339,6 @@ Er du sikker på at du vil fortsette?" "Hei, snakk med meg på %1$s: %2$s" "%1$s Android" "Rageshake for å rapportere feil" - "Fjern og utesteng medlem" - "Utesteng" - "De vil ikke kunne bli med i dette rommet igjen hvis de blir invitert." - "Er du sikker på at du vil utestenge dette medlemmet?" - "Utestenger %1$s" - "Fjern" - "De vil kunne bli med i dette rommet igjen hvis de blir invitert." - "Er du sikker på at du vil fjerne dette medlemmet?" - "Vis profil" - "Fjern fra rommet" - "Fjerne medlem og utestenge fra å bli med i fremtiden?" - "Fjerner %1$s…" "Kunne ikke velge medium, prøv igjen." "Teksting er kanskje ikke synlig for personer som bruker eldre apper." "Kunne ikke behandle medier for opplasting, vennligst prøv igjen." diff --git a/libraries/ui-strings/src/main/res/values-nl/translations.xml b/libraries/ui-strings/src/main/res/values-nl/translations.xml index 0ad734232f..290720da86 100644 --- a/libraries/ui-strings/src/main/res/values-nl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-nl/translations.xml @@ -292,15 +292,6 @@ Reden: %1$s." "Hé, praat met me op %1$s: %2$s" "%1$s Android" "Schudden om een bug te melden" - "Lid verwijderen en verbannen" - "Verbannen" - "Ze kunnen niet meer toetreden tot deze kamer als ze worden uitgenodigd." - "Weet je zeker dat je dit lid wilt verbannen?" - "%1$s verbannen" - "Profiel bekijken" - "Verwijderen uit kamer" - "Lid verwijderen en toekomstige deelname verbieden?" - "%1$s wordt verwijderd…" "Het selecteren van media is mislukt. Probeer het opnieuw." "Het verwerken van media voor uploaden is mislukt. Probeer het opnieuw." "Het uploaden van media is mislukt. Probeer het opnieuw." diff --git a/libraries/ui-strings/src/main/res/values-pl/translations.xml b/libraries/ui-strings/src/main/res/values-pl/translations.xml index e3e742072a..4d0941fcb1 100644 --- a/libraries/ui-strings/src/main/res/values-pl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pl/translations.xml @@ -343,18 +343,6 @@ Czy na pewno chcesz kontynuować?" "Hej, porozmawiajmy na %1$s: %2$s" "%1$s Android" "Wstrząśnij gniewnie, aby zgłosić błąd" - "Usuń i zbanuj członka" - "Zbanuj" - "Nie będą mogli ponownie dołączyć do tego pokoju, jeśli zostaną zaproszeni." - "Czy na pewno chcesz zbanować tego członka?" - "Banowanie %1$s" - "Usuń" - "Będą mogli ponownie dołączyć do pokoju, jeśli zostaną zaproszeni." - "Czy na pewno chcesz usunąć tego członka?" - "Wyświetl profil" - "Usuń z pokoju" - "Usunąć członka i zablokować możliwość dołączenia w przyszłości?" - "Usuwanie %1$s…" "Nie udało się wybrać multimediów. Spróbuj ponownie." "Opis może być niedostępny dla osób korzystających ze starszej wersji aplikacji." "Przetwarzanie multimediów do przesłania nie powiodło się, spróbuj ponownie." diff --git a/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml b/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml index b654dd355b..12df92cca6 100644 --- a/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml @@ -287,15 +287,6 @@ "Ei, fale comigo em %1$s: %2$s" "%1$s Android" "Rageshake para relatar um bug" - "Remover e banir membro" - "Banir" - "Eles não poderão entrar nesta sala novamente se forem convidados." - "Tem certeza de que quer banir este membro?" - "Banindo %1$s" - "Ver perfil" - "Remover da sala" - "Remover membro e banir de entrar novamente no futuro?" - "Removendo %1$s…" "Falha ao selecionar a mídia, tente novamente." "Falha ao processar mídia para upload. Tente novamente." "Falha ao enviar mídia. Tente novamente." diff --git a/libraries/ui-strings/src/main/res/values-pt/translations.xml b/libraries/ui-strings/src/main/res/values-pt/translations.xml index 24fa3d7e35..696de1e319 100644 --- a/libraries/ui-strings/src/main/res/values-pt/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pt/translations.xml @@ -324,16 +324,6 @@ Tens a certeza de que queres continuar?" "Alô! Fala comigo na %1$s: %2$s" "%1$s Android" "Agita o dispositivo em fúria para comunicar um problema" - "Remover e banir participante" - "Banir" - "Não poderão voltar a entrar nesta sala, mesmo se forem convidados." - "Tens a certeza que queres banir este participante?" - "A banir %1$s" - "Poderão entrar na sala novamente se convidados." - "Ver perfil" - "Remover da sala" - "Remover participante e proibir que entre no futuro?" - "A remover %1$s…" "Falha ao selecionar multimédia, por favor tente novamente." "As legendas poderão não ser visíveis em versões mais antigas da aplicação." "Falha ao processar multimédia para carregamento, por favor tente novamente." diff --git a/libraries/ui-strings/src/main/res/values-ro/translations.xml b/libraries/ui-strings/src/main/res/values-ro/translations.xml index 13a63c3ba9..98d849ce1b 100644 --- a/libraries/ui-strings/src/main/res/values-ro/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ro/translations.xml @@ -294,15 +294,6 @@ Motiv:%1$s." "Hei, vorbește cu mine pe %1$s: %2$s" "%1$s Android" "Rageshake pentru a raporta erori" - "Eliminați și interziceți membrul" - "Interzicere" - "Nu se vor putea alătura din nou acestei camere dacă sunt invitați." - "Sunteți sigur că doriți să interziceți acest membru?" - "Se interzice %1$s" - "Vizualizare profil" - "Înlăturați membrul" - "Înlăturați membrul și interziceți-i să se alăture în viitor?" - "Se elimină %1$s" "Selectarea fișierelor media a eșuat, încercați din nou." "Procesarea datelor media a eșuat, vă rugăm să încercați din nou." "Încărcarea fișierelor media a eșuat, încercați din nou." diff --git a/libraries/ui-strings/src/main/res/values-ru/translations.xml b/libraries/ui-strings/src/main/res/values-ru/translations.xml index 1b67806b09..7329755b34 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -343,17 +343,6 @@ "Привет, поговори со мной по %1$s: %2$s" "%1$s Android" "Встряхните устройство, чтобы сообщить об ошибке" - "Удалить и заблокировать участника" - "Заблокировать" - "Они не смогут снова присоединиться к этой комнате, если их пригласят." - "Вы уверены, что хотите заблокировать этого участника?" - "Блокировка %1$s" - "Удалить" - "Вы действительно хотите удалить этого участника?" - "Посмотреть профиль" - "Удалить участника из комнаты" - "Удалить участника и запретить присоединяться в будущем?" - "Удаление %1$s…" "Не удалось выбрать носитель, попробуйте еще раз." "Подпись может быть не видна пользователям старых приложений." "Не удалось обработать медиафайл для загрузки, попробуйте еще раз." diff --git a/libraries/ui-strings/src/main/res/values-sk/translations.xml b/libraries/ui-strings/src/main/res/values-sk/translations.xml index 7c4302db9a..cffde3494a 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -343,18 +343,6 @@ Naozaj chcete pokračovať?" "Ahoj, porozprávajte sa so mnou na %1$s: %2$s" "%1$s Android" "Zúrivo potriasť pre nahlásenie chyby" - "Odstrániť a zakázať člena" - "Zakázať" - "Nebudú sa môcť pripojiť k tejto miestnosti znova ani ak budú pozvaní." - "Ste si istý, že chcete zakázať tohto člena?" - "Zakazuje sa %1$s" - "Odstrániť" - "V prípade pozvania sa budú môcť znova pripojiť k tejto miestnosti." - "Ste si istý, že chcete odstrániť tohto člena?" - "Zobraziť profil" - "Odstrániť z miestnosti" - "Odstrániť člena a zakázať vstup v budúcnosti?" - "Odstraňuje sa %1$s…" "Nepodarilo sa vybrať médium, skúste to prosím znova." "Titulky nemusia byť viditeľné pre ľudí používajúcich staršie aplikácie." "Nepodarilo sa spracovať médiá na odoslanie, skúste to prosím znova." diff --git a/libraries/ui-strings/src/main/res/values-sv/translations.xml b/libraries/ui-strings/src/main/res/values-sv/translations.xml index 0fda3671c3..098226a069 100644 --- a/libraries/ui-strings/src/main/res/values-sv/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sv/translations.xml @@ -339,18 +339,6 @@ Anledning:%1$s." "Hallå, prata med mig på %1$s: %2$s" "%1$s Android" "Raseriskaka för att rapportera bugg" - "Ta bort och banna medlem" - "Banna" - "Denne kommer inte att kunna gå med i det här rummet igen om denne bjuds in." - "Är du säker på att du vill banna den här medlemmen?" - "Bannar %1$s" - "Ta bort" - "Denne kommer kunna gå med i rummet igen om denne bjuds in" - "Är du säker på att du vill ta bort den här medlemmen?" - "Visa profil" - "Ta bort från rummet" - "Ta bort medlem och banna från att gå med i framtiden?" - "Tar bort %1$s …" "Misslyckades att välja media, vänligen pröva igen." "Bildtexter kanske inte är synliga för personer som använder äldre appar." "Misslyckades att bearbeta media för uppladdning, vänligen pröva igen." diff --git a/libraries/ui-strings/src/main/res/values-tr/translations.xml b/libraries/ui-strings/src/main/res/values-tr/translations.xml index 16766f12af..46f87e2019 100644 --- a/libraries/ui-strings/src/main/res/values-tr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-tr/translations.xml @@ -316,15 +316,6 @@ Neden: %1$s." "Hey, benimle konuş %1$s: %2$s" "%1$s Android" "Hata bildirmek için Rageshake" - "Üyeyi çıkar ve yasakla" - "Yasakla" - "Davet edilseler bile bu odaya tekrar katılamazlar." - "Bu üyeyi yasaklamak istediğinize emin misiniz?" - "Yasaklanıyor %1$s" - "Profili görüntüle" - "Odadan çıkar" - "Üyeyi çıkarın ve gelecekte katılmasını yasaklayın?" - "Kaldırılıyor %1$s…" "Medya seçilemedi, lütfen tekrar deneyin." "Açıklamalar, eski uygulamaları kullanan kişiler tarafından görülemeyebilir." "Medya yüklenemedi, lütfen tekrar deneyin." diff --git a/libraries/ui-strings/src/main/res/values-uk/translations.xml b/libraries/ui-strings/src/main/res/values-uk/translations.xml index f8a233d183..141a65850c 100644 --- a/libraries/ui-strings/src/main/res/values-uk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uk/translations.xml @@ -343,18 +343,6 @@ "Вітаю, поспілкуйтеся зі мною в %1$s: %2$s" "%1$s Android" "Повідомити про ваду за допомогою Rageshake" - "Вилучити й заблокувати учасника" - "Заблокувати" - "Він не зможе приєднатися до цієї кімнати знову, якщо його запросять." - "Ви точно хочете заблокувати цього користувача?" - "Блокування %1$s" - "Вилучити" - "Вони зможуть знову приєднатися до цієї кімнати, якщо їх запросять." - "Ви дійсно хочете вилучити цього учасника?" - "Переглянути профіль" - "Вилучити з кімнати" - "Вилучити учасника та заборонити приєднання в майбутньому?" - "Вилучення %1$s…" "Не вдалося вибрати медіафайл, спробуйте ще раз." "Користувачі старих застосунків можуть не бачити підписи." "Не вдалося обробити медіафайл для завантаження, спробуйте ще раз." diff --git a/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml b/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml index ec0c7be7b6..8986bf6e79 100644 --- a/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml @@ -333,18 +333,6 @@ "嘿,來 %1$s 和我聊天:%2$s" "%1$s Android" "憤怒搖晃以回報臭蟲" - "踢出並加入黑名單" - "加入黑名單" - "即使收到邀請,他們仍然無法加入聊天室。" - "您確定要將此成員加入黑名單?" - "正在將 %1$s 加入黑名單" - "移除" - "若收到邀請,他們可以再次加入此聊天室。" - "您真的想要移除此成員嗎?" - "查看個人檔案" - "踢出聊天室" - "移除成員並禁止未來再度加入?" - "正在踢出 %1$s…" "選取媒體失敗,請再試一次。" "使用舊應用程式的使用者可能看不到標題。" "無法處理要上傳的媒體,請再試一次。" diff --git a/libraries/ui-strings/src/main/res/values-zh/translations.xml b/libraries/ui-strings/src/main/res/values-zh/translations.xml index cd7cd61f9b..50eaf02824 100644 --- a/libraries/ui-strings/src/main/res/values-zh/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh/translations.xml @@ -327,18 +327,6 @@ "嗨!请通过 %1$s 与我联系:%2$s" "%1$s Android" "摇一摇以报错" - "移除并封禁成员" - "封禁" - "即使受到邀请,他们也无法再次加入聊天室。" - "您确定要封禁该成员吗?" - "封禁 %1$s" - "移除" - "如果受到邀请,他们可以重新加入聊天室。" - "您确定要移除此成员吗?" - "查看个人资料" - "从聊天室移除" - "删除成员并禁止重新加入?" - "正在移除 %1$s……" "选择媒体失败,请重试。" "使用旧版应用程序的用户可能无法看到字幕。" "处理要上传的媒体失败,请重试。" diff --git a/tools/localazy/config.json b/tools/localazy/config.json index e5d35def0c..51db790fd8 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -325,6 +325,14 @@ "includeRegex" : [ "screen\\.report_room\\..*" ] + }, + { + "name" : ":features:roommembermoderation:impl", + "includeRegex" : [ + "screen\\.bottom_sheet\\.manage_room_member\\..*", + "screen_room_member_list_manage_member.*", + "screen_room_member_list_unbanning_user" + ] } ] }